分布式基础篇
1 项目简介
1.1 项目背景
1.2 电商模式
市面上有5种常见的电商模式 B2B、B2C、C2B、C2C、O2O
1.2.1 B2B 模式
B2B(Business to Business),是指商家和商家建立的商业关系,如阿里巴巴
1.2.2 B2C 模式
B2C(Business to Consumer) 就是我们经常看到的供应商直接把商品买个用户,即 “商对客” 模式,也就是我们呢说的商业零售,直接面向消费销售产品和服务,如苏宁易购,京东,天猫,小米商城
1.2.3 C2B 模式
C2B (Customer to Business),即消费者对企业,先有消费者需求产生而后有企业生产,即先有消费者提出需求,后又生产企业按需求组织生产
1.2.4 C2C 模式
C2C (Customer to Consumer) 客户之间把自己的东西放到网上去卖 。如淘宝、咸鱼
1.2.5 O2O 模式
O2O 即 Online To Offline,也即将线下商务的机会与互联网结合在一起,让互联网成为线上交易前台,线上快速支付,线上优质服务,如:饿了么,美团,淘票票,京东到家
1.3 谷粒商城
谷粒商城是一个B2C模式的电商平台,销售自营商品给客户
1.4 项目架构图
1.4.1 项目微服务架构图
前后分离开发,分为内网部署和外网部署,外网是面向公众访问的。访问前端项目,可以有手机APP,电脑网页;内网部署的是后端集群,前端在页面上操作发送请求到后端,在这途中会经过Nginx集群,Nginx把请求转交给API网关(springcloud gateway)(网关可以根据当前请求动态地路由到指定的服务,看当前请求是想调用商品服务还是购物车服务还是检索服务),从路由过来如果请求很多,可以负载均衡地调用商品服务器中一台(商品服务复制了多份),当商品服务器出现问题也可以在网关层面对服务进行熔断或降级(使用阿里的sentinel组件),网关还有其他的功能如认证授权、限流(只放行部分到服务器)等。到达服务器后进行处理(springboot为微服务),服务与服务可能会相互调用(使用feign组件),有些请求可能经过登录才能进行(基于OAuth2.0的认证中心。安全和权限使用springSecurity控制)服务可能保存了一些数据或者需要使用缓存,我们使用redis集群(分片+哨兵集群)。持久化使用mysql,读写分离和分库分表。服务和服务之间会使用消息队列(RabbitMQ),来完成异步解耦,分布式事务的一致性。有些服务可能需要全文检索,检索商品信息,使用ElaticSearch。服务可能需要存取数据,使用阿里云的对象存储服务OSS。项目上线后为了快速定位问题,使用ELK对日志进行处理,使用LogStash收集业务里的各种日志,把日志存储到ES中,用Kibana可视化页面从ES中检索出相关信息,帮助我们快速定位问题所在。在分布式系统中,由于我们每个服务都可能部署在很多台机器,服务和服务可能相互调用,就得知道彼此都在哪里,所以需要将所有服务都注册到注册中心。服务从注册中心发现其他服务所在位置(使用阿里Nacos作为注册中心)。每个服务的配置众多,为了实现改一处配置相同配置就同步更改,就需要配置中心,也使用阿里的Nacos,服务从配置中心中动态取配置。服务追踪,追踪服务调用链哪里出现问题,使用springcloud提供的Sleuth、Zipkin、Metrics,把每个服务的信息交给开源的Prometheus进行聚合分析,再由Grafana进行可视化展示,提供Prometheus提供的AlterManager实时得到服务的警告信息,以短信/邮件的方式告知服务开发人员。还提供了持续集成和持续部署。项目发布起来后,因为微服务众多,每一个都打包部署到服务器太麻烦,有了持续集成后开发人员可以将修改后的代码提交到github,运维人员可以通过自动化工具Jenkins Pipeline将github中获取的代码打包成docker镜像,最终是由k8s集成docker服务,将服务以docker容器的方式运行。
1.4.2 微服务划分图
反映了需要创建的微服务以及相关技术。前后分离开发。前端项目分为admin-vue(工作人员使用的后台管理系统)、shop-vue(面向公众访问的web网站)、app(公众)、小程序(公众)商品服务:商品的增删改查、商品的上下架、商品详情支付服务优惠服务用户服务:用户的个人中心、收货地址仓储服务:商品的库存秒杀服务订单服务:订单增删改查检索服务:商品的检索ES中央认证服务:登录、注册、单点登录、社交登录购物车服务后台管理系统:添加优惠信息等
1.5 项目技术&特色
前后分离开发,并开发基于vue的后台管理系统SpringCloud全新的解决方案应用监控、限流、网关、熔断降级等分布式方案,全方位涉及透彻讲解分布式事务,分布式锁等分布式系统的难点压力测试与性能优化各种集群技术的区别以及使用CI/CD 使用
1.6 项目前置要求
1.6.1 学习项目的前置知识
熟悉SpringBoot以及常见整合方案了解SpringCloud熟悉 gitmaven熟悉 linux redis docker 基本操作了解 html,css,js,vue熟练使用idea开发项目
2 分布式基础概念
2.1 微服务
微服务架构风格,就像是把一个单独的应用程序开发成一套小服务,每个小服务运行在自己的进程中,并使用轻量级机制通信,通常是 HTTP API 这些服务围绕业务能力来构建,并通过完全自动化部署机制来独立部署,这些服务使用不同的编程语言书写,以及不同数据存储技术,并保持最低限度的集中式管理简而言之,拒绝大型单体应用,基于业务边界进行服务微化拆分,每个服务独立部署运行。
2.2 集群&分布式&节点
集群是个物理状态,分布式是个工作方式只要是一堆机器,也可以叫做集群,他们是不是一起协作干活,这谁也不知道。《分布式系统原理与范型》定义:分布式系统是若干独立计算机的集合,这些计算机对于用户来说像单个系统分布式系统 (distributed system) 是建立网络之上的软件系统分布式是指根据不同的业务分布在不同的地方集群指的是将几台服务器集中在一起,实现同一业务例如:京东是一个分布式系统,众多业务运行在不同的机器上,所有业务构成一个大型的分布式业务集群,每一个小的业务,比如用户系统,访问压力大的时候一台服务器是不够的,我们就应该将用户系统部署到多个服务器,也就是每一个业务系统也可以做集群化分布式中的每一个节点,都可以做集群,而集群并不一定就是分布式的节点:集群中的一个服务器
2.3 远程调用
在分布式系统中,各个服务可能处于不同主机,但是服务之间不可避免的需要互相调用,我们称之为远程调用SpringCloud中使用HTTP+JSON的方式来完成远程调用
2.4 负载均衡
分布式系统中,A 服务需要调用B服务,B服务在多台机器中都存在, A调用任意一个服务器均可完成功能为了使每一个服务器都不要太或者太闲,我们可以负载均衡调用每一个服务器,提升网站的健壮性常见的负载均衡算法:轮询:为第一个请求选择健康池中的每一个后端服务器,然后按顺序往后依次选择,直到最后一个,然后循环最小连接:优先选择链接数最少,也就是压力最小的后端服务器,在会话较长的情况下可以考虑采取这种方式
2.5 服务注册/发现&注册中心
A服务调用B服务,A服务不知道B服务当前在哪几台服务器上有,哪些正常的,哪些服务已经下线,解决这个问题可以引入注册中心
如果某些服务下线,我们其他人可以实时的感知到其他服务的状态,从而避免调用不可用的服务
2.6 配置中心
每一个服务最终都有大量配置,并且每个服务都可能部署在多个服务器上,我们经常需要变更配置,我们可以让每个服务在配置中心获取自己的配置。配置中心用来集中管理微服务的配置信息
2.7 服务熔断&服务降级
在微服务架构中,微服务之间通过网络来进行通信,存在相互依赖,当其中一个服务不可用时,有可能会造成雪崩效应,要防止这种情况,必须要有容错机制来保护服务
rpc情景:订单服务 --> 商品服务 --> 库存服务库存服务出现故障导致响应慢,导致商品服务需要等待,可能等到10s后库存服务才能响应。库存服务的不可用导致商品服务阻塞,商品服务等的期间,订单服务也处于阻塞。一个服务不可用导致整个服务链都阻塞。如果是高并发,第一个请求调用后阻塞10s得不到结果,第二个请求直接阻塞10s。更多的请求进来导致请求积压,全部阻塞,最终服务器的资源耗尽。导致雪崩1、服务熔断设置服务的超时,当被调用的服务经常失败到达某个阈值,我们可以开启断路保护机制,后来的请求不再去调用这个服务,本地直接返回默认的数据2、服务降级在运维期间,当系统处于高峰期,系统资源紧张,我们可以让非核心业务降级运行,降级:某些服务不处理,或者简单处理【抛异常,返回NULL,调用 Mock数据,调用 FallBack 处理逻辑】
2.8 API 网关
在微服务架构中,API Gateway 作为整体架构的重要组件,抽象服务中需要的公共功能,同时它提供了客户端负载均衡,服务自动熔断,灰度发布,统一认证,限流监控,日志统计等丰富功能,帮助我们解决很多API管理的难题
3 环境搭建
3.1 安装jdk1.8
1 下载并解压jdk1.8tar-zxvfjdk-8u281-linux-x64.tar.gz(检查本机有没有jdk有的话卸载掉。安装上自己的jdk)2 配上环境变量vim /etc/profile# 添加一下两行代码export JAVA_HOME=jdk的位置export PATH=$PATH:$JAVA_HOME/bin3 使配置生效source/etc/profile
3.2 安装docker(CentOS)
1 卸载系统之前的docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine2设置存储库sudo yum install -y yum-utilssudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo3安装DOCKER引擎sudo yum install docker-ce docker-ce-cli containerd.io4启动Docker.sudo systemctl start docker5 配置镜像加速sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{"registry-mirrors": ["https://chqac97z.mirror.aliyuncs.com"]}EOFsudo systemctl daemon-reloadsudo systemctl restart docker
3.3 安装mysql
1 拉去mysql镜像sudo docker pull mysql:8.02 启动mysql容器# --name指定容器名字 -v目录挂载 -p指定端口映射-e设置mysql参数 -d后台运行sudo docker run --name mysql -v /usr/local/mysql/data:/var/lib/mysql -v /usr/local/mysql:/etc/mysql/conf.d -v /usr/local/mysql/log:/var/log/mysql-e MYSQL_ROOT_PASSWORD=root-p 3306:3306 -d mysql:8.03 使用su - root(切换为root,这样就不用每次都sudo来赐予了)su - root4 进入mysql容器docker exec -it 容器名称|容器id bin/bash
3.4 安装redis
1 在docker hub搜索redis镜像docker search redis2 拉取redis镜像到本地docker pull redis:6.0.103 修改需要自定义的配置(docker-redis默认没有配置文件,自己在宿主机建立后挂载映射)创建并修改/usr/local/redis/redis.confbind 0.0.0.0 开启远程权限appendonly yes 开启aof持久化4 启动redis服务运行容器docker run --name redis-v /usr/local/redis/data:/data-v /usr/local/redis/redis.conf:/usr/local/etc/redis/redis.conf -p 6379:6379 -d redis:6.0.10redis-server /usr/local/etc/redis/redis.conf 解释: -v /usr/local/redis/data:/data# 将数据目录挂在到本地保证数据安全 -v /root/redis/redis.conf:/usr/local/etc/redis/redis.conf # 将配置文件挂在到本地修改方便 5直接进去redis客户端。docker exec -it redis redis-cli
3.5 Maven
在maven配置文件配置配置阿里云镜像nexus-aliyuncentralNexus aliyunhttp://maven.aliyun.com/nexus/content/groups/public配置 jdk 1.8 编译项目jdk-1.8true1.81.81.81.8
3.6 安装开发插件(可选-方便开发)
vscodeAuto Close TagAuto Rename Tag Chinese ESlint HTML CSS SupportHTML SnippetsJavaScript (ES6) code snippetsLive Serveropen in browerVeturidealombok、mybatisx
3.7 安装git
# 配置用户名git config --global user.name "username"//(名字,随意写)# 配置邮箱git config --global user.email "55333@qq.com" // 注册账号时使用的邮箱# 配置ssh免密登录ssh-keygen -t rsa -C "55333@qq.com"三次回车后生成了密钥,也可以查看密钥cat ~/.ssh/id_rsa.pub浏览器登录码云后,个人头像上点设置、然后点ssh公钥、随便填个标题,然后赋值ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6MWhGXSKdRxr1mGPZysDrcwABMTrxc8Va2IWZyIMMRHH9Qn/wy3PN2I9144UUqg65W0CDE/thxbOdn78MygFFsIG4j0wdT9sdjmSfzQikLHFsJ02yr58V6J2zwXcW9AhIlaGr+XIlGKDUy5mXb4OF+6UMXM6HKF7rY9FYh9wL6bun9f1jV4Ydlxftb/xtV8oQXXNJbI6OoqkogPKBYcNdWzMbjJdmbq2bSQugGaPVnHEqAD74Qgkw1G7SIDTXnY55gBlFPVzjLWUu74OWFCx4pFHH6LRZOCLlMaJ9haTwT2DB/sFzOG/Js+cEExx/arJ2rvvdmTMwlv/T+6xhrMS3 894548575@qq.com# 测试ssh -T git@gitee.com# 测试成功Hi unique_perfect! You've successfully authenticated, but GITEE.COM does not provide shell access.
3.8 创建仓库
在码云新建仓库,仓库名gulimall,选择语言java,在.gitignore选中maven,许可证选Apache-2.0,开发模型选生产/开发模型,开发时在dev分支,发布时在master分支,创建如图所示
3.9 新建项目并创建出以下服务模块
在IDEA中New Project from version control Git复制刚才项目的地址,如https://gitee.com/yxj/gulimall.git创建以下模块商品服务product存储服务ware订单服务order优惠券服务coupon用户服务member每个模块导入web和openFeign如下图所示
总体效果
创建父模块:在gulimall中创建pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.atguigu.gulimall</groupId><artifactId>gulimall</artifactId><version>0.0.1-SNAPSHOT</version><name>gulimall</name><description>谷粒商城-聚合服务</description><packaging>pom</packaging><modules><module>gulimall-coupon</module><module>gulimall-member</module><module>gulimall-order</module><module>gulimall-product</module><module>gulimall-ware</module></modules></project>
在maven窗口刷新,并点击+号,找到刚才的pom.xml添加进来,发现多了个root。这样比如运行root的clean命令,其他项目也一起clean了。修改总项目的.gitignore,把小项目里的垃圾文件在提交的时候忽略掉target/pom.xml.tagpom.xml.releaseBackuppom.xml.versionsBackuppom.xml.nextrelease.propertiesdependency-reduced-pom.xmlbuildNumber.properties.mvn/timing.properties.mvn/wrapper/maven-wrapper.jar**/mvnw**/mvnw.cmd**/.mvn**/target.idea**/.gitignore**/README.md
3.10 创建数据库
创建数据库之前需要启动docker服务sudo docker pssudo docker ps -a# 这两个命令的差别就是后者会显示【已创建但没有启动的容器】# 我们接下来设置我们要用的容器每次都是自动启动sudo docker update redis --restart=alwayssudo docker update mysql --restart=always# 如果不配置上面的内容的话,我们也可以选择手动启动sudo docker start mysqlsudo docker start redis# 如果要进入已启动的容器sudo docker exec -it mysql /bin/bash
接着创建数据库然后接着去sqlyog直接我们的操作,在左侧root上右键建立数据库:字符集选utf8mb4,他能兼容utf8且能解决一些乱码的问题。分别建立了下面数据库gulimall_omsgulimall_pmsgulimall_smsgulimall_umsgulimall_wms所有的数据库数据再复杂也不建立外键,因为在电商系统里,数据量大,做外键关联很耗性能。
gulimall-oms.sqldrop table if exists oms_order;drop table if exists oms_order_item;drop table if exists oms_order_operate_history;drop table if exists oms_order_return_apply;drop table if exists oms_order_return_reason;drop table if exists oms_order_setting;drop table if exists oms_payment_info;drop table if exists oms_refund_info;/*==============================================================*//* Table: oms_order *//*==============================================================*/create table oms_order( id bigint not null auto_increment comment 'id', member_idbigint comment 'member_id', order_sn char(32) comment '订单号', coupon_idbigint comment '使用的优惠券', create_timedatetime comment 'create_time', member_usernamevarchar(200) comment '用户名', total_amount decimal(18,4) comment '订单总额', pay_amount decimal(18,4) comment '应付总额', freight_amount decimal(18,4) comment '运费金额', promotion_amount decimal(18,4) comment '促销优化金额(促销价、满减、阶梯价)', integration_amount decimal(18,4) comment '积分抵扣金额', coupon_amountdecimal(18,4) comment '优惠券抵扣金额', discount_amountdecimal(18,4) comment '后台调整订单使用的折扣金额', pay_type tinyint comment '支付方式【1->支付宝;2->微信;3->银联; 4->货到付款;】', source_typetinyint comment '订单来源[0->PC订单;1->app订单]', status tinyint comment '订单状态【0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单】', delivery_company varchar(64) comment '物流公司(配送方式)', delivery_snvarchar(64) comment '物流单号', auto_confirm_day int comment '自动确认时间(天)', integrationint comment '可以获得的积分', growth int comment '可以获得的成长值', bill_typetinyint comment '发票类型[0->不开发票;1->电子发票;2->纸质发票]', bill_headervarchar(255) comment '发票抬头', bill_content varchar(255) comment '发票内容', bill_receiver_phonevarchar(32) comment '收票人电话', bill_receiver_emailvarchar(64) comment '收票人邮箱', receiver_namevarchar(100) comment '收货人姓名', receiver_phone varchar(32) comment '收货人电话', receiver_post_code varchar(32) comment '收货人邮编', receiver_provincevarchar(32) comment '省份/直辖市', receiver_cityvarchar(32) comment '城市', receiver_regionvarchar(32) comment '区', receiver_detail_address varchar(200) comment '详细地址', note varchar(500) comment '订单备注', confirm_status tinyint comment '确认收货状态[0->未确认;1->已确认]', delete_statustinyint comment '删除状态【0->未删除;1->已删除】', use_integrationint comment '下单时使用的积分', payment_time datetime comment '支付时间', delivery_timedatetime comment '发货时间', receive_time datetime comment '确认收货时间', comment_time datetime comment '评价时间', modify_timedatetime comment '修改时间', primary key (id));alter table oms_order comment '订单';/*==============================================================*//* Table: oms_order_item*//*==============================================================*/create table oms_order_item( id bigint not null auto_increment comment 'id', order_id bigint comment 'order_id', order_sn char(32) comment 'order_sn', spu_id bigint comment 'spu_id', spu_name varchar(255) comment 'spu_name', spu_picvarchar(500) comment 'spu_pic', spu_brandvarchar(200) comment '品牌', category_idbigint comment '商品分类id', sku_id bigint comment '商品sku编号', sku_name varchar(255) comment '商品sku名字', sku_picvarchar(500) comment '商品sku图片', sku_pricedecimal(18,4) comment '商品sku价格', sku_quantity int comment '商品购买的数量', sku_attrs_vals varchar(500) comment '商品销售属性组合(JSON)', promotion_amount decimal(18,4) comment '商品促销分解金额', coupon_amountdecimal(18,4) comment '优惠券优惠分解金额', integration_amount decimal(18,4) comment '积分优惠分解金额', real_amountdecimal(18,4) comment '该商品经过优惠后的分解金额', gift_integration int comment '赠送积分', gift_growthint comment '赠送成长值', primary key (id));alter table oms_order_item comment '订单项信息';/*==============================================================*//* Table: oms_order_operate_history *//*==============================================================*/create table oms_order_operate_history( id bigint not null auto_increment comment 'id', order_id bigint comment '订单id', operate_manvarchar(100) comment '操作人[用户;系统;后台管理员]', create_timedatetime comment '操作时间', order_status tinyint comment '订单状态【0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单】', note varchar(500) comment '备注', primary key (id));alter table oms_order_operate_history comment '订单操作历史记录';/*==============================================================*//* Table: oms_order_return_apply*//*==============================================================*/create table oms_order_return_apply( id bigint not null auto_increment comment 'id', order_id bigint comment 'order_id', sku_id bigint comment '退货商品id', order_sn char(32) comment '订单编号', create_timedatetime comment '申请时间', member_usernamevarchar(64) comment '会员用户名', return_amountdecimal(18,4) comment '退款金额', return_namevarchar(100) comment '退货人姓名', return_phone varchar(20) comment '退货人电话', status tinyint(1) comment '申请状态[0->待处理;1->退货中;2->已完成;3->已拒绝]', handle_timedatetime comment '处理时间', sku_imgvarchar(500) comment '商品图片', sku_name varchar(200) comment '商品名称', sku_brandvarchar(200) comment '商品品牌', sku_attrs_vals varchar(500) comment '商品销售属性(JSON)', sku_countint comment '退货数量', sku_pricedecimal(18,4) comment '商品单价', sku_real_price decimal(18,4) comment '商品实际支付单价', reason varchar(200) comment '原因', description述 varchar(500) comment '描述', desc_picsvarchar(2000) comment '凭证图片,以逗号隔开', handle_notevarchar(500) comment '处理备注', handle_man varchar(200) comment '处理人员', receive_manvarchar(100) comment '收货人', receive_time datetime comment '收货时间', receive_note varchar(500) comment '收货备注', receive_phonevarchar(20) comment '收货电话', company_addressvarchar(500) comment '公司收货地址', primary key (id));alter table oms_order_return_apply comment '订单退货申请';/*==============================================================*//* Table: oms_order_return_reason *//*==============================================================*/create table oms_order_return_reason( id bigint not null auto_increment comment 'id', name varchar(200) comment '退货原因名', sort int comment '排序', status tinyint(1) comment '启用状态', create_timedatetime comment 'create_time', primary key (id));alter table oms_order_return_reason comment '退货原因';/*==============================================================*//* Table: oms_order_setting *//*==============================================================*/create table oms_order_setting( id bigint not null auto_increment comment 'id', flash_order_overtime int comment '秒杀订单超时关闭时间(分)', normal_order_overtime int comment '正常订单超时时间(分)', confirm_overtime int comment '发货后自动确认收货时间(天)', finish_overtimeint comment '自动完成交易时间,不能申请退货(天)', comment_overtime int comment '订单完成后自动好评时间(天)', member_level tinyint(2) comment '会员等级【0-不限会员等级,全部通用;其他-对应的其他会员等级】', primary key (id));alter table oms_order_setting comment '订单配置信息';/*==============================================================*//* Table: oms_payment_info*//*==============================================================*/create table oms_payment_info( id bigint not null auto_increment comment 'id', order_sn char(32) comment '订单号(对外业务号)', order_id bigint comment '订单id', alipay_trade_novarchar(50) comment '支付宝交易流水号', total_amount decimal(18,4) comment '支付总金额', subjectvarchar(200) comment '交易内容', payment_status varchar(20) comment '支付状态', create_timedatetime comment '创建时间', confirm_time datetime comment '确认时间', callback_content varchar(4000) comment '回调内容', callback_timedatetime comment '回调时间', primary key (id));alter table oms_payment_info comment '支付信息表';/*==============================================================*//* Table: oms_refund_info *//*==============================================================*/create table oms_refund_info( id bigint not null auto_increment comment 'id', order_return_idbigint comment '退款的订单', refund decimal(18,4) comment '退款金额', refund_snvarchar(64) comment '退款交易流水号', refund_statustinyint(1) comment '退款状态', refund_channel tinyint comment '退款渠道[1-支付宝,2-微信,3-银联,4-汇款]', refund_content varchar(5000), primary key (id));alter table oms_refund_info comment '退款信息';
gulimall-pms.sqldrop table if exists pms_attr;drop table if exists pms_attr_attrgroup_relation;drop table if exists pms_attr_group;drop table if exists pms_brand;drop table if exists pms_category;drop table if exists pms_category_brand_relation;drop table if exists pms_comment_replay;drop table if exists pms_product_attr_value;drop table if exists pms_sku_images;drop table if exists pms_sku_info;drop table if exists pms_sku_sale_attr_value;drop table if exists pms_spu_comment;drop table if exists pms_spu_images;drop table if exists pms_spu_info;drop table if exists pms_spu_info_desc;/*==============================================================*//* Table: pms_attr*//*==============================================================*/create table pms_attr( attr_idbigint not null auto_increment comment '属性id', attr_namechar(30) comment '属性名', search_typetinyint comment '是否需要检索[0-不需要,1-需要]', icon varchar(255) comment '属性图标', value_select char(255) comment '可选值列表[用逗号分隔]', attr_typetinyint comment '属性类型[0-销售属性,1-基本属性,2-既是销售属性又是基本属性]', enable bigint comment '启用状态[0 - 禁用,1 - 启用]', catelog_id bigint comment '所属分类', show_desctinyint comment '快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整', primary key (attr_id));alter table pms_attr comment '商品属性';/*==============================================================*//* Table: pms_attr_attrgroup_relation *//*==============================================================*/create table pms_attr_attrgroup_relation( id bigint not null auto_increment comment 'id', attr_idbigint comment '属性id', attr_group_idbigint comment '属性分组id', attr_sortint comment '属性组内排序', primary key (id));alter table pms_attr_attrgroup_relation comment '属性&属性分组关联';/*==============================================================*//* Table: pms_attr_group*//*==============================================================*/create table pms_attr_group( attr_group_idbigint not null auto_increment comment '分组id', attr_group_namechar(20) comment '组名', sort int comment '排序', descript varchar(255) comment '描述', icon varchar(255) comment '组图标', catelog_id bigint comment '所属分类id', primary key (attr_group_id));alter table pms_attr_group comment '属性分组';/*==============================================================*//* Table: pms_brand *//*==============================================================*/create table pms_brand( brand_id bigint not null auto_increment comment '品牌id', name char(50) comment '品牌名', logo varchar(2000) comment '品牌logo地址', descript longtext comment '介绍', show_statustinyint comment '显示状态[0-不显示;1-显示]', first_letter char(1) comment '检索首字母', sort int comment '排序', primary key (brand_id));alter table pms_brand comment '品牌';/*==============================================================*//* Table: pms_category*//*==============================================================*/create table pms_category( cat_id bigint not null auto_increment comment '分类id', name char(50) comment '分类名称', parent_cid bigint comment '父分类id', cat_levelint comment '层级', show_statustinyint comment '是否显示[0-不显示,1显示]', sort int comment '排序', icon char(255) comment '图标地址', product_unit char(50) comment '计量单位', product_countint comment '商品数量', primary key (cat_id));alter table pms_category comment '商品三级分类';/*==============================================================*//* Table: pms_category_brand_relation *//*==============================================================*/create table pms_category_brand_relation( id bigint not null auto_increment, brand_id bigint comment '品牌id', catelog_id bigint comment '分类id', brand_name varchar(255), catelog_name varchar(255), primary key (id));alter table pms_category_brand_relation comment '品牌分类关联';/*==============================================================*//* Table: pms_comment_replay*//*==============================================================*/create table pms_comment_replay( id bigint not null auto_increment comment 'id', comment_id bigint comment '评论id', reply_id bigint comment '回复id', primary key (id));alter table pms_comment_replay comment '商品评价回复关系';/*==============================================================*//* Table: pms_product_attr_value*//*==============================================================*/create table pms_product_attr_value( id bigint not null auto_increment comment 'id', spu_id bigint comment '商品id', attr_idbigint comment '属性id', attr_namevarchar(200) comment '属性名', attr_value varchar(200) comment '属性值', attr_sortint comment '顺序', quick_show tinyint comment '快速展示【是否展示在介绍上;0-否 1-是】', primary key (id));alter table pms_product_attr_value comment 'spu属性值';/*==============================================================*//* Table: pms_sku_images*//*==============================================================*/create table pms_sku_images( id bigint not null auto_increment comment 'id', sku_id bigint comment 'sku_id', img_urlvarchar(255) comment '图片地址', img_sort int comment '排序', default_imgint comment '默认图[0 - 不是默认图,1 - 是默认图]', primary key (id));alter table pms_sku_images comment 'sku图片';/*==============================================================*//* Table: pms_sku_info*//*==============================================================*/create table pms_sku_info( sku_id bigint not null auto_increment comment 'skuId', spu_id bigint comment 'spuId', sku_name varchar(255) comment 'sku名称', sku_desc varchar(2000) comment 'sku介绍描述', catalog_id bigint comment '所属分类id', brand_id bigint comment '品牌id', sku_default_imgvarchar(255) comment '默认图片', sku_titlevarchar(255) comment '标题', sku_subtitle varchar(2000) comment '副标题', pricedecimal(18,4) comment '价格', sale_count bigint comment '销量', primary key (sku_id));alter table pms_sku_info comment 'sku信息';/*==============================================================*//* Table: pms_sku_sale_attr_value *//*==============================================================*/create table pms_sku_sale_attr_value( id bigint not null auto_increment comment 'id', sku_id bigint comment 'sku_id', attr_idbigint comment 'attr_id', attr_namevarchar(200) comment '销售属性名', attr_value varchar(200) comment '销售属性值', attr_sortint comment '顺序', primary key (id));alter table pms_sku_sale_attr_value comment 'sku销售属性&值';/*==============================================================*//* Table: pms_spu_comment *//*==============================================================*/create table pms_spu_comment( id bigint not null auto_increment comment 'id', sku_id bigint comment 'sku_id', spu_id bigint comment 'spu_id', spu_name varchar(255) comment '商品名字', member_nick_name varchar(255) comment '会员昵称', star tinyint(1) comment '星级', member_ipvarchar(64) comment '会员ip', create_timedatetime comment '创建时间', show_statustinyint(1) comment '显示状态[0-不显示,1-显示]', spu_attributes varchar(255) comment '购买时属性组合', likes_countint comment '点赞数', reply_countint comment '回复数', resourcesvarchar(1000) comment '评论图片/视频[json数据;[{type:文件类型,url:资源路径}]]', contenttext comment '内容', member_iconvarchar(255) comment '用户头像', comment_type tinyint comment '评论类型[0 - 对商品的直接评论,1 - 对评论的回复]', primary key (id));alter table pms_spu_comment comment '商品评价';/*==============================================================*//* Table: pms_spu_images*//*==============================================================*/create table pms_spu_images( id bigint not null auto_increment comment 'id', spu_id bigint comment 'spu_id', img_name varchar(200) comment '图片名', img_urlvarchar(255) comment '图片地址', img_sort int comment '顺序', default_imgtinyint comment '是否默认图', primary key (id));alter table pms_spu_images comment 'spu图片';/*==============================================================*//* Table: pms_spu_info*//*==============================================================*/create table pms_spu_info( id bigint not null auto_increment comment '商品id', spu_name varchar(200) comment '商品名称', spu_descriptionvarchar(1000) comment '商品描述', catalog_id bigint comment '所属分类id', brand_id bigint comment '品牌id', weight decimal(18,4), publish_status tinyint comment '上架状态[0 - 下架,1 - 上架]', create_timedatetime, update_timedatetime, primary key (id));alter table pms_spu_info comment 'spu信息';/*==============================================================*//* Table: pms_spu_info_desc *//*==============================================================*/create table pms_spu_info_desc( spu_id bigint not null comment '商品id', decriptlongtext comment '商品介绍', primary key (spu_id));alter table pms_spu_info_desc comment 'spu信息介绍';
gulimall_sms.sqldrop table if exists sms_coupon;drop table if exists sms_coupon_history;drop table if exists sms_coupon_spu_category_relation;drop table if exists sms_coupon_spu_relation;drop table if exists sms_home_adv;drop table if exists sms_home_subject;drop table if exists sms_home_subject_spu;drop table if exists sms_member_price;drop table if exists sms_seckill_promotion;drop table if exists sms_seckill_session;drop table if exists sms_seckill_sku_notice;drop table if exists sms_seckill_sku_relation;drop table if exists sms_sku_full_reduction;drop table if exists sms_sku_ladder;drop table if exists sms_spu_bounds;/*==============================================================*//* Table: sms_coupon*//*==============================================================*/create table sms_coupon( id bigint not null auto_increment comment 'id', coupon_typetinyint(1) comment '优惠卷类型[0->全场赠券;1->会员赠券;2->购物赠券;3->注册赠券]', coupon_img varchar(2000) comment '优惠券图片', coupon_namevarchar(100) comment '优惠卷名字', numint comment '数量', amount decimal(18,4) comment '金额', per_limitint comment '每人限领张数', min_pointdecimal(18,4) comment '使用门槛', start_time datetime comment '开始时间', end_time datetime comment '结束时间', use_type tinyint(1) comment '使用类型[0->全场通用;1->指定分类;2->指定商品]', note varchar(200) comment '备注', publish_countint(11) comment '发行数量', use_countint(11) comment '已使用数量', receive_countint(11) comment '领取数量', enable_start_timedatetime comment '可以领取的开始日期', enable_end_timedatetime comment '可以领取的结束日期', code varchar(64) comment '优惠码', member_level tinyint(1) comment '可以领取的会员等级[0->不限等级,其他-对应等级]', publishtinyint(1) comment '发布状态[0-未发布,1-已发布]', primary key (id));alter table sms_coupon comment '优惠券信息';/*==============================================================*//* Table: sms_coupon_history*//*==============================================================*/create table sms_coupon_history( id bigint not null auto_increment comment 'id', coupon_idbigint comment '优惠券id', member_idbigint comment '会员id', member_nick_name varchar(64) comment '会员名字', get_type tinyint(1) comment '获取方式[0->后台赠送;1->主动领取]', create_timedatetime comment '创建时间', use_type tinyint(1) comment '使用状态[0->未使用;1->已使用;2->已过期]', use_time datetime comment '使用时间', order_id bigint comment '订单id', order_sn bigint comment '订单号', primary key (id));alter table sms_coupon_history comment '优惠券领取历史记录';/*==============================================================*//* Table: sms_coupon_spu_category_relation*//*==============================================================*/create table sms_coupon_spu_category_relation( id bigint not null auto_increment comment 'id', coupon_idbigint comment '优惠券id', category_idbigint comment '产品分类id', category_namevarchar(64) comment '产品分类名称', primary key (id));alter table sms_coupon_spu_category_relation comment '优惠券分类关联';/*==============================================================*//* Table: sms_coupon_spu_relation *//*==============================================================*/create table sms_coupon_spu_relation( id bigint not null auto_increment comment 'id', coupon_idbigint comment '优惠券id', spu_id bigint comment 'spu_id', spu_name varchar(255) comment 'spu_name', primary key (id));alter table sms_coupon_spu_relation comment '优惠券与产品关联';/*==============================================================*//* Table: sms_home_adv*//*==============================================================*/create table sms_home_adv( id bigint not null auto_increment comment 'id', name varchar(100) comment '名字', picvarchar(500) comment '图片地址', start_time datetime comment '开始时间', end_time datetime comment '结束时间', status tinyint(1) comment '状态', click_countint comment '点击数', urlvarchar(500) comment '广告详情连接地址', note varchar(500) comment '备注', sort int comment '排序', publisher_id bigint comment '发布者', auth_idbigint comment '审核者', primary key (id));alter table sms_home_adv comment '首页轮播广告';/*==============================================================*//* Table: sms_home_subject*//*==============================================================*/create table sms_home_subject( id bigint not null auto_increment comment 'id', name varchar(200) comment '专题名字', titlevarchar(255) comment '专题标题', sub_titlevarchar(255) comment '专题副标题', status tinyint(1) comment '显示状态', urlvarchar(500) comment '详情连接', sort int comment '排序', imgvarchar(500) comment '专题图片地址', primary key (id));alter table sms_home_subject comment '首页专题表【jd首页下面很多专题,每个专题链接新的页面,展示专题商品信息】';/*==============================================================*//* Table: sms_home_subject_spu*//*==============================================================*/create table sms_home_subject_spu( id bigint not null auto_increment comment 'id', name varchar(200) comment '专题名字', subject_id bigint comment '专题id', spu_id bigint comment 'spu_id', sort int comment '排序', primary key (id));alter table sms_home_subject_spu comment '专题商品';/*==============================================================*//* Table: sms_member_price*//*==============================================================*/create table sms_member_price( id bigint not null auto_increment comment 'id', sku_id bigint comment 'sku_id', member_level_idbigint comment '会员等级id', member_level_namevarchar(100) comment '会员等级名', member_price decimal(18,4) comment '会员对应价格', add_othertinyint(1) comment '可否叠加其他优惠[0-不可叠加优惠,1-可叠加]', primary key (id));alter table sms_member_price comment '商品会员价格';/*==============================================================*//* Table: sms_seckill_promotion *//*==============================================================*/create table sms_seckill_promotion( id bigint not null auto_increment comment 'id', titlevarchar(255) comment '活动标题', start_time datetime comment '开始日期', end_time datetime comment '结束日期', status tinyint comment '上下线状态', create_timedatetime comment '创建时间', user_idbigint comment '创建人', primary key (id));alter table sms_seckill_promotion comment '秒杀活动';/*==============================================================*//* Table: sms_seckill_session *//*==============================================================*/create table sms_seckill_session( id bigint not null auto_increment comment 'id', name varchar(200) comment '场次名称', start_time datetime comment '每日开始时间', end_time datetime comment '每日结束时间', status tinyint(1) comment '启用状态', create_timedatetime comment '创建时间', primary key (id));alter table sms_seckill_session comment '秒杀活动场次';/*==============================================================*//* Table: sms_seckill_sku_notice*//*==============================================================*/create table sms_seckill_sku_notice( id bigint not null auto_increment comment 'id', member_idbigint comment 'member_id', sku_id bigint comment 'sku_id', session_id bigint comment '活动场次id', subcribe_timedatetime comment '订阅时间', send_timedatetime comment '发送时间', notice_typetinyint(1) comment '通知方式[0-短信,1-邮件]', primary key (id));alter table sms_seckill_sku_notice comment '秒杀商品通知订阅';/*==============================================================*//* Table: sms_seckill_sku_relation*//*==============================================================*/create table sms_seckill_sku_relation( id bigint not null auto_increment comment 'id', promotion_id bigint comment '活动id', promotion_session_id bigint comment '活动场次id', sku_id bigint comment '商品id', seckill_pricedecimal comment '秒杀价格', seckill_countdecimal comment '秒杀总量', seckill_limitdecimal comment '每人限购数量', seckill_sort int comment '排序', primary key (id));alter table sms_seckill_sku_relation comment '秒杀活动商品关联';/*==============================================================*//* Table: sms_sku_full_reduction*//*==============================================================*/create table sms_sku_full_reduction( id bigint not null auto_increment comment 'id', sku_id bigint comment 'spu_id', full_price decimal(18,4) comment '满多少', reduce_price decimal(18,4) comment '减多少', add_othertinyint(1) comment '是否参与其他优惠', primary key (id));alter table sms_sku_full_reduction comment '商品满减信息';/*==============================================================*//* Table: sms_sku_ladder*//*==============================================================*/create table sms_sku_ladder( id bigint not null auto_increment comment 'id', sku_id bigint comment 'spu_id', full_count int comment '满几件', discount decimal(4,2) comment '打几折', pricedecimal(18,4) comment '折后价', add_othertinyint(1) comment '是否叠加其他优惠[0-不可叠加,1-可叠加]', primary key (id));alter table sms_sku_ladder comment '商品阶梯价格';/*==============================================================*//* Table: sms_spu_bounds*//*==============================================================*/create table sms_spu_bounds( id bigint not null auto_increment comment 'id', spu_id bigint, grow_boundsdecimal(18,4) comment '成长积分', buy_bounds decimal(18,4) comment '购物积分', work tinyint(1) comment '优惠生效情况[1111(四个状态位,从右到左);0 - 无优惠,成长积分是否赠送;1 - 无优惠,购物积分是否赠送;2 - 有优惠,成长积分是否赠送;3 - 有优惠,购物积分是否赠送【状态位0:不赠送,1:赠送】]', primary key (id));alter table sms_spu_bounds comment '商品spu积分设置';
gulimall_ums.sqldrop table if exists ums_growth_change_history;drop table if exists ums_integration_change_history;drop table if exists ums_member;drop table if exists ums_member_collect_spu;drop table if exists ums_member_collect_subject;drop table if exists ums_member_level;drop table if exists ums_member_login_log;drop table if exists ums_member_receive_address;drop table if exists ums_member_statistics_info;/*==============================================================*//* Table: ums_growth_change_history *//*==============================================================*/create table ums_growth_change_history( id bigint not null auto_increment comment 'id', member_idbigint comment 'member_id', create_timedatetime comment 'create_time', change_count int comment '改变的值(正负计数)', note varchar(0) comment '备注', source_typetinyint comment '积分来源[0-购物,1-管理员修改]', primary key (id));alter table ums_growth_change_history comment '成长值变化历史记录';/*==============================================================*//* Table: ums_integration_change_history*//*==============================================================*/create table ums_integration_change_history( id bigint not null auto_increment comment 'id', member_idbigint comment 'member_id', create_timedatetime comment 'create_time', change_count int comment '变化的值', note varchar(255) comment '备注', source_tyoetinyint comment '来源[0->购物;1->管理员修改;2->活动]', primary key (id));alter table ums_integration_change_history comment '积分变化历史记录';/*==============================================================*//* Table: ums_member*//*==============================================================*/create table ums_member( id bigint not null auto_increment comment 'id', level_id bigint comment '会员等级id', username char(64) comment '用户名', password varchar(64) comment '密码', nickname varchar(64) comment '昵称', mobile varchar(20) comment '手机号码', emailvarchar(64) comment '邮箱', header varchar(500) comment '头像', gender tinyint comment '性别', birthdate comment '生日', city varchar(500) comment '所在城市', jobvarchar(255) comment '职业', sign varchar(255) comment '个性签名', source_typetinyint comment '用户来源', integrationint comment '积分', growth int comment '成长值', status tinyint comment '启用状态', create_timedatetime comment '注册时间', primary key (id));alter table ums_member comment '会员';/*==============================================================*//* Table: ums_member_collect_spu*//*==============================================================*/create table ums_member_collect_spu( id bigint not null comment 'id', member_idbigint comment '会员id', spu_id bigint comment 'spu_id', spu_name varchar(500) comment 'spu_name', spu_imgvarchar(500) comment 'spu_img', create_timedatetime comment 'create_time', primary key (id));alter table ums_member_collect_spu comment '会员收藏的商品';/*==============================================================*//* Table: ums_member_collect_subject*//*==============================================================*/create table ums_member_collect_subject( id bigint not null auto_increment comment 'id', subject_id bigint comment 'subject_id', subject_name varchar(255) comment 'subject_name', subject_imgvarchar(500) comment 'subject_img', subject_urll varchar(500) comment '活动url', primary key (id));alter table ums_member_collect_subject comment '会员收藏的专题活动';/*==============================================================*//* Table: ums_member_level*//*==============================================================*/create table ums_member_level( id bigint not null auto_increment comment 'id', name varchar(100) comment '等级名称', growth_point int comment '等级需要的成长值', default_status tinyint comment '是否为默认等级[0->不是;1->是]', free_freight_point decimal(18,4) comment '免运费标准', comment_growth_point int comment '每次评价获取的成长值', priviledge_free_freight tinyint comment '是否有免邮特权', priviledge_member_price tinyint comment '是否有会员价格特权', priviledge_birthdaytinyint comment '是否有生日特权', note varchar(255) comment '备注', primary key (id));alter table ums_member_level comment '会员等级';/*==============================================================*//* Table: ums_member_login_log*//*==============================================================*/create table ums_member_login_log( id bigint not null auto_increment comment 'id', member_idbigint comment 'member_id', create_timedatetime comment '创建时间', ip varchar(64) comment 'ip', city varchar(64) comment 'city', login_type tinyint(1) comment '登录类型[1-web,2-app]', primary key (id));alter table ums_member_login_log comment '会员登录记录';/*==============================================================*//* Table: ums_member_receive_address*//*==============================================================*/create table ums_member_receive_address( id bigint not null auto_increment comment 'id', member_idbigint comment 'member_id', name varchar(255) comment '收货人姓名', phonevarchar(64) comment '电话', post_codevarchar(64) comment '邮政编码', province varchar(100) comment '省份/直辖市', city varchar(100) comment '城市', region varchar(100) comment '区', detail_address varchar(255) comment '详细地址(街道)', areacode varchar(15) comment '省市区代码', default_status tinyint(1) comment '是否默认', primary key (id));alter table ums_member_receive_address comment '会员收货地址';/*==============================================================*//* Table: ums_member_statistics_info*//*==============================================================*/create table ums_member_statistics_info( id bigint not null auto_increment comment 'id', member_idbigint comment '会员id', consume_amount decimal(18,4) comment '累计消费金额', coupon_amountdecimal(18,4) comment '累计优惠金额', order_countint comment '订单数量', coupon_count int comment '优惠券数量', comment_countint comment '评价数', return_order_count int comment '退货数量', login_countint comment '登录次数', attend_count int comment '关注数量', fans_count int comment '粉丝数量', collect_product_count int comment '收藏的商品数量', collect_subject_count int comment '收藏的专题活动数量', collect_comment_count int comment '收藏的评论数量', invite_friend_countint comment '邀请的朋友数量', primary key (id));alter table ums_member_statistics_info comment '会员统计信息';
gulimall_wms.sql/*SQLyog Ultimate v11.25 (64 bit)MySQL - 5.7.27 : Database - gulimall_wms**********************************************************************//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;CREATE DATABASE /*!32312 IF NOT EXISTS*/`gulimall_wms` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;USE `gulimall_wms`;/*Table structure for table `undo_log` */DROP TABLE IF EXISTS `undo_log`;CREATE TABLE `undo_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,`ext` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Data for the table `undo_log` *//*Table structure for table `wms_purchase` */DROP TABLE IF EXISTS `wms_purchase`;CREATE TABLE `wms_purchase` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`assignee_id` bigint(20) DEFAULT NULL,`assignee_name` varchar(255) DEFAULT NULL,`phone` char(13) DEFAULT NULL,`priority` int(4) DEFAULT NULL,`status` int(4) DEFAULT NULL,`ware_id` bigint(20) DEFAULT NULL,`amount` decimal(18,4) DEFAULT NULL,`create_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购信息';/*Data for the table `wms_purchase` *//*Table structure for table `wms_purchase_detail` */DROP TABLE IF EXISTS `wms_purchase_detail`;CREATE TABLE `wms_purchase_detail` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`purchase_id` bigint(20) DEFAULT NULL COMMENT '采购单id',`sku_id` bigint(20) DEFAULT NULL COMMENT '采购商品id',`sku_num` int(11) DEFAULT NULL COMMENT '采购数量',`sku_price` decimal(18,4) DEFAULT NULL COMMENT '采购金额',`ware_id` bigint(20) DEFAULT NULL COMMENT '仓库id',`status` int(11) DEFAULT NULL COMMENT '状态[0新建,1已分配,2正在采购,3已完成,4采购失败]',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;/*Data for the table `wms_purchase_detail` *//*Table structure for table `wms_ware_info` */DROP TABLE IF EXISTS `wms_ware_info`;CREATE TABLE `wms_ware_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`name` varchar(255) DEFAULT NULL COMMENT '仓库名',`address` varchar(255) DEFAULT NULL COMMENT '仓库地址',`areacode` varchar(20) DEFAULT NULL COMMENT '区域编码',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='仓库信息';/*Data for the table `wms_ware_info` *//*Table structure for table `wms_ware_order_task` */DROP TABLE IF EXISTS `wms_ware_order_task`;CREATE TABLE `wms_ware_order_task` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`order_id` bigint(20) DEFAULT NULL COMMENT 'order_id',`order_sn` varchar(255) DEFAULT NULL COMMENT 'order_sn',`consignee` varchar(100) DEFAULT NULL COMMENT '收货人',`consignee_tel` char(15) DEFAULT NULL COMMENT '收货人电话',`delivery_address` varchar(500) DEFAULT NULL COMMENT '配送地址',`order_comment` varchar(200) DEFAULT NULL COMMENT '订单备注',`payment_way` tinyint(1) DEFAULT NULL COMMENT '付款方式【 1:在线付款 2:货到付款】',`task_status` tinyint(2) DEFAULT NULL COMMENT '任务状态',`order_body` varchar(255) DEFAULT NULL COMMENT '订单描述',`tracking_no` char(30) DEFAULT NULL COMMENT '物流单号',`create_time` datetime DEFAULT NULL COMMENT 'create_time',`ware_id` bigint(20) DEFAULT NULL COMMENT '仓库id',`task_comment` varchar(500) DEFAULT NULL COMMENT '工作单备注',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存工作单';/*Data for the table `wms_ware_order_task` *//*Table structure for table `wms_ware_order_task_detail` */DROP TABLE IF EXISTS `wms_ware_order_task_detail`;CREATE TABLE `wms_ware_order_task_detail` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`sku_id` bigint(20) DEFAULT NULL COMMENT 'sku_id',`sku_name` varchar(255) DEFAULT NULL COMMENT 'sku_name',`sku_num` int(11) DEFAULT NULL COMMENT '购买个数',`task_id` bigint(20) DEFAULT NULL COMMENT '工作单id',`ware_id` bigint(20) DEFAULT NULL COMMENT '仓库id',`lock_status` int(1) DEFAULT NULL COMMENT '1-已锁定2-已解锁3-扣减',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存工作单';/*Data for the table `wms_ware_order_task_detail` *//*Table structure for table `wms_ware_sku` */DROP TABLE IF EXISTS `wms_ware_sku`;CREATE TABLE `wms_ware_sku` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`sku_id` bigint(20) DEFAULT NULL COMMENT 'sku_id',`ware_id` bigint(20) DEFAULT NULL COMMENT '仓库id',`stock` int(11) DEFAULT NULL COMMENT '库存数',`sku_name` varchar(200) DEFAULT NULL COMMENT 'sku_name',`stock_locked` int(11) DEFAULT '0' COMMENT '锁定库存',PRIMARY KEY (`id`),KEY `sku_id` (`sku_id`) USING BTREE,KEY `ware_id` (`ware_id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品库存';/*Data for the table `wms_ware_sku` *//*!40101 SET SQL_MODE=@OLD_SQL_MODE */;/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
3.11 VSCode准备
在码云上搜索人人开源,我们使用renren-fast,renren-fast-vue项目。git clone https://gitee.com/renrenio/renren-fast.gitgit clone https://gitee.com/renrenio/renren-fast-vue.git下载到了桌面,我们把renren-fast移动到我们的项目文件夹(删掉.git文件),而renren-fast-vue是用VSCode打开的(后面再弄)
3.11.1 renren-fast
在idea(root)项目里的pom.xml添加一个<modules><module>gulimall-coupon</module><module>gulimall-member</module><module>gulimall-order</module><module>gulimall-product</module><module>gulimall-ware</module><module>renren-fast</module></modules>然后打开renren-fast/db/mysql.sql,复制全部,在sqlyog中创建库gulimall_admin,粘贴以下的内容执行。-- 菜单CREATE TABLE `sys_menu` (`menu_id` bigint NOT NULL AUTO_INCREMENT,`parent_id` bigint COMMENT '父菜单ID,一级菜单为0',`name` varchar(50) COMMENT '菜单名称',`url` varchar(200) COMMENT '菜单URL',`perms` varchar(500) COMMENT '授权(多个用逗号分隔,如:user:list,user:create)',`type` int COMMENT '类型 0:目录 1:菜单 2:按钮',`icon` varchar(50) COMMENT '菜单图标',`order_num` int COMMENT '排序',PRIMARY KEY (`menu_id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='菜单管理';-- 系统用户CREATE TABLE `sys_user` (`user_id` bigint NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL COMMENT '用户名',`password` varchar(100) COMMENT '密码',`salt` varchar(20) COMMENT '盐',`email` varchar(100) COMMENT '邮箱',`mobile` varchar(100) COMMENT '手机号',`status` tinyint COMMENT '状态0:禁用 1:正常',`create_user_id` bigint(20) COMMENT '创建者ID',`create_time` datetime COMMENT '创建时间',PRIMARY KEY (`user_id`),UNIQUE INDEX (`username`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统用户';-- 系统用户TokenCREATE TABLE `sys_user_token` (`user_id` bigint(20) NOT NULL,`token` varchar(100) NOT NULL COMMENT 'token',`expire_time` datetime DEFAULT NULL COMMENT '过期时间',`update_time` datetime DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`user_id`),UNIQUE KEY `token` (`token`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统用户Token';-- 系统验证码CREATE TABLE `sys_captcha` (`uuid` char(36) NOT NULL COMMENT 'uuid',`code` varchar(6) NOT NULL COMMENT '验证码',`expire_time` datetime DEFAULT NULL COMMENT '过期时间',PRIMARY KEY (`uuid`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统验证码';-- 角色CREATE TABLE `sys_role` (`role_id` bigint NOT NULL AUTO_INCREMENT,`role_name` varchar(100) COMMENT '角色名称',`remark` varchar(100) COMMENT '备注',`create_user_id` bigint(20) COMMENT '创建者ID',`create_time` datetime COMMENT '创建时间',PRIMARY KEY (`role_id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='角色';-- 用户与角色对应关系CREATE TABLE `sys_user_role` (`id` bigint NOT NULL AUTO_INCREMENT,`user_id` bigint COMMENT '用户ID',`role_id` bigint COMMENT '角色ID',PRIMARY KEY (`id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='用户与角色对应关系';-- 角色与菜单对应关系CREATE TABLE `sys_role_menu` (`id` bigint NOT NULL AUTO_INCREMENT,`role_id` bigint COMMENT '角色ID',`menu_id` bigint COMMENT '菜单ID',PRIMARY KEY (`id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='角色与菜单对应关系';-- 系统配置信息CREATE TABLE `sys_config` (`id` bigint NOT NULL AUTO_INCREMENT,`param_key` varchar(50) COMMENT 'key',`param_value` varchar(2000) COMMENT 'value',`status` tinyint DEFAULT 1 COMMENT '状态 0:隐藏 1:显示',`remark` varchar(500) COMMENT '备注',PRIMARY KEY (`id`),UNIQUE INDEX (`param_key`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统配置信息表';-- 系统日志CREATE TABLE `sys_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(50) COMMENT '用户名',`operation` varchar(50) COMMENT '用户操作',`method` varchar(200) COMMENT '请求方法',`params` varchar(5000) COMMENT '请求参数',`time` bigint NOT NULL COMMENT '执行时长(毫秒)',`ip` varchar(64) COMMENT 'IP地址',`create_date` datetime COMMENT '创建时间',PRIMARY KEY (`id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统日志';-- 文件上传CREATE TABLE `sys_oss` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`url` varchar(200) COMMENT 'URL地址',`create_date` datetime COMMENT '创建时间',PRIMARY KEY (`id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='文件上传';-- 定时任务CREATE TABLE `schedule_job` (`job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务id',`bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名称',`params` varchar(2000) DEFAULT NULL COMMENT '参数',`cron_expression` varchar(100) DEFAULT NULL COMMENT 'cron表达式',`status` tinyint(4) DEFAULT NULL COMMENT '任务状态0:正常1:暂停',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`job_id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='定时任务';-- 定时任务日志CREATE TABLE `schedule_job_log` (`log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务日志id',`job_id` bigint(20) NOT NULL COMMENT '任务id',`bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名称',`params` varchar(2000) DEFAULT NULL COMMENT '参数',`status` tinyint(4) NOT NULL COMMENT '任务状态0:成功1:失败',`error` varchar(2000) DEFAULT NULL COMMENT '失败信息',`times` int(11) NOT NULL COMMENT '耗时(单位:毫秒)',`create_time` datetime DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`log_id`),KEY `job_id` (`job_id`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='定时任务日志';-- 用户表CREATE TABLE `tb_user` (`user_id` bigint NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL COMMENT '用户名',`mobile` varchar(20) NOT NULL COMMENT '手机号',`password` varchar(64) COMMENT '密码',`create_time` datetime COMMENT '创建时间',PRIMARY KEY (`user_id`),UNIQUE INDEX (`username`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='用户';-- 初始数据 INSERT INTO `sys_user` (`user_id`, `username`, `password`, `salt`, `email`, `mobile`, `status`, `create_user_id`, `create_time`) VALUES ('1', 'admin', '9ec9750e709431dad22365cabc5c625482e574c74adaebba7dd02f1129e4ce1d', 'YzcmCZNvbXocrsz9dm8e', 'root@renren.io', '13612345678', '1', '1', '2016-11-11 11:11:11');INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (1, 0, '系统管理', NULL, NULL, 0, 'system', 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (2, 1, '管理员列表', 'sys/user', NULL, 1, 'admin', 1);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (3, 1, '角色管理', 'sys/role', NULL, 1, 'role', 2);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (4, 1, '菜单管理', 'sys/menu', NULL, 1, 'menu', 3);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (5, 1, 'SQL监控', 'http://localhost:8080/renren-fast/druid/sql.html', NULL, 1, 'sql', 4);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (6, 1, '定时任务', 'job/schedule', NULL, 1, 'job', 5);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (7, 6, '查看', NULL, 'sys:schedule:list,sys:schedule:info', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (8, 6, '新增', NULL, 'sys:schedule:save', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (9, 6, '修改', NULL, 'sys:schedule:update', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (10, 6, '删除', NULL, 'sys:schedule:delete', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (11, 6, '暂停', NULL, 'sys:schedule:pause', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (12, 6, '恢复', NULL, 'sys:schedule:resume', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (13, 6, '立即执行', NULL, 'sys:schedule:run', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (14, 6, '日志列表', NULL, 'sys:schedule:log', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (15, 2, '查看', NULL, 'sys:user:list,sys:user:info', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (16, 2, '新增', NULL, 'sys:user:save,sys:role:select', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (17, 2, '修改', NULL, 'sys:user:update,sys:role:select', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (18, 2, '删除', NULL, 'sys:user:delete', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (19, 3, '查看', NULL, 'sys:role:list,sys:role:info', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (20, 3, '新增', NULL, 'sys:role:save,sys:menu:list', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (21, 3, '修改', NULL, 'sys:role:update,sys:menu:list', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (22, 3, '删除', NULL, 'sys:role:delete', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (23, 4, '查看', NULL, 'sys:menu:list,sys:menu:info', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (24, 4, '新增', NULL, 'sys:menu:save,sys:menu:select', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (25, 4, '修改', NULL, 'sys:menu:update,sys:menu:select', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (26, 4, '删除', NULL, 'sys:menu:delete', 2, NULL, 0);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (27, 1, '参数管理', 'sys/config', 'sys:config:list,sys:config:info,sys:config:save,sys:config:update,sys:config:delete', 1, 'config', 6);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (29, 1, '系统日志', 'sys/log', 'sys:log:list', 1, 'log', 7);INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (30, 1, '文件上传', 'oss/oss', 'sys:oss:all', 1, 'oss', 6);INSERT INTO `sys_config` (`param_key`, `param_value`, `status`, `remark`) VALUES ('CLOUD_STORAGE_CONFIG_KEY', '{\"aliyunAccessKeyId\":\"\",\"aliyunAccessKeySecret\":\"\",\"aliyunBucketName\":\"\",\"aliyunDomain\":\"\",\"aliyunEndPoint\":\"\",\"aliyunPrefix\":\"\",\"qcloudBucketName\":\"\",\"qcloudDomain\":\"\",\"qcloudPrefix\":\"\",\"qcloudSecretId\":\"\",\"qcloudSecretKey\":\"\",\"qiniuAccessKey\":\"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ\",\"qiniuBucketName\":\"ios-app\",\"qiniuDomain\":\"http://7xqbwh.dl1.z0.glb.clouddn.com\",\"qiniuPrefix\":\"upload\",\"qiniuSecretKey\":\"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV\",\"type\":1}', '0', '云存储配置信息');INSERT INTO `schedule_job` (`bean_name`, `params`, `cron_expression`, `status`, `remark`, `create_time`) VALUES ('testTask', 'renren', '0 0/30 * * * ?', '0', '参数测试', now());-- 账号:13612345678密码:adminINSERT INTO `tb_user` (`username`, `mobile`, `password`, `create_time`) VALUES ('mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', '2017-03-23 22:37:41');--quartz自带表结构CREATE TABLE QRTZ_JOB_DETAILS(SCHED_NAME VARCHAR(120) NOT NULL,JOB_NAME VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,JOB_CLASS_NAME VARCHAR(250) NOT NULL,IS_DURABLE VARCHAR(1) NOT NULL,IS_NONCONCURRENT VARCHAR(1) NOT NULL,IS_UPDATE_DATA VARCHAR(1) NOT NULL,REQUESTS_RECOVERY VARCHAR(1) NOT NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,JOB_NAME VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,NEXT_FIRE_TIME BIGINT(13) NULL,PREV_FIRE_TIME BIGINT(13) NULL,PRIORITY INTEGER NULL,TRIGGER_STATE VARCHAR(16) NOT NULL,TRIGGER_TYPE VARCHAR(8) NOT NULL,START_TIME BIGINT(13) NOT NULL,END_TIME BIGINT(13) NULL,CALENDAR_NAME VARCHAR(200) NULL,MISFIRE_INSTR SMALLINT(2) NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_SIMPLE_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,REPEAT_COUNT BIGINT(7) NOT NULL,REPEAT_INTERVAL BIGINT(12) NOT NULL,TIMES_TRIGGERED BIGINT(10) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_CRON_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,CRON_EXPRESSION VARCHAR(120) NOT NULL,TIME_ZONE_ID VARCHAR(80),PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_SIMPROP_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,STR_PROP_1 VARCHAR(512) NULL,STR_PROP_2 VARCHAR(512) NULL,STR_PROP_3 VARCHAR(512) NULL,INT_PROP_1 INT NULL,INT_PROP_2 INT NULL,LONG_PROP_1 BIGINT NULL,LONG_PROP_2 BIGINT NULL,DEC_PROP_1 NUMERIC(13,4) NULL,DEC_PROP_2 NUMERIC(13,4) NULL,BOOL_PROP_1 VARCHAR(1) NULL,BOOL_PROP_2 VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_BLOB_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,BLOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_CALENDARS (SCHED_NAME VARCHAR(120) NOT NULL,CALENDAR_NAME VARCHAR(200) NOT NULL,CALENDAR BLOB NOT NULL,PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_FIRED_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,ENTRY_ID VARCHAR(95) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,FIRED_TIME BIGINT(13) NOT NULL,SCHED_TIME BIGINT(13) NOT NULL,PRIORITY INTEGER NOT NULL,STATE VARCHAR(16) NOT NULL,JOB_NAME VARCHAR(200) NULL,JOB_GROUP VARCHAR(200) NULL,IS_NONCONCURRENT VARCHAR(1) NULL,REQUESTS_RECOVERY VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,ENTRY_ID))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_SCHEDULER_STATE (SCHED_NAME VARCHAR(120) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,LAST_CHECKIN_TIME BIGINT(13) NOT NULL,CHECKIN_INTERVAL BIGINT(13) NOT NULL,PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE QRTZ_LOCKS (SCHED_NAME VARCHAR(120) NOT NULL,LOCK_NAME VARCHAR(40) NOT NULL,PRIMARY KEY (SCHED_NAME,LOCK_NAME))ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);----------------------------------------------------------------------------------------------------------然后修改项目里renren-fast中的application.yml,修改application-dev.yml中的数库库的url: jdbc:mysql://192.168.1.103:3306/gulimall_admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: root然后执行java下的RenrenApplication浏览器输入http://localhost:8080/renren-fast/ 得到{“msg”:“invalid token”,“code”:401}就代表无误
3.11.2 renren-fast-vue
用VSCode打开renren-fast-vue安装node:注意:版本为v10.16.3,python版本为3(因为不同版本等下下面遇到的问题可能不一样)接下来npm config set registry http://registry.npm.taobao.org/# 设置node仓库。提高下载速度然后在VScode的终端进入项目中输入 npm install,会报错,然后进行如下操作:报错:npm ERR! code ELIFECYCLEnpm ERR! errno 1npm ERR! chromedriver@2.27.2 install: `node install.js`npm ERR! Exit status 1npm ERR!npm ERR! Failed at the chromedriver@2.27.2 install script.npm ERR! This is probably not a problem with npm. There is likely additional logging output above.npm ERR! A complete log of this run can be found in:npm ERR! E:\installation_program\nodeRepository\npm_cache\_logs\2021-02-09T07_38_47_075Z-debug.log解决报错:npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver浏览器输入localhost:8001 就可以看到内容了,登录账号admin 密码admin
3.12 逆向工程搭建
3.12.1 product
git clone https://gitee.com/renrenio/renren-generator.git下载到桌面后,同样把里面的.git文件删除,然后移动到我们IDEA项目目录中,同样配置好pom.xml(root)gulimall-coupongulimall-membergulimall-ordergulimall-productgulimall-warerenren-fastrenren-generator
修改renren-generator的application.ymlurl: jdbc:mysql://192.168.1.103:3306/gulimall-pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: root修改generator.propertiesmainPath=com.yxj # 主目录package=com.yxj.gulimall # 包名moduleName=product # 模块名author=yxj# 作者email=xxx@qq.com# emailtablePrefix=pms_ # 我们的pms数据库中的表的前缀都有pms,如果写了表前缀,每一张表对于的javaBean就不会添加前缀了
运行RenrenApplication。如果启动不成功,修改application中是port为80。访问http://localhost:80然后点击全部,点击生成代码。下载了压缩包解压压缩包,把main放到gulimall-product的同级目录下。
然后在项目上右击(在项目上右击很重要)new modules— maven—然后在name上输入gulimall-common。在pom.xml中也自动添加了gulimall-common在common项目的pom.xml(我们把每个微服务里公共的类和依赖放到common里。)中添加com.baomidoumybatis-plus-boot-starter3.3.2org.projectlomboklombok1.18.8org.apache.httpcomponentshttpcore4.4.13commons-langcommons-lang2.6
然后在product项目中的pom.xml中加入下面内容com.atguigu.gulimallgulimall-common0.0.1-SNAPSHOT
复制renren-fast----utils包下的Query和PageUtils、R、Constant复制到common项目的java/com.yxj.common.utils下把@RequiresPermissions这些注解掉,因为是shiro的复制renren-fast中的xss包粘贴到common的java/com.yxj.common目录下。还复制了exception文件夹,对应的位置关系自己观察一下就行注释掉product项目下类中的//import org.apache.shiro.authz.annotation.RequiresPermissions;,他是shiro的东西注释renren-generator\src\main\resources\template/Controller中所有的# @RequiresPermissions。# import org.apache.shiro.authz.annotation.RequiresPermissions;总之什么报错就去renren-fast里面找。
测试测试与整合商品服务里的mybatisplus在common的pom.xml中导入mysqlmysql-connector-java8.0.17javax.servletservlet-api2.5provided# Tomcat有带,所以provided删掉common里xss/xssfiler和XssHttpServletRequestWrapper在product项目的resources目录下新建application.ymlspring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.1.103:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: root# MapperScan# sql映射文件位置mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: auto然后在主启动类上加上注解@MapperScan()@MapperScan("com.yxj.gulimall.product.dao")@SpringBootApplicationpublic class gulimallProductApplication {public static void main(String[] args) {SpringApplication.run(gulimallProductApplication.class, args);}}然后去测试,先通过下面方法给数据库添加内容@SpringBootTestclass gulimallProductApplicationTests {@AutowiredBrandService brandService;@Testvoid contextLoads() {BrandEntity brandEntity = new BrandEntity();brandEntity.setDescript("hello");brandEntity.setName("华为");brandService.save(brandEntity);System.out.println("保存成功");}}
3.12.2 coupon
重新打开generator逆向工程,修改generator.properties# 主目录 mainPath=com.yxjpackage=com.yxj.gulimallmoduleName=couponautho=yxjemail=xxx@qq.comtablePrefix=sms_修改yml数据库信息spring:datasource:username: rootpassword: rooturl: jdbc:mysql://192.168.1.103:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaimybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0server:port: 7000启动生成RenrenApplication.java,运行后去浏览器80端口查看,同样让他一页全显示后选择全部后生成。生成后解压复制到coupon项目对应目录下。让coupon也依赖于common,修改pom.xmlcom.atguigu.gulimallgulimall-common0.0.1-SNAPSHOTresources下src包先删除添加application.ymlspring:datasource:username: rootpassword: rooturl: jdbc:mysql://192.168.1.103:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0运行gulimallCouponApplication.javahttp://localhost:8080/coupon/coupon/list{"msg":"success","code":0,"page":{"totalCount":0,"pageSize":10,"totalPage":0,"currPage":1,"list":[]}}
3.12.3 member
重新使用代码生成器生成ums模仿上面修改下面两个配置代码生成器里:url: jdbc:mysql://192.168.1.103:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/ShanghaimainPath=com.yxj package=com.yxj.gulimallmoduleName=memberauthor=yxjemail=xxx@qq.comtablePrefix=ums_重启RenrenApplication.java,然后同样去浏览器获取压缩包解压到对应member项目目录member也导入依赖com.atguigu.gulimallgulimall-common0.0.1-SNAPSHOT同样新建application.ymlspring:datasource:username: rootpassword: rooturl: jdbc:mysql://192.168.1.103:3306/gulimall-ums?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0server:port: 8000
order端口是9000,product是10000,ware是11000。以后比如order系统要复制多份,他的端口计算9001、9002。。。重启web后,http://localhost:8000/member/growthchangehistory/list测试成功:{"msg":"success","code":0,"page":{"totalCount":0,"pageSize":10,"totalPage":0,"currPage":1,"list":[]}}
3.12.4 order
修改代码生成器jdbc:mysql://192.168.1.103:3306/gulimall_oms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai#代码生成器,配置信息mainPath=com.yxjpackage=com.yxj.gulimallmoduleName=orderauthor=yxjemail=xxx@qq.comtablePrefix=oms_运行RenrenApplication.java重新生成后去下载解压放置。application.ymlspring:datasource:username: rootpassword: rooturl: jdbc:mysql://192.168.1.103:3306/gulimall_oms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0server:port: 9000在pom.xml添加com.atguigu.gulimallgulimall-common0.0.1-SNAPSHOT启动gulimallOrderApplication.javahttp://localhost:9000/order/order/list{"msg":"success","code":0,"page":{"totalCount":0,"pageSize":10,"totalPage":0,"currPage":1,"list":[]}}
3.12.5 ware
修改代码生成器jdbc:mysql://192.168.1.103:3306/gulimall_wms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai#代码生成器,配置信息mainPath=com.yxjpackage=com.yxj.gulimallmoduleName=wareauthor=yxjemail=xxx@qq.comtablePrefix=wms_运行RenrenApplication.java重新生成后去下载解压放置。application.ymlspring:datasource:username: rootpassword: rooturl: jdbc:mysql://192.168.1.103:3306/gulimall_wms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0server:port: 11000在pom.xml添加com.atguigu.gulimallgulimall-common0.0.1-SNAPSHOT启动gulimallWareApplication.javahttp://localhost:11000/ware/wareinfo/list{"msg":"success","code":0,"page":{"totalCount":0,"pageSize":10,"totalPage":0,"currPage":1,"list":[]}}
4 SpringCloud Alibaba简介
4.1 搭配环境
2.1.8.RELEASEGreenwich.SR3在common的pom.xml中加入# 下面是依赖管理,相当于以后再dependencies里引spring cloud alibaba就不用写版本号, 全用dependencyManagement进行管理 com.alibaba.cloud spring-cloud-alibaba-dependencies 2.1.0.RELEASE pom import
4.2 Nacos
一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。作为我们的注册中心和配置中心。
先了解一下 Spring Cloud 应用如何接入 Nacos Discovery。1 首先,修改 common中的pom.xml 文件,引入 Nacos Discovery Starter。com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discovery2 在应用的common中的application.yml 配置文件中配置 Nacos Server 地址和微服务名称spring:application:name: gulimall-coupondatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.1.103:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: rootcloud:nacos:discovery:server-addr: 192.168.11.1:8848mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autoserver:port: 70003 我们要配置nacos服务器的地址,也就是注册中心地址,但是我们还没有nacos服务器,所以我们需要启动nacos server创建nacos服务器(软件官方可以下载)启动命令windows:startup.cmd -m standalone4 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能package com.yxj.gulimall.coupon;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@MapperScan("com.yxj.gulimall.coupon.dao")@EnableDiscoveryClientpublic class GulimallCouponApplication {public static void main(String[] args) {SpringApplication.run(GulimallCouponApplication.class, args);}}5 访问http://127.0.0.1:8848/nacos/账号密码nacos出现如下页面,则表示访问成功
按照以上步骤注册member1 在应用的common中的application.yml 配置文件中配置 Nacos Server 地址和微服务名称spring:application:name: gulimall-memberdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.1.103:3306/gulimall_ums?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: rootcloud:nacos:discovery:server-addr: 192.168.11.1:8848mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autoserver:port: 80002 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能package com.yxj.gulimall.member;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@MapperScan("com.yxj.gulimall.member.dao")@EnableDiscoveryClientpublic class GulimallMemberApplication {public static void main(String[] args) {SpringApplication.run(GulimallMemberApplication.class, args);}}
4.3 测试member和coupon的远程调用
想要获取当前会员领取到的所有优惠券。先去注册中心找优惠券服务,注册中心调一台优惠券服务器给会员,会员服务器发送请求给这台优惠券服务器,然后对方响应。Feign与注册中心spring cloud feign声明式远程调用feign是一个声明式的HTTP客户端,他的目的就是让远程调用更加简单。给远程服务发的是HTTP请求。1 会员服务想要远程调用优惠券服务,只需要给会员服务里引入openfeign依赖,他就有了远程调用其他服务的能力。org.springframework.cloudspring-cloud-starter-openfeign2 在coupon中修改如下的内容@RequestMapping("coupon/coupon")public class CouponController {@Autowiredprivate CouponService couponService;@RequestMapping("/member/list")public R membercoupons(){//全系统的所有返回都返回R// 应该去数据库查用户对于的优惠券,但这个我们简化了,不去数据库查了,构造了一个优惠券给他返回CouponEntity couponEntity = new CouponEntity();couponEntity.setCouponName("满100减10");//优惠券的名字return R.ok().put("coupons",Arrays.asList(couponEntity));}3 这样我们准备好了优惠券的调用内容在member的配置类上加注解@EnableFeignClients(basePackages="com.yxj.gulimall.member.feign"),告诉spring这里面是一个远程调用客户端,member要调用的接口package com.yxj.gulimall.member;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication@MapperScan("com.yxj.gulimall.member.dao")@EnableDiscoveryClient@EnableFeignClients(basePackages="com.yxj.gulimall.member.feign")public class GulimallMemberApplication {public static void main(String[] args) {SpringApplication.run(GulimallMemberApplication.class, args);}}4 那么要调用什么东西呢?就是我们刚才写的优惠券的功能,复制函数部分,在member的com.yxj.gulimall.member.feign包下新建类:package com.yxj.gulimall.member.feign;import com.yxj.common.utils.R;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.RequestMapping;@FeignClient("gulimall-coupon") //告诉spring cloud这个接口是一个远程客户端,要调用coupon服务,再去调用coupon服务/coupon/coupon/member/list对应的方法public interface CouponFeignService {@RequestMapping("/coupon/coupon/member/list") public R membercoupons();//得到一个R对象}5 然后我们在member的控制层写一个测试请求@RestController@RequestMapping("member/member")public class MemberController {@Autowiredprivate MemberService memberService;@AutowiredCouponFeignService couponFeignService;@RequestMapping("/coupons")public R test(){MemberEntity memberEntity = new MemberEntity();memberEntity.setNickname("张三");R membercoupons = couponFeignService.membercoupons(); //假设张三去数据库查了后返回了张三的优惠券信息// 打印会员和优惠券信息return R.ok().put("member",memberEntity).put("coupons",membercoupons.get("coupons"));}6 重新启动服务http://localhost:8000/member/member/coupons{"msg":"success","code":0,"coupons":[{"id":null,"couponType":null,"couponImg":null,"couponName":"满100减10","num":null,"amount":null,"perLimit":null,"minPoint":null,"startTime":null,"endTime":null,"useType":null,"note":null,"publishCount":null,"useCount":null,"receiveCount":null,"enableStartTime":null,"enableEndTime":null,"code":null,"memberLevel":null,"publish":null}],"member":{"id":null,"levelId":null,"username":null,"password":null,"nickname":"张三","mobile":null,"email":null,"header":null,"gender":null,"birth":null,"city":null,"job":null,"sign":null,"sourceType":null,"integration":null,"growth":null,"status":null,"createTime":null}}7 上面内容很重要,我们停留5分钟体会一下。coupon里的R.ok()是什么 # coupon里的控制层就是new了个couponEntity然后放到hashmap(R)里而已。public class R extends HashMap {public static R ok() {return new R();}public R put(String key, Object value) {super.put(key, value);return this;}}
4.4 配置中心
我们还可以用nacos作为配置中心。配置中心的意思是不在application.properties等文件中配置了,而是放到nacos配置中心公用,这样无需每台机器都改。1 引入配置中心依赖,放到common中 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config 2 在coupons项目中创建/src/main/resources/bootstrap.properties ,这个文件是springboot里规定的,他优先级别application.properties高# 改名字,对应nacos里的配置文件名spring.application.name=gulimall-couponspring.cloud.nacos.config.server-addr=192.168.11.1:88483 @RestController@RequestMapping("coupon/coupon")public class CouponController {@Autowiredprivate CouponService couponService;@Value("${coupon.user.name}")//从application.properties中获取//不要写user.name,他是环境里的变量private String name;@Value("${coupon.user.age}")private Integer age;@RequestMapping("/test")public R test(){return R.ok().put("name",name).put("age",age);}}4 浏览器去nacos里的配置列表,点击+号,data ID:gulimall-coupon.properties,配置# gulimall-coupon.propertiescoupon.user.name="张三"coupon.user.age=125 然后点击发布。重启coupon,http://localhost:7000/coupon/coupon/test{"msg":"success","code":0,"name":"张三","age":12}6 但是修改肿么办?实际生产中不能重启应用。在coupon的控制层上加@RefreshScope7 最终代码如下@RefreshScope@RestController@RequestMapping("coupon/coupon")public class CouponController {@Autowiredprivate CouponService couponService;@Value("${coupon.user.name}")//从application.properties中获取//不要写user.name,他是环境里的变量private String name;@Value("${coupon.user.age}")private Integer age;@RequestMapping("/test")public R test(){return R.ok().put("name",name).put("age",age);}}8 重启后,在nacos浏览器里修改配置,修改就可以观察到能动态修改了nacos的配置内容优先于项目本地的配置内容。
4.5 配置中心进阶
在nacos浏览器中还可以配置:命名空间:用作配置隔离。(一般每个微服务一个命名空间)默认public。默认新增的配置都在public空间下开发、测试、开发可以用命名空间分割。properties每个空间有一份。在bootstrap.properties里配置spring.cloud.nacos.config.namespace=b176a68a-6800-4648-833b-be10be8bab00# 可以选择对应的命名空间 ,即写上对应环境的命名空间ID也可以为每个微服务配置一个命名空间,微服务互相隔离配置集:一组相关或不相关配置项的集合。配置集ID:类似于配置文件名,即Data ID配置分组:默认所有的配置集都属于DEFAULT_GROUP。自己可以创建分组,比如双十一,618,双十二spring.cloud.nacos.config.group=DEFAULT_GROUP# 更改配置分组最终方案:每个微服务创建自己的命名空间,然后使用配置分组区分环境(dev/test/prod)加载多配置集我们要把原来application.yml里的内容都分文件抽离出去。我们在nacos里创建好后,在coupons里指定要导入的配置即可。bootstrap.propertiesspring.application.name=gulimall-couponspring.cloud.nacos.config.server-addr=192.168.11.1:8848spring.cloud.nacos.config.namespace=ed042b3b-b7f3-4734-bdcb-0c516cb357d7# # 可以选择对应的命名空间 ,即写上对应环境的命名空间IDspring.cloud.nacos.config.group=dev# 配置文件所在的组spring.cloud.nacos.config.ext-config[0].data-id=datasource.ymlspring.cloud.nacos.config.ext-config[0].group=devspring.cloud.nacos.config.ext-config[0].refresh=truespring.cloud.nacos.config.ext-config[1].data-id=mybatis.ymlspring.cloud.nacos.config.ext-config[1].group=devspring.cloud.nacos.config.ext-config[1].refresh=truespring.cloud.nacos.config.ext-config[2].data-id=other.ymlspring.cloud.nacos.config.ext-config[2].group=devspring.cloud.nacos.config.ext-config[2].refresh=truedatasource.ymlspring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.1.103:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: rootmybatis.ymlmybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autoother.ymlspring:application:name: gulimall-couponcloud:nacos:discovery:server-addr: 192.168.11.1:8848server:port: 7000
4.6 网关
发送请求需要知道商品服务的地址,如果商品服务器有100服务器,1号掉线后,还得改,所以需要网关动态地管理,他能从注册中心中实时地感知某个服务上线还是下线。请求也要加上询问权限,看用户有没有权限访问这个请求,也需要网关。所以我们使用spring cloud的gateway组件做网关功能。网关是请求浏览的入口,常用功能包括路由转发,权限校验,限流控制等。springcloud gateway取到了zuul网关。三大核心概念:Route: The basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates断言, and a collection of filters. A route is matched if the aggregate predicate is true.发一个请求给网关,网关要将请求路由到指定的服务。路由有id,目的地uri,断言的集合,匹配了断言就能到达指定位置,Predicate断言: This is a Java 8 Function Predicate. The input type is a Spring Framework ServerWebExchange. This lets you match on anything from the HTTP request, such as headers or parameters.就是java里的断言函数,匹配请求里的任何信息,包括请求头等Filter: These are instances of Spring Framework GatewayFilter that have been constructed with a specific factory. Here, you can modify requests andresponses before or after sending the downstream request.过滤器请求和响应都可以被修改。客户端发请求给服务端。中间有网关。先交给映射器,如果能处理就交给handler处理,然后交给一系列filer,然后给指定的服务,再返回回来给客户端。
4.6.1 创建模块gulimall-gateway
1 在pom.xml引入com.atguigu.gulimallgulimall-common0.0.1-SNAPSHOT版本环境需保持一致2.1.8.RELEASEGreenwich.SR32 开启注册服务发现@EnableDiscoveryClientpackage com.yxj.gulimall.gateway;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})@EnableDiscoveryClientpublic class GulimallGatewayApplication {public static void main(String[] args) {SpringApplication.run(GulimallGatewayApplication.class, args);}}3 配置nacos注册中心地址applicaion.propertiesspring.application.name=gulimall-gatewayspring.cloud.nacos.discovery.server-addr=192.168.11.1:8848server.port=884 bootstrap.properties 填写配置中心地址spring.application.name=gulimall-couponspring.cloud.nacos.config.server-addr=192.168.11.1:8848spring.cloud.nacos.config.namespace=a791fa0e-cef8-47ee-8f07-5ac5a63ea0615 nacos里创建命名空间gateway,然后在命名空间里创建文件guilmall-gateway.ymlspring:application:name: gulimall-gateway6 在项目里创建application.ymlspring:cloud:gateway:routes:- id: baidu_routeuri: http://www.baidu.compredicates:- Query=url,baidu- id: test_routeuri: http://www.qq.compredicates:- Query=url,qq测试 localhost:8080?url=baidu # 跳到百度页面测试 localhost:8080?url=baidu # 跳到qq页面
5 前端
前后端对比
5.1 ES6
ECMAScript6.0(以下简称ES6,ECMAScript是一种由Ecma国际通过ECMA-262标准化的脚本),是JavaScript语言的下一代标准,2015年6月正式发布,从ES6开始的版本号采用年号,如ES2015,就是ES6。ES2016就是ES7。ECMAScript是规范,JS的规范的具体实现。
5.1.1 let&&const
var在{}之外也起作用let在{}之外不起作用var多次声明同一变量不会报错,let多次声明会报错,只能声明一次。var 会变量提升(打印和定义可以顺序反)。let 不存在变量提升(顺序不能反)const声明之后不允许改变
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><script> // var 声明的变量往往会越域 // let 声明的变量有严格局部作用域// {// var a = 1;// let b = 2;// }// console.log(a);// 1// console.log(b);// ReferenceError: b is not defined// var 可以声明多次// let 只能声明一次// var m = 1// var m = 2// let n = 3// let n = 4// console.log(m)// 2// console.log(n)// Identifier 'n' has already been declared// var 会变量提升// let 不存在变量提升// console.log(x);// undefined// var x = 10;// console.log(y); //ReferenceError: y is not defined// let y = 20;// const// 1. const声明之后不允许改变// 2. 一但声明必须初始化,否则会报错const a = 1;a = 3; //Uncaught TypeError: Assignment to constant variable.</script></body></html>
5.1.2 解构表达式
支持let arr = [1,2,3]; let [a,b,c] = arr;这种语法支持对象解析:const { name: abc, age, language } = person; 冒号代表改名字符串函数支持一个字符串为多行占位符功能 ${}
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><script>//数组解构// let arr = [1,2,3];// // let a = arr[0];// // let b = arr[1];// // let c = arr[2];// let [a,b,c] = arr;// console.log(a,b,c)const person = {name: "jack",age: 21,language: ['java', 'js', 'css']}// const name = person.name;// const age = person.age;// const language = person.language;//对象解构const { name: abc, age, language } = person;console.log(abc, age, language)// 字符串扩展let str = "hello.vue";console.log(str.startsWith("hello"));//trueconsole.log(str.endsWith(".vue"));//trueconsole.log(str.includes("e"));//trueconsole.log(str.includes("hello"));//true//字符串模板let ss = `hello world`;console.log(ss);// 字符串插入变量和表达式。变量名写在 ${} 中,${} 中可以放入 JavaScript 表达式。function fun() {return "这是一个函数"}let info = `我是${abc},今年${age + 10}了, 我想说: ${fun()}`;console.log(info);</script></body></html>
5.1.3 函数优化
原来想要函数默认值得这么写b = b || 1; 现在可以直接写了function add2(a, b = 1) {函数不定参数function fun(...values) {支持箭头函数(lambda表达式),还支持使用{}结构传入对象的成员
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><script>//在ES6以前,我们无法给一个函数参数设置默认值,只能采用变通写法:function add(a, b) {// 判断b是否为空,为空就给默认值1b = b || 1;return a + b;}// 传一个参数console.log(add(10));//现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值function add2(a, b = 1) {return a + b;}console.log(add2(20));//不定参数function fun(...values) {console.log(values.length)}fun(1, 2)//2fun(1, 2, 3, 4)//4//箭头函数//以前声明一个方法// var print = function (obj) {// console.log(obj);// }var print = obj => console.log(obj);print("hello");var sum = function (a, b) {c = a + b;return a + c;}var sum2 = (a, b) => a + b;console.log(sum2(11, 12));var sum3 = (a, b) => {c = a + b;return a + c;}console.log(sum3(10, 20))const person = {name: "jack",age: 21,language: ['java', 'js', 'css']}function hello(person) {console.log("hello," + person.name)}//箭头函数+解构var hello2 = ({name}) => console.log("hello," +name);hello2(person);</script></body></html>
5.1.4 对象优化
可以获取map的键值对等Object.keys()、values、entriesObject.assgn(target,source1,source2) 合并const person2 = { age, name } //声明对象简写…代表取出该对象所有属性拷贝到当前对象。let someone = { …p1 }
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><script>const person = {name: "jack",age: 21,language: ['java', 'js', 'css']}console.log(Object.keys(person));//["name", "age", "language"]console.log(Object.values(person));//["jack", 21, Array(3)]console.log(Object.entries(person));//[Array(2), Array(2), Array(2)]const target = { a: 1 };const source1 = { b: 2 };const source2 = { c: 3 };//{a:1,b:2,c:3}Object.assign(target, source1, source2);console.log(target);//["name", "age", "language"]// 声明对象简写const age = 23const name = "张三"const person1 = { age: age, name: name }const person2 = { age, name }//声明对象简写console.log(person2);// 对象的函数属性简写let person3 = {name: "jack",// 以前:eat: function (food) {console.log(this.name + "在吃" + food);},//箭头函数this不能使用,对象.属性eat2: food => console.log(person3.name + "在吃" + food),eat3(food) {console.log(this.name + "在吃" + food);}}person3.eat("香蕉");person3.eat2("苹果")person3.eat3("橘子");// 对象拓展运算符//拷贝对象(深拷贝)let p1 = { name: "Amy", age: 15 }let someone = { ...p1 }console.log(someone)//{name: "Amy", age: 15}//合并对象let age1 = { age: 15 }let name1 = { name: "Amy" }let p2 = {name:"zhangsan"}p2 = { ...age1, ...name1 } console.log(p2)</script></body></html>
5.1.5 map和reduce
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><script>//数组中新增了map和reduce方法。//map():接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。 let arr = ['1', '20', '-5', '3']; //arr = arr.map((item)=>{// return item*2//}); arr = arr.map(item=> item*2); console.log(arr);//reduce() 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,//[2, 40, -10, 6]//arr.reduce(callback,[initialValue])/** 1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))2、currentValue (数组中当前被处理的元素)3、index (当前元素在数组中的索引)4、array (调用 reduce 的数组)*/let result = arr.reduce((a,b)=>{console.log("上一次处理后:"+a);console.log("当前正在处理:"+b);return a + b;},100);console.log(result)</script></body></html>
5.1.6 promise
以前嵌套ajax的时候很繁琐。解决方案:把Ajax封装到Promise中,赋值给let p在Ajax中成功使用resolve(data),交给then处理,失败使用reject(err),交给catch处理p.then().catch()
corse_score_10.json 得分{"id": 100,"score": 90}user.json 用户{"id": 1,"name": "zhangsan","password": "123456"}user_corse_1.json 课程{"id": 10,"name": "chinese"}
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script></head><body><script>//1、查出当前用户信息//2、按照当前用户的id查出他的课程//3、按照当前课程id查出分数// $.ajax({// url: "mock/user.json",// success(data) {// console.log("查询用户:", data);// $.ajax({// url: `mock/user_corse_${data.id}.json`,// success(data) {// console.log("查询到课程:", data);// $.ajax({// url: `mock/corse_score_${data.id}.json`,// success(data) {// console.log("查询到分数:", data);// },// error(error) {// console.log("出现异常了:" + error);// }// });// },// error(error) {// console.log("出现异常了:" + error);// }// });// },// error(error) {// console.log("出现异常了:" + error);// }// });//1、Promise可以封装异步操作// let p = new Promise((resolve, reject) => { //传入成功解析,失败拒绝// //1、异步操作// $.ajax({// url: "mock/user.json",// success: function (data) {// console.log("查询用户成功:", data)// resolve(data);// },// error: function (err) {// reject(err);// }// });// });// p.then((obj) => { //成功以后做什么// return new Promise((resolve, reject) => {// $.ajax({// url: `mock/user_corse_${obj.id}.json`,// success: function (data) {// console.log("查询用户课程成功:", data)// resolve(data);// },// error: function (err) {// reject(err)// }// });// })// }).then((data) => { //成功以后干什么// console.log("上一步的结果", data)// $.ajax({// url: `mock/corse_score_${data.id}.json`,// success: function (data) {// console.log("查询课程得分成功:", data)// },// error: function (err) {// }// });// })function get(url, data) { //自己定义一个方法整合一下return new Promise((resolve, reject) => {$.ajax({url: url,data: data,success: function (data) {resolve(data);},error: function (err) {reject(err)}})});}get("mock/user.json").then((data) => {console.log("用户查询成功~~~:", data)return get(`mock/user_corse_${data.id}.json`);}).then((data) => {console.log("课程查询成功~~~:", data)return get(`mock/corse_score_${data.id}.json`);}).then((data)=>{console.log("课程成绩查询成功~~~:", data)}).catch((err)=>{ //失败的话catchconsole.log("出现异常",err)});</script></body></html>
5.1.7 模块化
模块化就是把代码进行拆分,方便重复利用。类似于java中的导包,而JS换了个概念,是导模块。模块功能主要有两个命令构成 export 和importexport用于规定模块的对外接口import用于导入其他模块提供的功能
user.jsvar name = "jack"var age = 21function add(a,b){return a + b;}export {name,age,add}hello.js// export const util = {// sum(a, b) {// return a + b;// }// }export default {sum(a, b) {return a + b;}}// export {util}//`export`不仅可以导出对象,一切JS变量都可以导出。比如:基本类型变量、函数、数组、对象。main.jsimport abc from "./hello.js"import {name,add} from "./user.js"abc.sum(1,2);console.log(name);add(1,3);
5.2 Vue
MVVM思想M:model 包括数据和一些基本操作V:view 视图,页面渲染结果VM:View-model,模型与视图间的双向操作(无需开发人员干涉)视图和数据通过VM绑定起来,model里有变化会自动地通过Directives填写到视view中,视图表单中添加了内容也会自动地通过DOM Listeners保存到模型中。
5.2.1 基础案例
在VSCode中安装vue 2 snippets语法提示插件,在谷歌浏览器中安装vue.js devtools<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><input type="text" v-model="num">v-model实现双向绑定<button v-on:click="num++">点赞</button>v-on:click绑定事件,实现自增<button v-on:click="cancel">取消</button>回到自定义的方法<h1> {{name}} ,非常帅,有{{num}}个人为他点赞{{hello()}}</h1></div><script src="./node_modules/vue/dist/vue.js"></script><script>//1、vue声明式渲染let vm = new Vue({ //生成vue对象el: "#app",//绑定元素 div id="app"data: {//封装数据name: "张三",// 也可以使用{} //表单中可以取出num: 1},methods:{//封装方法cancel(){this.num -- ;},hello(){return "1"}}});还可以在html控制台vm.name//2、双向绑定,模型变化,视图变化。反之亦然。//3、事件处理//v-xx:指令//1、创建vue实例,关联页面的模板,将自己的数据(data)渲染到关联的模板,响应式的//2、指令来简化对dom的一些操作。//3、声明方法来做更复杂的操作。methods里面可以封装方法。</script></body></html>
5.2.2 v-text、v-html.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body> <div id="app">{{msg}}{{1+1}}{{hello()}}<br/>用v-html取内容<span v-html="msg"></span><br/>原样显示<span v-text="msg"></span></div> <script src="../node_modules/vue/dist/vue.js"></script><script>new Vue({el:"#app",data:{msg:"Hello
",link:"http://www.baidu.com"},methods:{hello(){return "World"}}})</script></body></html>
5.2.3 插值表达式
花括号:只能写在标签体内,不能用在标签内。用v-bind解决{{}}必须有返回值
5.2.4 单向绑定v-bind
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"> <a v-bind:href="link">gogogo</a><span v-bind:class="{active:isActive,'text-danger':hasError}":style="{color: color1,fontSize: size}">你好</span></div><script src="../node_modules/vue/dist/vue.js"></script><script>let vm = new Vue({el:"#app",data:{link: "http://www.baidu.com",isActive:true,hasError:true,color1:'red',size:'36px'}})</script></body></html>
5.2.5 双向绑定v-model
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app">精通的语言:<input type="checkbox" v-model="language" value="Java"> java<br/><input type="checkbox" v-model="language" value="PHP"> PHP<br/><input type="checkbox" v-model="language" value="Python"> Python<br/>选中了 {{language.join(",")}}</div><script src="../node_modules/vue/dist/vue.js"></script><script>let vm = new Vue({el:"#app",data:{language: []}})</script></body></html>
5.2.6 v-on
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><button v-on:click="num++">点赞</button><button @click="cancel">取消</button><h1>有{{num}}个赞</h1><div style="border: 1px solid red;padding: 20px;" v-on:click.once="hello">大div<div style="border: 1px solid blue;padding: 20px;" @click.stop="hello">小div <br /><a href="http://www.baidu.com" @click.prevent.stop="hello">去百度</a></div></div><input type="text" v-model="num" v-on:keyup.up="num+=2" @keyup.down="num-=2" @click.ctrl="num=10"><br />提示:</div><script src="../node_modules/vue/dist/vue.js"></script><script>new Vue({el:"#app",data:{num: 1},methods:{cancel(){this.num--;},hello(){alert("点击了")}}})</script></body></html>
5.2.7 v-for
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><ul><li v-for="(user,index) in users" :key="user.name" v-if="user.gender == '女'"> 当前索引:{{index}} ==> {{user.name}}==> {{user.gender}} ==>{{user.age}} <br>对象信息:<span v-for="(v,k,i) in user">{{k}}=={{v}}=={{i}};</span></li></ul><ul><li v-for="(num,index) in nums" :key="index"></li></ul></div><script src="../node_modules/vue/dist/vue.js"></script><script> let app = new Vue({el: "#app",data: {users: [{ name: '柳岩', gender: '女', age: 21 },{ name: '张三', gender: '男', age: 18 },{ name: '范冰冰', gender: '女', age: 24 },{ name: '刘亦菲', gender: '女', age: 18 },{ name: '古力娜扎', gender: '女', age: 25 }],nums: [1,2,3,4,4]},})</script></body></html>
5.2.8 v-if和v-show
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><button v-on:click="show = !show">点我呀</button><h1 v-if="show">if=看到我....</h1><h1 v-show="show">show=看到我</h1></div><script src="../node_modules/vue/dist/vue.js"></script><script>let app = new Vue({el: "#app",data: {show: true}})</script></body></html>
5.2.9 v-else和v-else-if
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><button v-on:click="random=Math.random()">点我呀</button><span>{{random}}</span><h1 v-if="random>=0.75">看到我啦?! ">>= 0.75</h1><h1 v-else-if="random>=0.5">看到我啦?! ">>= 0.5</h1><h1 v-else-if="random>=0.2">看到我啦?! ">>= 0.2</h1><h1 v-else>看到我啦?! <span title="< 0.2</h1></div><script src="../node_modules/vue/dist/vue.js"></script><script> let app = new Vue({el: "#app",data: { random: 1 }}) </script></body></html>
5.2.10 计算属性和侦听器
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><ul><li>西游记; 价格:{{xyjPrice}},数量:<input type="number" v-model="xyjNum"> </li><li>水浒传; 价格:{{shzPrice}},数量:<input type="number" v-model="shzNum"> </li> <li>总价:{{totalPrice}}</li>{{msg}}</ul></div><script src="../node_modules/vue/dist/vue.js"></script><script>//watch可以让我们监控一个值的变化。从而做出相应的反应。new Vue({el: "#app",data: {xyjPrice: 99.98,shzPrice: 98.00,xyjNum: 1,shzNum: 1,msg: ""},computed: {totalPrice(){return this.xyjPrice*this.xyjNum + this.shzPrice*this.shzNum}},watch: {xyjNum(newVal,oldVal){if(newVal>=3){this.msg = "库存超出限制";this.xyjNum = 3}else{this.msg = "";}}},})</script></body></html>
5.2.11 过滤器
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><ul><li v-for="user in userList">{{user.id}} ==> {{user.name}} ==> {{user.gender == 1?"男":"女"}} ==>{{user.gender | genderFilter}} ==> {{user.gender | gFilter}}</li></ul></div><script src="../node_modules/vue/dist/vue.js"></script><script>Vue.filter("gFilter", function (val) {if (val == 1) {return "男~~~";} else {return "女~~~";}})let vm = new Vue({el: "#app",data: {userList: [{ id: 1, name: 'jacky', gender: 1 },{ id: 2, name: 'peter', gender: 0 }]},filters: { filters 定义局部过滤器,只可以在当前vue实例中使用genderFilter(val) {if (val == 1) {return "男";} else {return "女";}}}})</script></body></html>
5.2.12 组件化
在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。但是如果每个页面都自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同分拆分成立的组件,然后在不同页面就可以共享这些组件,避免重复开发。在vue里,所有的vue实例都是组件组件其实也是一个vue实例,因此它在定义时也会接收:data、methods、生命周期函等不同的是组件不会与页面的元素綁定,否则就无法复用了,因此没有el属性。但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组了data必须是一个函数,不再是一个对象。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><button v-on:click="count++">我被点击了 {{count}} 次</button><counter></counter><counter></counter><counter></counter><counter></counter><counter></counter><button-counter></button-counter></div><script src="../node_modules/vue/dist/vue.js"></script><script>//1、全局声明注册一个组件Vue.component("counter", {template: ``,data() {return {count: 1}}});//2、局部声明一个组件const buttonCounter = {template: ``,data() {return {count: 1}}};new Vue({el: "#app",data: {count: 1},components: {'button-counter': buttonCounter}})</script></body></html>
5.2.13 生命周期钩子函数
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><span id="num">{{num}}</span><button @click="num++">赞!</button><h2>{{name}},有{{num}}个人点赞</h2></div><script src="../node_modules/vue/dist/vue.js"></script><script>let app = new Vue({el: "#app",data: {name: "张三",num: 100},methods: {show() {return this.name;},add() {this.num++;}},beforeCreate() {console.log("=========beforeCreate=============");console.log("数据模型未加载:" + this.name, this.num);console.log("方法未加载:" + this.show());console.log("html模板未加载:" + document.getElementById("num"));},created: function () {console.log("=========created=============");console.log("数据模型已加载:" + this.name, this.num);console.log("方法已加载:" + this.show());console.log("html模板已加载:" + document.getElementById("num"));console.log("html模板未渲染:" + document.getElementById("num").innerText);},beforeMount() {console.log("=========beforeMount=============");console.log("html模板未渲染:" + document.getElementById("num").innerText);},mounted() {console.log("=========mounted=============");console.log("html模板已渲染:" + document.getElementById("num").innerText);},beforeUpdate() {console.log("=========beforeUpdate=============");console.log("数据模型已更新:" + this.num);console.log("html模板未更新:" + document.getElementById("num").innerText);},updated() {console.log("=========updated=============");console.log("数据模型已更新:" + this.num);console.log("html模板已更新:" + document.getElementById("num").innerText);}});</script></body></html>
5.2.14 使用Vue脚手架进行开发
全局安装webpack1 npm install webpack -g全局安装vue脚手架2 npm install -g @vue/cli-init3 初始化vue项目vue init webpack appname:vue脚手架使用webpack模板初始化一个appname项目4 启动vue项目项目的package.json中有scripts,代表我们能运行的命令npm start = npm run dev: 启动项目npm run build:将项目打包
5.2.15 使用element-ui
推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用。npm i element-ui -S在 main.js 中写入以下内容:import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI);
想要获取该该课程markdown笔记(脑图+笔记)。可以扫描以下微信公众号二维码。或者搜索微信公众号-Java大世界。回复sc1即可获取笔记获取方式。