栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

谷粒商城 -->「P01-P40」

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

谷粒商城 -->「P01-P40」

文章目录
  • 分布式基础篇
    • 1.项目简介
      • 1.1项目背景
      • 1.2电商模式
        • 1.2.1 B2B 模式
        • 1.2.2 B2C 模式
        • 1.2.1 C2B 模式
        • 1.2.1 C2C 模式
        • 1.2.1 O2O 模式
    • 1.3谷粒商城
    • 1.4项目架构图
    • csdn机制问题导致图片丢失,可以查看本人的个人博客:[谷粒商城-初级篇](https://www.r2coding.vip/articles/2022/04/28/1651137988099.html)
    • 1.4微服务划分图
    • 1.5 项目技术&特色
      • 1.6项目前置要求
        • 1.6.1 学习项目的前置知识
    • 2.分布式基础概念
      • 2.1 微服务
      • 2.2 集群&分布式&节点
      • 2.3 远程调用
      • 2.4 负载均衡
      • 2.5 服务注册/发现&注册中心
      • 2.6 配置中心
      • 2.7 服务熔断&服务降级
      • 2.8 API 网关
    • 3 环境搭建
      • 3.1 安装docker(CentOS)
        • 3.1.2其他指令(可以不执行的指令)
        • 3.1.3Docker镜像操作
        • 3.1.4Docker容器操作
        • 3.1.5Docker-compose安装
        • 3.1.6容器日志管理
          • 关闭容器运行日志
          • 限制容器运行日志大小
          • 定时任务清空日志
      • 3.2 安装mysql
      • 3.3安装redis
      • 3.4Maven配置(本机)
      • 3.5安装开发插件(本机)(可选-方便开发)
      • 3.6安装git(本机)
        • 3.6.1参考
        • 3.6.2如何使用
          • 3.6.1.1如果是从远端拉取代码
          • 3.6.1.2 如果是本地已有的仓库
          • 3.6.1.3补充一下Coding
        • 3.6.3 谷粒商城Git配置
      • 3.7创建仓库
      • 3.8新建项目并创建出以下服务模块
      • 3.9创建数据库
      • 3.10VSCode准备
        • 3.10.1renren-fast
        • 3.10.2renren-fast-vue
      • 3.11逆向工程搭建
        • 3.11.1product
        • 3.11.2coupon
        • 3.11.3member
        • 3.11.4order
        • 3.11.5ware
    • 4.SpringCloud Alibaba简介
      • 4.1搭配环境
      • 4.2Nacos
      • 4.3测试member和coupon的远程调用
      • 4.4 配置中心
      • 4.5 配置中心进阶
      • 4.6网关
        • 4.6.1创建模块gulimall-gateway
      • 5.前端
      • 5.1 ES6
        • 5.1.2 解构表达式
        • 5.1.3 函数优化
        • 5.1.4 对象优化
        • 5.1.5map和reduce
        • 5.1.6promise
        • 5.1.7模块化
      • 5.2 Vue
        • 5.2.1基础案例
        • 5.2.2 v-text、v-html.html
        • 5.2.3插值表达式
        • 5.2.4 单向绑定v-bind
        • 5.2.5 双向绑定v-model
        • 5.2.6 v-on
        • 5.2.7 v-for
        • 5.2.8 v-if和v-show
        • 5.2.9 v-else和v-else-if
        • 5.2.10 计算属性和侦听器
        • 5.2.11 过滤器
        • 5.2.12 组件化
        • 5.2.13 生命周期钩子函数
    • 与 2.x 版本生命周期相对应的组合式 API
        • 5.2.14 使用Vue脚手架进行开发
        • 5.2.15 使用element-ui

分布式基础篇 1.项目简介 1.1项目背景
市面上有5种常见的电商模式 B2B、B2C、C2B、C2C、O2O
1.2电商模式 1.2.1 B2B 模式
B2B(Business to Business),是指商家和商家建立的商业关系,如阿里巴巴
1.2.2 B2C 模式
B2C(Business to Consumer) 就是我们经常看到的供应商直接把商品卖给用户,
即 “商对客” 模式,也就是我们呢说的商业零售,直接面向消费销售产品和服务,
如苏宁易购,京东,天猫,小米商城
1.2.1 C2B 模式
C2B (Customer to Business),即消费者对企业,先有消费者需求产生
而后有企业生产,即先有消费者提出需求,后又生产企业按需求组织生产
1.2.1 C2C 模式
C2C (Customer to Consumer) 客户之间把自己的东西放到网上去卖 。
如淘宝、咸鱼
1.2.1 O2O 模式
O2O 即 Online To Offline,也即将线下商务的机会与互联网
结合在一起,让互联网成为线上交易前台,线上快速支付,线上优质服务,
如:饿了么,美团,淘票票,京东到家
1.3谷粒商城
谷粒商城是一个B2C模式的电商平台,销售自营商品给客户
1.4项目架构图 csdn机制问题导致图片丢失,可以查看本人的个人博客:谷粒商城-初级篇

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mUQdvdIc-1651150085131)(https://cdn.jsdelivr.net/gh/Jonny-Chi/picgo_imgs/BLog/202203312050401.png)]

前后分离开发,分为内网部署和外网部署,外网是面向公众访问的。
访问前端项目,可以有手机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微服务划分图

反映了需要创建的微服务以及相关技术。

前后分离开发。前端项目分为admin-vue(工作人员使用的后台管理系统)、
shop-vue(面向公众访问的web网站)、app(公众)、小程序(公众)

商品服务:商品的增删改查、商品的上下架、商品详情
支付服务
优惠服务
用户服务:用户的个人中心、收货地址
仓储服务:商品的库存
秒杀服务
订单服务:订单增删改查
检索服务:商品的检索ES
中央认证服务:登录、注册、单点登录、社交登录
购物车服务
后台管理系统:添加优惠信息等
1.5 项目技术&特色
前后分离开发,并开发基于vue的后台管理系统
SpringCloud全新的解决方案
应用监控、限流、网关、熔断降级等分布式方案,全方位涉及
透彻讲解分布式事务,分布式锁等分布式系统的难点
压力测试与性能优化
各种集群技术的区别以及使用
CI/CD 使用
1.6项目前置要求
熟悉SpringBoot以及常见整合方案
了解SpringCloud
熟悉 git  maven
熟悉 linux redis docker 基本操作
了解 html,css,js,vue
熟练使用idea开发项目
1.6.1 学习项目的前置知识
熟悉SpringBoot以及常见整合方案
了解SpringCloud
熟悉 git  maven
熟悉 linux redis docker 基本操作
了解 html,css,js,vue
熟练使用idea开发项目
2.分布式基础概念 2.1 微服务
微服务架构风格,就像是把一个单独的应用程序开发成一套小服务,每个小
服务运行在自己的进程中,并使用轻量级机制通信,通常是 HTTP API 这些
服务围绕业务能力来构建,	并通过完全自动化部署机制来独立部署,这些服
务使用不同的编程语言书写,以及不同数据存储技术,并保持最低限度的集中式管理

简而言之,拒绝大型单体应用,基于业务边界进行服务微化拆分,每个服务独
立部署运行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SXbVYLUu-1651150085132)(https://cdn.jsdelivr.net/gh/Jonny-Chi/picgo_imgs/BLog/202203312127361.png)]

2.2 集群&分布式&节点
集群是个物理状态,分布式是个工作方式

只要是一堆机器,也可以叫做集群,他们是不是一起协作干活,
这谁也不知道。

《分布式系统原理与范型》定义:

分布式系统是若干独立计算机的集合,这些计算机对于用户来说像单个系统
分布式系统 (distributed system) 是建立网络之上的软件系统

分布式是指根据不同的业务分布在不同的地方

集群指的是将几台服务器集中在一起,实现同一业务

例如:京东是一个分布式系统,众多业务运行在不同的机器上,所有业务构成
一个大型的分布式业务集群,每一个小的业务,比如用户系统,访问压力大的
时候一台服务器是不够的,我们就应该将用户系统部署到多个服务器,也就是
每一个业务系统也可以做集群化

分布式中的每一个节点,都可以做集群,而集群并不一定就是分布式的

节点:集群中的一个服务器
2.3 远程调用
在分布式系统中,各个服务可能处于不同主机,但是服务之间不可避免的需要
互相调用,我们称之为远程调用

SpringCloud中使用HTTP+JSON的方式来完成远程调用

2.4 负载均衡

分布式系统中,A 服务需要调用B服务,B服务在多台机器中都存在, 
A调用任意一个服务器均可完成功能

为了使每一个服务器都不要太或者太闲,我们可以负载均衡调用每一个服务器,
提升网站的健壮性

常见的负载均衡算法:
轮询:为第一个请求选择健康池中的每一个后端服务器,然后按顺序往后依
次选择,直到最后一个,然后循环

最小连接:优先选择链接数最少,也就是压力最小的后端服务器,在会话较
长的情况下可以考虑采取这种方式
2.5 服务注册/发现&注册中心
A服务调用B服务,A服务不知道B服务当前在哪几台服务器上有,哪些正常
的,哪些服务已经下线,解决这个问题可以引入注册中心

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0krXGJL2-1651150085133)(https://cdn.jsdelivr.net/gh/Jonny-Chi/picgo_imgs/BLog/202203312132193.png)]

如果某些服务下线,我们其他人可以实时的感知到其他服务的状态,
从而避免调用不可用的服务
2.6 配置中心

每一个服务最终都有大量配置,并且每个服务都可能部署在多个服务
器上,我们经常需要变更配置,我们可以让每个服务在配置中心获取
自己的配置。

配置中心用来集中管理微服务的配置信息
2.7 服务熔断&服务降级
在微服务架构中,微服务之间通过网络来进行通信,存在相互依赖,
当其中一个服务不可用时,有可能会造成雪崩效应,要防止这种情
况,必须要有容错机制来保护服务

rpc
情景:
订单服务 --> 商品服务 --> 库存服务

库存服务出现故障导致响应慢,导致商品服务需要等待,可能等到10s后库存服
务才能响应。库存服务的不可用导致商品服务阻塞,商品服务等的期间,订单服
务也处于阻塞。一个服务不可用导致整个服务链都阻塞。如果是高并发,第一个
请求调用后阻塞10s得不到结果,第二个请求直接阻塞10s。更多的请求进来导致
请求积压,全部阻塞,最终服务器的资源耗尽。导致雪崩

1、服务熔断
设置服务的超时,当被调用的服务经常失败到达某个阈值,我们可以开启断路保
护机制,后来的请求不再去调用这个服务,本地直接返回默认的数据

2、服务降级
在运维期间,当系统处于高峰期,系统资源紧张,我们可以让非核心业务降级
运行,降级:某些服务不处理,或者简单处理【抛异常,返回NULL,调用 
Mock数据,调用 FallBack 处理逻辑】
2.8 API 网关
在微服务架构中,API Gateway 作为整体架构的重要组件,抽象服务中
需要的公共功能,同时它提供了客户端负载均衡,服务自动熔断,灰度发布,统
一认证,限流监控,日志统计等丰富功能,帮助我们解决很多API管理的难题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zTgPD88G-1651150085134)(https://cdn.jsdelivr.net/gh/Jonny-Chi/picgo_imgs/BLog/202203312137369.png)]

3 环境搭建

安装下面这些软件之前建议设置一下Linux的时间

// 查看当前时间
date
// 安装ntpdate
yum install -y ntpdate
// 更新时间
ntpdate 0.asia.pool.ntp.org
// 将系统时间同步到硬件,防止系统重启后时间被还原
hwclock --systohc

// 设置定时任务自动更新时间(每5分钟执行一次)
echo "* 5 * * * /usr/sbin/ntpdate ntp.api.bz > /dev/null 2>&1" >> /var/spool/cron/root

//查看当前Linux有哪些定时任务
crontab -l

//重启定时任务服务
systemctl restart crond.service
3.1 安装docker(CentOS)
1 卸载系统之前的docker 
sudo yum remove docker 
                  docker-client 
                  docker-client-latest 
                  docker-common 
                  docker-latest 
                  docker-latest-logrotate 
                  docker-logrotate 
                  docker-engine

2  安装一些必要的系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

3  添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

4  更新 yum 缓存
sudo yum makecache fast

5	 安装DOCKER引擎
sudo yum install docker-ce docker-ce-cli containerd.io

6  启动 Docker 后台服务
sudo systemctl start docker
// 设置开机自启
sudo systemctl enable docker

7. Docker配置国内镜像源

vi /etc/docker/daemon.json

添加以下配置
{
  "registry-mirrors": [
    "https://registry.docker-cn.com",
    "http://hub-mirror.c.163.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}

重新加载配置
sudo systemctl daemon-reload
重新启动docker
sudo systemctl restart docker


3.1.2其他指令(可以不执行的指令)
// 停止
sudo systemctl stop docker
// 重启
sudo systemctl restart docker
// 查看状态
sudo systemctl status docker
// 设置开机自启
sudo systemctl enable docker
// 取消开机自启
sudo systemctl disable docker
// 查看是否已经配置开机自启
sudo systemctl is-enabled docker
3.1.3Docker镜像操作
  • 查看镜像

    sudo docker images
    
  • 拉取镜像
    docker pull 镜像名称:版本号 如:

    sudo docker pull redis:5.0.4
    
  • 删除镜像

    sudo docker rmi 镜像ID
    
  • 运行镜像

    sudo docker run --name test -p 80:80 -p 8081:8081 -v /data/log:/data/log --restart=always -d test:1.0.0
    
    • name
      表示运行的容器的别名

    • p
      宿主机的端口域容器端口的映射关系

    • v

      文件挂载

      • 时间同步

        -v /etc/localtime:/etc/localtime
        
    • restart
      重启方式,自动重启

    • d
      后台运行

  • 镜像打标签
    sudo docker tag 基础镜像:版本 镜像地址(默认docker仓库)/路径/镜像名称:版本 如:

    sudo docker tag redis:5.0.4 hub.c.163.com/test/redis:5.0.4
    
  • 推送镜像

    sudo docker push hub.c.163.com/test/redis:5.0.4
    
3.1.4Docker容器操作
  • 查看容器运行情况

    sudo docker ps
    
  • 查看所有的容器运行情况

    sudo docker ps -a
    
  • 查询特定的容器

    sudo docker ps|grep redis
    
  • 停止容器

    sudo docker stop 容器id
    
  • 重启容器

    sudo docker restart 容器id
    
  • 启动容器

    sudo docker start 容器id
    
  • 删除容器

    sudo docker rm 容器id
    
  • 查看容器运行的日志

    sudo docker logs -f 容器ID
    
    • Docker运行日志保存的目录

      cd /var/lib/docker/containers
      
    • 清理Docker容器运行的日志

      #首先进入上面的目录
      #cd进入对应的容器
      #清空  容器id-json.log的记录文件即可清理容器运行的日志
      #或者停止、删除、重启镜像
      
  • 进入容器

    sudo docker exec -it 容器ID /bin/bash
    

    使用exit退出

  • 执行容器内的脚本
    以Nginx检查配置文件是否正确测试

    sudo docker exec 容器ID /usr/sbin/nginx -s reload
    
3.1.5Docker-compose安装
  • 方式一(推荐)

    // 直接下载
    //   github的源
    sudo curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
    //    Daocloud镜像
    curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    // 下载完成之后设置权限
    sudo chmod +x /usr/local/bin/docker-compose
    // 卸载
    sudo rm /usr/local/bin/docker-compose
    

  • 方式二

    #依赖python 可能受python版本的影响导致安装失败
    yum install epel-release
    yum install -y python-pip
    pip install docker-compose
    
  • 基础命令

    #启动容器,如果镜像不存在则先下载镜像,如果容器没创建则创建容器,如果容器没启动则启动
    docker-compose up -d 
    #停止并移除容器
    docker-compose down 
    #重启服务
    docker-compose restart 
    
  • 异常情况

    Could not find a version that satisfies the requirement requests<3,>=2.20.0 (from docker-compose) (from versions: )
    No matching distribution found for requests<3,>=2.20.0 (from docker-compose)
    You are using pip version 8.1.2, however version 19.3.1 is available.
    You should consider upgrading via the 'pip install --upgrade pip' command.
    

    pip install --upgrade pip
    // 升级成功即可安装
    

3.1.6容器日志管理
  • 容器的日志查看

    sudo docker logs -f 容器ID
    
  • 容器日志保存的位置

    /var/lib/docker/containers/
    

    以上路径下保存了当前容器的各种资源及配置,让容器被删除的时候,这里对应的文件夹也会被删除

    以下红色部分即为容器运行时的日志

  • 带来的问题
    当容器不删除重启的时候,这里的日志文件将会变得越来越大,占用了大量的内存资源;而实际的情况下,以SpringBoot项目为例,我们都会在项目里面定义自己的日志策略,因此容器运行时记录的运行日志实际上是一份多余的日志;既然是日志,必定就会占用IO,IO又是一个比较耗时的操作,而且文件越大,操作的性能就会下降。既然没啥用,那我们何不关掉它。

关闭容器运行日志
  • 配置daemon.json

    vim /etc/docker/daemon.json
    
    #添加以下配置
    "log-driver":"none"
    

    #重启docker
    service docker restart
    

    移除并重新运行镜像,再来查看容器日志,发现*-json.log已经没有了
    个人的建议是,测试环境是可以开启这个容器日志,如果镜像测试一旦稳定,推到生产的时候,出于性能考虑(因为这部分日志没有太大的价值),所以可以直接关闭掉;

限制容器运行日志大小
  • 配置daemon.json

    vim /etc/docker/daemon.json
    
    #添加以下配置
    "log-driver":"json-file",
    "log-opts": {"max-size":"1m", "max-file":"3"}
    
    • max-size
      表示日志文件的大小
    • max-file
      表示日志文件的个数,这里是3,那么最多会生成三个日志文件,每个日志文件最大1m;超过3个之后,会把最旧的那个文件给删除掉。
定时任务清空日志

不太建议使用这种方式,虽然可以解决问题,但是我认为不是一个最好的方法

  • 创建清除日志的脚本
    vim /etc/docker/clean_docker_container_logs.sh

    #!/bin/sh 
    
    echo "======== start clean docker containers logs ========"  
    #查找/var/lib/docker/containers/路径下以-json.log结尾的文件
    logs=$(find /var/lib/docker/containers/ -name *-json.log)  
    for log in $logs  
            do  
                    echo "clean logs : $log"  
                    #将对应文件的内容置为null
                    cat /dev/null > $log  
                    # 或者
                    # echo "">$log
            done  
    echo "======== end clean docker containers logs ========" 
    

    然后在crontab设置定时任务执行

    #5分钟执行一次
    */5 * * * * sh /etc/docker/clean_docker_container_logs.sh
    
3.2 安装mysql
1 拉去mysql镜像
sudo docker pull mysql:5.7

2 启动mysql容器
# --name指定容器名字 -v目录挂载 -p指定端口映射  -e设置mysql参数 -d后台运行
sudo docker run --name mysql -v /opt/docker/mysql/data:/var/lib/mysql -v /opt/docker/mysql/config:/etc/mysql -v /opt/docker/mysql/log:/var/log/mysql  -e MYSQL_ROOT_PASSWORD=root  -p 3306:3306 -d mysql:5.7

3 使用sudo su - root(切换为root,这样就不用每次都sudo来赐予了)
sudo su - root
4 进入mysql容器
docker exec -it 容器名称|容器id bin/bash
3.3安装redis
#1 在docker hub搜索redis镜像
docker search redis

#2 拉取redis镜像到本地
docker pull redis:6.0.10

#3 修改需要自定义的配置(docker-redis默认没有配置文件,
自己在宿主机建立后挂载映射)
#创建并修改/opt/docker/redis/conf/redis.conf
mkdir -p /opt/docker/redis/conf
vi /opt/docker/redis/conf/redis.conf

bind 0.0.0.0 开启远程权限(暂时可以不配置)
appendonly yes 开启aof持久化

#4 启动redis服务运行容器
docker run -p 6379:6379 --name redis -v /opt/docker/redis/data:/data  -v /opt/docker/redis/conf/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf 

解释:-v /opt/docker/redis/data:/data # 将数据目录挂在到本地保证数据安全
-v /opt/docker/redis/conf/redis.conf:/etc/redis/redis.conf   # 将配置文件挂在到本地修改方便
 
#5  直接进去redis客户端。
docker exec -it redis redis-cli
3.4Maven配置(本机)



	
		nexus-aliyun
		central
		Nexus aliyun
		http://maven.aliyun.com/nexus/content/groups/public
	




	
		jdk-1.8
		
			true
			1.8
		
		
			1.8
			1.8
			1.8
		
	

3.5安装开发插件(本机)(可选-方便开发)
vscode

Auto Close Tag  
Auto Rename Tag 
Chinese 
ESlint 
HTML CSS Support
HTML Snippets
JavaScript (ES6) code snippets
Live Server
open in brower
Vetur

idea
lombok、mybatisx
3.6安装git(本机) 3.6.1参考

进行具体配置之前,建议对git不太了解的朋友参考下面内容

查看git相关配置

查看配置 :git config -l

查看系统配置:git config --system --list #配置文件所在路径在Git安装目录下的 Git目录下的etc目录的gitconfig

查看当前用户配置:git config --global --list

#配置文件路径:Windows:C:UserAdminidtrator.gitconfig Mac:/Users/用户/.gitconfig

设置用户名与邮箱

  1. 通过命令方式修改用户及邮箱
  • 查看是否已经设置过,用户名及邮箱

  • git config user.name
    git config user.email
    
  • 若已设置,执行下面命令,重设

    • git config --global --unset user.name
      git config --global --unset user.email
      
  • 重置后,重新设置用户名及密码

    • git config --global user.name "xxx" // 配置全局用户名,如Github上注册的用户名
      git config --global user.email "yyy@mail.com" // 配置全局邮箱,如Github上配置的邮箱
      
  1. 通过配置文件直接修改用户和邮箱
  • 打开上面提到的.gitconfig文件,直接添加user和email即可
  • 例图:
  1. 对每个账户生成一对密钥
  • 首先进入保存秘钥的目录:

  • cd ~/.ssh // 进入目录,该目录下保存生成的秘钥

  • 然后,根据账户邮箱生成秘钥。例如我在GitHub上的邮箱是******.**.**,则命令为:

  • ssh-keygen -t rsa -C "******.**.**"

  • 输入完成后,会有如下提示:

  • Generating public/private rsa key pair.
    Enter file in which to save the key (/Users/jonny/.ssh/id_rsa):
    

    这里要求对秘钥进行命名,默认的文件名是id_rsa。为了方便区分,我这里命名为id_rsa_github。接下来的提示都直接进行回车,直到秘钥生成。通过ls命令,可以看到刚刚生成的密钥对id_rsa_github和id_rsa_github.pub。其中id_rsa_github.pub是公钥。

    同样,对于GitLab上的账户,我是用另一个邮箱注册的,按照同样的步骤生成id_rsa_gitlab的秘钥对。接下来的步骤,除额外说明外,两个账户的操作完全相同

  • 查看生成的密钥

  • cat id_rsa_gitee.pub 这里的id_rsa_gitee是我上面自定义的文件名,这里可根据自己设置的文件名修改

  1. 私钥添加到本地
  • SSH协议的原理,就是在托管网站上使用公钥,在本地使用私钥,这样本地仓库就可以和远程仓库进行通信。在上一步已经生成了秘钥文件,接下来需要使用秘钥文件,首先是在本地使用秘钥文件:

  • ssh-add ~/.ssh/id_rsa_github // 将GitHub私钥添加到本地 ssh-add ~/.ssh/id_rsa_gitlab // 将GitLab私钥添加到本地

  • 为了检验本地是否添加成功,可以使用ssh-add -l命令进行查看

  1. 对本地秘钥进行配置

由于添加了多个密钥文件,所以需要对这多个密钥进行管理。在.ssh目录下新建一个config文件:

touch config

文件中的内容如下:

Host github // 网站的别名,随意取
HostName github.com // 托管网站的域名
User Jonny // 托管网站上的用户名
IdentityFile ~/.ssh/id_rsa_github // 使用的密钥文件

// Gitee的配置相同
Host gitee
HostName gitee.com
User Jonny
IdentityFile ~/.ssh/id_rsa_gitee

注意,实际写到配置文件中时,一定不要写//的注释,建议直接不写注释

  1. 公钥添加到托管网站

以GitHub为例,先在本地复制公钥。进入.ssh目录,使用vim id_rsa_github.pub查看生成的GitHub公钥,全选进行复制。

登录GitHub,点击右上角头像选择settings,在打开的页面中选择SSH and GPG keys

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GGAPoe7h-1651150085137)(https://cdn.jsdelivr.net/gh/Jonny-Chi/picgo_imgs/BLog/202204010029377.png)]

在打开的页面的Key输入框中粘贴刚刚复制的公钥,title的名字自己随便去,然后点击下方的Add SSH key按钮:

至此,托管网站的公钥添加完成。总结来说,就是针对每个托管网站分别生成一对密钥,然后分别添加到本地和托管网站。

这时候,可以测试一下配置是否成功,测试命令使用别名。例如,对于GitHub,本来应该使用的测试命令是:

ssh -T git@github.com

在config文件中,给GitHub网站配置的别名就是github,所以直接使用别名,就是

ssh -T git@github

3.6.2如何使用

使用有两种情况,一种情况是从远端拉取代码到本地,一种是本地已有仓库需要与远程仓库关联。

3.6.1.1如果是从远端拉取代码

选择SSH协议的复制命令,如对于GitLab上代码库test,其复制命令为

git clone git@gitlab.com:****/test.git

由于使用了别名gitlab,所以实际使用的复制命令应当为:

git clone git@gitlab:****/test.git

github同理

这种方法较为简单,修改后的代码无需额外配置,可以直接push

3.6.1.2 如果是本地已有的仓库

这种情况适用于本地新建的仓库需要与远端进行关联,或者之前已经使用sourceTree等图形界面软件拷贝的仓库。进入本地仓库文件夹,需要单独配置该仓库的用户名和邮箱

git config user.name "Jonny" git config user.email "******.**.**"

然后,进入本地仓库的git目录,打开config文件

cd .git // 该目录是隐藏的,ls命令不可见,但是可以直接进入,如果是新建的文件夹需要先执行git init vim config

在config文件中,修改(config文件中已有remote "origin"信息)或者添加(config文件中不包含remote "origin"信息)分支信息:

[remote "origin"] url = git@gitlab:GuiLiu/test.git fetch = +refs/headsgulimall.git 创建以下模块 商品服务product 存储服务ware 订单服务order 优惠券服务coupon 用户服务member 每个模块导入web和openFeign 如下图所示

按照上图的格式创建即可

创建父模块:在gulimall中创建pom.xml


    4.0.0
    com.atguigu.gulimall
    gulimall
    0.0.1-SNAPSHOT
    gulimall
    谷粒商城-聚合服务
    pom

    
        gulimall-coupon
        gulimall-member
        gulimall-order
        gulimall-product
        gulimall-ware
    



修改总项目的.gitignore,把小项目里的垃圾文件在提交的时候忽略掉

target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar

**/mvnw
**/mvnw.cmd

**/.mvn
**/target

.idea


**/.gitignore

**/README.md


3.9创建数据库
#创建数据库之前需要启动docker服务

sudo docker ps
sudo docker ps -a
# 这两个命令的差别就是后者会显示  【已创建但没有启动的容器】

# 我们接下来设置我们要用的容器每次都是自动启动
sudo docker update redis --restart=always
sudo docker update mysql --restart=always
# 如果不配置上面的内容的话,我们也可以选择手动启动
sudo docker start mysql
sudo docker start redis
# 如果要进入已启动的容器
sudo docker exec -it mysql /bin/bash
接着创建数据库
然后接着去sqlyog直接我们的操作,在左侧root上右键建立数据库:
字符集选utf8mb4,他能兼容utf8且能解决一些乱码的问题。分别
建立了下面数据库

gulimall_oms
gulimall_pms
gulimall_sms
gulimall_ums
gulimall_wms

所有的数据库数据再复杂也不建立外键,因为在电商系统里,数据量大,
做外键关联很耗性能。

具体SQL在代码中有,不一一列举出来了

3.10VSCode准备
//在码云上搜索人人开源,我们使用renren-fast,renren-fast-vue项目。
git clone https://gitee.com/renrenio/renren-fast.git

git clone https://gitee.com/renrenio/renren-fast-vue.git

//下载到了桌面,我们把renren-fast移动到我们的项目文件夹(删掉.git文件),而renren-fast-vue是用VSCode打开的(后面再弄)
3.10.1renren-fast
在idea(root)项目里的pom.xml添加一个

    gulimall-coupon
    gulimall-member
    gulimall-order
    gulimall-product
    gulimall-ware

    renren-fast


然后打开renren-fast/db/mysql.sql,复制全部,在数据库工具直接执行即可
3.10.2renren-fast-vue
用VSCode打开renren-fast-vue

安装node:
注意:版本为v10.16.3,python版本为3(因为不同版本等下下面遇到的问题可能不一样)【我在这用的是16.14版的】
接下来
npm config set registry http://registry.npm.taobao.org/  # 设置node仓库。提高下载速度

然后在VScode的终端进入项目中输入 npm install,会报错,然后进行如下操作:
报错:
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! chromedriver@2.27.2 install: `node install.js`
npm ERR! Exit status 1
npm 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_programnodeRepositorynpm_cache_logs2021-02-09T07_38_47_075Z-debug.log

解决报错:
npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver

报错:
Module build failed: Error: ENOENT: no such file or directory, scandir '/Users/joe/Study/Demo/gulimall/renren-fast-vue/node_modules/node-sass/vendor'

解决报错
1.cd 进入node_modules
$ cd node_modules

2.运行npm rebuild node-sass
$ npm rebuild node-sass

需要等待一段时间:出现 rebuilt dependencies successfully

最后直接运行代码就OK了

浏览器输入localhost:8001 就可以看到内容了,登录账号admin 密码admin
3.11逆向工程搭建 3.11.1product
git clone https://gitee.com/renrenio/renren-generator.git

下载到桌面后,同样把里面的.git文件删除,然后移动到我们IDEA项目目录中,同样配置好pom.xml(root)


		gulimall-coupon
		gulimall-member
		gulimall-order
		gulimall-product
		gulimall-ware
		renren-fast
		renren-generator

修改renren-generator的application.yml
url: jdbc:mysql://192.168.1.17:3306/gulimall-pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root

修改generator.properties
mainPath=com.rabbitboss # 主目录
package=com.rabbitboss.gulimall # 包名
moduleName=product   # 模块名
author=Jonny  # 作者
email=xxx@qq.com  # email
tablePrefix=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.baomidou
    mybatis-plus-boot-starter
    3.3.2



    org.projectlombok
    lombok
    1.18.8



    org.apache.httpcomponents
    httpcore
    4.4.13


    commons-lang
    commons-lang
    2.6

然后在product项目中的pom.xml中加入下面内容

    com.atguigu.gulimall
    gulimall-common
    0.0.1-SNAPSHOT

复制

renren-fast----utils包下的Query和PageUtils、R、Constant复制到common项目的java/com.rabbitboss.common.utils下

把@RequiresPermissions这些注解掉,因为是shiro的

复制renren-fast中的xss包粘贴到common的java/com.rabbitboss.common目录下。

还复制了exception文件夹,对应的位置关系自己观察一下就行

注释掉product项目下类中的//import org.apache.shiro.authz.annotation.RequiresPermissions;,他是shiro的东西

注释renren-generatorsrcmainresourcestemplate/Controller中所有的
# @RequiresPermissions。
# import org.apache.shiro.authz.annotation.RequiresPermissions;

总之什么报错就去renren-fast里面找。
测试
测试与整合商品服务里的mybatisplus

在common的pom.xml中导入


    mysql
    mysql-connector-java
    8.0.17



    javax.servlet
    servlet-api
    2.5
    provided  # Tomcat有带,所以provided


删掉common里xss/xssfiler和XssHttpServletRequestWrapper
在product项目的resources目录下新建application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.17:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root


# MapperScan
# sql映射文件位置
mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto

然后在主启动类上加上注解@MapperScan()
@MapperScan("com.rabbitboss.gulimall.product.dao")
@SpringBootApplication
public class gulimallProductApplication {


    public static void main(String[] args) {

        SpringApplication.run(gulimallProductApplication.class, args);
    }

}

然后去测试,先通过下面方法给数据库添加内容
@SpringBootTest
class GulimallProductApplicationTests {

    @Autowired
    BrandService brandService;

    @Test
    void contextLoads() {

//        BrandEntity brandEntity = new BrandEntity();
//        brandEntity.setBrandId(1L);
//        brandEntity.setDescript("华为");

//        brandEntity.setDescript("");
//        brandEntity.setName("华为");
//        this.brandService.save(brandEntity);
//        System.out.println("保存成功!");

//        brandService.updateById(brandEntity);
//        System.out.println("修改成功!");

        List list = brandService.list(new QueryWrapper().eq("brand_id", 1L));
        list.forEach((item)->{
            System.out.println(item);
        });

    }

}
3.11.2coupon
重新打开generator逆向工程,修改generator.properties
# 主目录 
mainPath=com.rabbitboss
package=com.rabbitboss.gulimall
moduleName=coupon
autho=rabbitboss
email=xxx@qq.com
tablePrefix=sms_

修改yml数据库信息
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.1.17:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai


mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0

server:
  port: 7000

启动生成RenrenApplication.java,运行后去浏览器80端口查看,同样让他一
页全显示后选择全部后生成。生成后解压复制到coupon项目对应目录下。
让coupon也依赖于common,修改pom.xml


    com.atguigu.gulimall
    gulimall-common
    0.0.1-SNAPSHOT


resources下src包先删除

添加application.yml
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.1.17:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver


mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0

运行gulimallCouponApplication.java

http://localhost:8080/coupon/coupon/list

{"msg":"success","code":0,"page":{"totalCount":0,"pageSize":10,"totalPage":0,"currPage":1,"list":[]}}
3.11.3member
重新使用代码生成器生成ums

模仿上面修改下面两个配置
代码生成器里:
url: jdbc:mysql://192.168.1.17:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai


mainPath=com.rabbitboss 
package=com.rabbitboss.gulimall
moduleName=member
author=rabbitboss
email=xxx@qq.com
tablePrefix=ums_

重启RenrenApplication.java,然后同样去浏览器获取压缩包解压到对应member项目目录

member也导入依赖

    com.atguigu.gulimall
    gulimall-common
    0.0.1-SNAPSHOT


同样新建application.yml
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.1.17:3306/gulimall-ums?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver


mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0

server:
  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.11.4order
修改代码生成器
jdbc:mysql://192.168.1.17:3306/gulimall_oms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai

#代码生成器,配置信息
mainPath=com.rabbitboss
package=com.rabbitboss.gulimall
moduleName=order
author=rabbitboss
email=xxx@qq.com
tablePrefix=oms_


运行RenrenApplication.java重新生成后去下载解压放置。
application.yml

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.1.17:3306/gulimall_oms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver


mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0
      
server:
  port: 9000

在pom.xml添加

    com.atguigu.gulimall
    gulimall-common
    0.0.1-SNAPSHOT


启动gulimallOrderApplication.java

http://localhost:9000/order/order/list
{"msg":"success","code":0,"page":{"totalCount":0,"pageSize":10,"totalPage":0,"currPage":1,"list":[]}}
3.11.5ware
修改代码生成器
jdbc:mysql://192.168.1.17:3306/gulimall_wms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai

#代码生成器,配置信息

mainPath=com.rabbitboss
package=com.rabbitboss.gulimall
moduleName=ware
author=rabbitboss
email=xxx@qq.com
tablePrefix=wms_

运行RenrenApplication.java重新生成后去下载解压放置。

application.yml

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.1.17:3306/gulimall_wms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver


mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0
      
server:
  port: 11000

在pom.xml添加

    com.atguigu.gulimall
    gulimall-common
    0.0.1-SNAPSHOT


启动gulimallWareApplication.java
http://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.6.6.RELEASE
2021.0.1


在common的pom.xml中加入
# 下面是依赖管理,相当于以后再dependencies里引spring cloud alibaba就不用写版本号, 全用dependencyManagement进行管理

        
            
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                2021.0.1.0
                pom
                import
            
        

4.2Nacos
一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

作为我们的注册中心和配置中心。
先了解一下 Spring Cloud 应用如何接入 Nacos Discovery。
1 首先,修改 common中的pom.xml 文件,引入 Nacos Discovery Starter。

    com.alibaba.cloud
    spring-cloud-starter-alibaba-nacos-discovery


2 在应用的resources中的application.yml 配置文件中配置 Nacos Server 地址和微服务名称
spring:
  application:
    name: gulimall-coupon
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.17:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto



server:
  port: 7000

3 我们要配置nacos服务器的地址,也就是注册中心地址,但是我们还没有nacos服务器,所以我们需要启动nacos server创建nacos服务
器(软件官方可以下载)启动命令(standalone代表着单机模式运行,非集群模式)
启动命令windows:startup.cmd -m standalone
启动命令Mac:sh startup.sh -m standalone

停止命令windows:shutdown.cmd
停止命令Mac:sh shutdown.sh

4 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能
package com.rabbitboss.gulimall.coupon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class GulimallCouponApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallCouponApplication.class, args);
    }

}

5 访问http://127.0.0.1:8848/nacos/  账号密码nacos
出现如下页面,则表示访问成功

如图所示:

仿照上面的例子继续配置:member,order,product,ware

4.3测试member和coupon的远程调用
想要获取当前会员领取到的所有优惠券。先去注册中心找优惠券服务,注册中心调一台优惠券服务器给会员,
会员服务器发送请求给这台优惠券服务器,然后对方响应。

Feign与注册中心
spring cloud feign

声明式远程调用

feign是一个声明式的HTTP客户端,他的目的就是让远程调用更加简单。
给远程服务发的是HTTP请求。

1 会员服务想要远程调用优惠券服务,只需要给会员服务里引入
openfeign依赖,他就有了远程调用其他服务的能力。


    org.springframework.cloud
    spring-cloud-starter-openfeign

                                                                                                                                                 
2 在coupon中修改如下的内容
@RequestMapping("coupon/coupon")
public class CouponController {
    @Autowired
    private 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.rabbitboss.gulimall.member.feign"),
告诉spring这里面是一个远程调用客户端,member要调用的接口

package com.rabbitboss.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.rabbitboss.gulimall.member.dao")
@EnableDiscoveryClient
@EnableFeignClients(basePackages="com.rabbitboss.gulimall.member.feign")
public class GulimallMemberApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallMemberApplication.class, args);
    }

}

4 那么要调用什么东西呢?就是我们刚才写的优惠券的功能,
复制函数部分,在member的com.rabbitboss.gulimall.member.feign包下新建类:
package com.rabbitboss.gulimall.member.feign;

import com.rabbitboss.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 {
    @Autowired
    private MemberService memberService;

    @Autowired
    CouponFeignService 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;
	}

}

报错:No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?

将gulimall-common下的pom.xml文件中 **spring-cloud-starter-alibaba-nacos-discovery**的依赖修改一下,

并添加**spring-cloud-starter-loadbalancer**依赖

        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
            
                
                    org.springframework.cloud
                    spring-cloud-starter-netflix-ribbon
                
            
        

        
            org.springframework.cloud
            spring-cloud-loadbalancer

            3.1.0
        
4.4 配置中心

nacos 配置中心不实时同步问题或者读取不到bootstrap.properties

将gulimall-common下的pom.xml文件中添加以下依赖

        
        
        
            org.springframework.cloud
            spring-cloud-starter-bootstrap
            3.1.0
        
 
我们还可以用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-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

3 @RestController
@RequestMapping("coupon/coupon")
public class CouponController {
    @Autowired
    private 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.properties
coupon.user.name="张三"      
coupon.user.age=12

5 然后点击发布。重启coupon,http://localhost:7000/coupon/coupon/test
{"msg":"success","code":0,"name":"张三","age":12}


6 但是修改肿么办?实际生产中不能重启应用。在coupon的控制层上加
@RefreshScope


7 最终代码如下
@RefreshScope
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
    @Autowired
    private 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.properties
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848


spring.cloud.nacos.config.namespace=ed042b3b-b7f3-4734-bdcb-0c516cb357d7  # # 可以选择对应的命名空间 ,即写上对应环境的命名空间ID
spring.cloud.nacos.config.group=dev  # 配置文件所在的组

spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true

spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true

spring.cloud.nacos.config.ext-config[2].data-id=other.yml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true


datasource.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.17:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root

mybatis.yml
mybatis-plus:
  mapper-locations: classpath:/mapper*.xml
  global-config:
    db-config:
      id-type: auto

other.yml
spring:
  application:
    name: gulimall-coupon
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

server:
  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 and
responses before or after sending the downstream request.
过滤器请求和响应都可以被修改。
客户端发请求给服务端。中间有网关。先交给映射器,如果能处理就交给handler
处理,然后交给一系列filer,然后给指定的服务,再返回回来给客户端。

4.6.1创建模块gulimall-gateway

1 在pom.xml引入

            com.atguigu.gulimall
            gulimall-common
            0.0.1-SNAPSHOT


版本环境需保持一致
2.1.8.RELEASE
Greenwich.SR3

2 开启注册服务发现@EnableDiscoveryClient
package 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})
@EnableDiscoveryClient
public class GulimallGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallGatewayApplication.class, args);
    }

}

3 配置nacos注册中心地址applicaion.properties
spring.application.name=gulimall-gateway
spring.cloud.nacos.discovery.server-addr=192.168.11.1:8848
server.port=88

4 bootstrap.properties 填写配置中心地址
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=192.168.11.1:8848

spring.cloud.nacos.config.namespace=a791fa0e-cef8-47ee-8f07-5ac5a63ea061

5 nacos里创建命名空间gateway,然后在命名空间里创建文件guilmall-gateway.yml

spring:
    application:
        name: gulimall-gateway

6 在项目里创建application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: baidu_route
          uri: http://www.baidu.com
          predicates:
            - Query=url,baidu

        - id: test_route
          uri: http://www.qq.com
          predicates:
            - Query=url,qq

测试 localhost:8080?url=baidu # 跳到百度页面
测试 localhost:8080?url=baidu # 跳到qq页面
5.前端

前后端对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9C85pEzs-1651150085140)(https://cdn.jsdelivr.net/gh/Jonny-Chi/picgo_imgs/BLog/202204032257179.png)]

5.1 ES6

ECMAScript6.0(以下简称ES6,ECMAScript是一种由Ecma国际通过ECMA-262标准化的脚本),
是JavaScript语言的下一代标准,2015年6月正式发布,从ES6开始的版本号采用年号,如ES2015,就是ES6。ES2016就是ES7。
ECMAScript是规范,JS的规范的具体实现。

var在{}之外也起作用
let在{}之外不起作用
var多次声明同一变量不会报错,let多次声明会报错,let变量只能声明一次。

var 会变量提升(打印和定义可以顺序反)。let 不存在变量提升(顺序不能反)
## var变量提升实际就是,var的变量在为定义之前可以输出,不报错,只是说未定义的变量未赋值(undefined)
## let变量如果不赋值会报错:【ReferenceError: y is not defined】

const声明之后不允许改变




    
    
    
    Document





    





5.1.2 解构表达式

支持let arr = [1,2,3]; let [a,b,c] = arr;这种语法
支持对象解析:const { name: abc, age, language } = person; 冒号代表改名
字符串函数
支持一个字符串为多行
占位符功能 ${}





    
    
    
    Document





    




5.1.3 函数优化

原来想要函数默认值得这么写b = b || 1; 现在可以直接写了function add2(a, b = 1) {
函数不定参数function fun(…values) {
支持箭头函数(lambda表达式),还支持使用{}结构传入对象的成员





    
    
    
    Document




    




5.1.4 对象优化

可以获取map的键值对等Object.keys()、values、entries
Object.assgn(target,source1,source2) 合并
const person2 = { age, name } //声明对象简写
…代表取出该对象所有属性拷贝到当前对象。let someone = { …p1 }




    
    
    
    Document


    
    


5.1.5map和reduce



    
    
    
    Document


    
    


5.1.6promise
以前嵌套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"
}



    
    
    
    Document
    


    



5.1.7模块化
模块化就是把代码进行拆分,方便重复利用。类似于java中的导包,
而JS换了个概念,是导模块。

模块功能主要有两个命令构成 export 和import

export用于规定模块的对外接口
import用于导入其他模块提供的功能
user.js
var name = "jack"
var age = 21
function add(a,b){
    return a + b;
}

export {name,age,add}

hello.js
// export const util = {		
//这种方式导入在import abc from "./hello.js"不可以用自定义的abc变量名,需要固定使用定义的util
//     sum(a, b) {
//         return a + b;
//     }
// }

export default {
    sum(a, b) {
        return a + b;
    }
}
// export {util}

//`export`不仅可以导出对象,一切JS变量都可以导出。比如:基本类型变量、函数、数组、对象。


main.js
import 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基础案例
官网:https://cn.vuejs.org/
参考:https://cn.vuejs.org/v2/guide/
Git 地址:https://github.com/vuejs

Vue2.x初始化
当前文件夹下的终端:
- npm init -y
- npm install vue

Vue3.x初始化
# npm 6.x
$ npm init vite@latest  --template vue

# npm 7+,需要加上额外的双短横线
$ npm init vite@latest  -- --template vue

$ cd 
$ npm install
$ npm run dev

Vue2.x写法







    
    
    
    Document




    
v-model实现双向绑定 v-on:click绑定事件,实现自增 回到自定义的方法

{{name}} ,非常帅,有{{num}}个人为他点赞{{hello()}}

Vue3.x写法





    
    
    
    Document




    
v-model实现双向绑定 v-on:click绑定事件,实现自增 回到自定义的方法

{{name}} ,非常帅,有{{num}}个人为他点赞

{ counter }} -->
5.2.2 v-text、v-html.html

v-text :将数据输出到元素内部,如果输出的数据有 HTML 代码,会作为普通文本输出

v-html :将数据输出到元素内部,如果输出的数据有 HTML 代码,会被渲染

Vue2.x写法




    
    
    
    Document


   
    
{{msg}} {{1+1}} {{hello()}}
用v-html取内容
原样显示

Vue3.x写法




    
    
    
    Document


    
    
{{msg}}
{{1+1}}
{{hello()}}


存在区别:在2.x版本的时候直接用{{}} 取值的时候会直接将插值表达式展示出来,而Vue3.x不会直接展示插值表达式

5.2.3插值表达式
花括号:只能写在标签体内,不能用在标签内。用v-bind解决
{{}}必须有返回值
5.2.4 单向绑定v-bind

html 属性不能使用双大括号形式绑定,我们可以使用 v-bind 指令给 HTML 标签属性绑定值;

而且在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。

v-bind :style 的对象语法十分直观,看着非常像 CSS ,但其实是一个 JavaScript 对象。style 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case ,这种方式记得用单引号括起 来) 来命名。

例如:font-size–>fontSize

Vue2.x写法




    
    
    
    Document



    
    
gogogo 你好

Vue3.x写法




    
    
    
    Document


    
    
gogogo 'active':isActive,'text-danger':hasError}" v-bind:style="{'color':color1,'font-size':size}" >你好

v-bind在标签内可以不写,直接用 :代替即可

5.2.5 双向绑定v-model

刚才的 v-text、v-html、v-bind 可以看做是单向绑定,数据影响了视图渲染,但是反过来就不 行。接下来学习的 v-model 是双向绑定,视图(View )和模型(Model)之间会互相影响。

既然是双向绑定,一定是在视图中可以修改数据,这样就限定了视图的元素类型。 目前 v-model 的可使用元素有:

- input

- select

- textarea

- checkbox

- radio

- components (Vue 中的自定义组件)

基本上除了最后一项,其它都是表单的输入项。

Vue2.x




    
    
    
    Document



    
    
精通的语言: java
PHP
Python
选中了 {{language.join(",")}}

Vue3.x




    
    
    
    Document


    
    
精通的语言: java
PHP
Python
选中了 {{language.join(",")}}
5.2.6 v-on
  1. 基本用法

    v-on 指令用于给页面元素绑定事件。

    语法: v-on:事件名="js 片段或函数名"

    另外,事件绑定可以简写,例如v-on:click='add'简写为 @click='add'

  2. 事件修饰符

    在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的 需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑, 而不是去处理 DOM 事件细节。

    为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。修饰符是由点开头的指令后缀来 表示的。

    • .stop :阻止事件冒泡到父元素
    • .prevent :阻止默认事件发生
    • .capture:使用事件捕获模式
    • .self :只有元素自身触发事件才执行。 (冒泡或捕获的都不执行)
    • .once:只执行一次
  3. 按键修饰符

    在监听键盘事件时,我们经常需要检查常见的键值。Vue 允许为 v-on 在监听键盘事件时添 加按键修饰符:

    
    
    

    记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名:

    < !-- 同上 -->
    
    < !-- 缩写语法 -->
    
    

    全部的按键别名:

    • .enter

    • .tab

    • .delete` (捕获“删除”和“退格”键)

    • .esc

    • .space

    • .up

    • .down

    • .left

    • .right

  4. 组合按键:

    可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

    • .ctrl

    • .alt

    • .shift

    • < !-- Alt + C -->
      
      < !-- Ctrl + Click -->
      
      Do something

Vue2.x





    
    
    
    Document



    

有{{num}}个赞

大div
小div
去百度

提示:

Vue3.x




    
    
    
    Document


    
    

有{{num}}个赞

大div
小div
去百度

提示:
5.2.7 v-for

遍历数据渲染页面是非常常用的需求,Vue 中通过 v-for 指令来实现

1. 遍历数组

​ 语法:v-for="item in items

  • items:要遍历的数组,需要在 vue 的 data 中定义好。
  • item:迭代得到的当前正在遍历的元素

2.数组角标

​ 在遍历的过程中,如果我们需要知道数组角标,可以指定第二个参数:

​ 语法:v-for="(item,index) in items"

  • items:要迭代的数组
  • item:迭代得到的数组元素别名
  • index:迭代到的当前元素索引,从 0 开始。

3.遍历对象

​ v-for 除了可以迭代数组,也可以迭代对象。语法基本类似

​ 语法:

  • v-for=“value in object” // 1 个参数时,得到的是对象的属性值
  • v-for=“(value,key) in object” //2 个参数时,第一个是属性值,第二个是属性名
  • v-for=“(value,key,index) in object” //3 个参数时,第三个是索引,从 0 开始

遍历的时候都加上:key来区分不同数据,提高vue渲染效率

Vue2.x与Vue3.x在v-for和v-if上的区别

vue2.x
在同一个元素上同时使用v-if和v-for,v-for会优先使用;

vue3.x
v-if总是优先于v-for生效

如果Vue3.x需要在遍历的时候使用v-if怎么写?

  •  
{{item.text}} ```

Vue2.x





    
    
    
    Document




    
  • 当前索引:{{index}} ==> {{user.name}} ==> {{user.gender}} ==>{{user.age}}
    对象信息: {{k}}=={{v}}=={{i}};

Vue3.x





    
    
    
    Document



    
    
5.2.8 v-if和v-show

v-if ,顾名思义,条件判断。当得到结果为true 时,所在的元素才会被渲染

v-show ,当得到结果为true 时,所在的元素才会被显示。

  • 「注意,v-show是改变元素的display属性而v-if的结果为false是直接不显示整个元素」

语法:v-if="布尔表达式", v-show="布尔表达式"

Vue2.x与Vue3.x在v-for和v-if上的区别

vue2.x
在同一个元素上同时使用v-if和v-for,v-for会优先使用;

vue3.x
v-if总是优先于v-for生效

Vue2.x





    
    
    
    Document



    
    

if=看到我....

show=看到我

Vue3.x




    
    
    
    Document


    
    

if=看到我....

show=看到我

5.2.9 v-else和v-else-if

v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

Vue2.x





    
    
    
    Document



    
{{random}}

看到我啦?! ">>= 0.75

看到我啦?! ">>= 0.5

看到我啦?! ">>= 0.2

看到我啦?! < 0.2

Vue3.x




    
    
    
    Document


    
    
{{random}}

看到我啦?! ">>= 0.75

看到我啦?! ">>= 0.5

看到我啦?! ">>= 0.2

看到我啦?! < 0.2

5.2.10 计算属性和侦听器
  1. 计算属性(computed)

    某些结果是基于之前数据实时计算出来的,我们可以利用计算属性来完成

    效果:只要依赖的属性发生变化,就会重新计算这个属性

  2. 侦听(watch)

    watch 可以让我们监控一个值的变化。从而做出相应的反应。

Vue2.x





    
    
    
    Document



    
  • 西游记; 价格:{{xyjPrice}},数量:
  • 水浒传; 价格:{{shzPrice}},数量:
  • 总价:{{totalPrice}}
  • {{msg}}

Vue3.x





    
    
    
    Document



    

    
  • 西游记; 价格:{{xyjPrice}},数量:
  • 水浒传; 价格:{{shzPrice}},数量:
  • 总价:{{totalPrice}}
  • {{msg}}
5.2.11 过滤器

过滤器(filters)

过滤器不改变真正的data ,而只是改变渲染的结果,并返回过滤后的版本。在很多不同的 情况下,过滤器都是有用的,比如尽可能保持 API 响应的干净,并在前端处理数据的格式。

  • 针对于Vue2.x
  1. 局部过滤器

    注册在当前 vue 实例中,只有当前实例能用

  2. 全局过滤器

    过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:

    • 双花括号插值和 v-bind 表达式
  • 针对于Vue3.x

2020年9月份,vue3出来了。增加了很多新功能,但是也删掉了一些功能。比如删掉了vue2中的过滤器filter功能。与此同时,官方建议:用方法调用或计算属性替换过滤器。下面Vue3.x具体案例有写实现方式

    • 注意事项
    • // 计算属性要return一个函数接收参数

Vue2.x





    
    
    
    Document



    
    
  • {{user.id}} ==> {{user.name}} ==> {{user.gender == 1?"男":"女"}} ==> {{user.gender | genderFilter}} ==> {{user.gender | gFilter}}

Vue3.x





    
    
    
    Document



    

    
  • {{user.id}} ==> {{user.name}} ==> {{user.gender == 1?"男":"女"}}
    ==> 局部过滤器 : {{user.gender | genderFilter}}
    ==> 计算属性过滤器实现 : {{gFilter(user.gender)}}
    ==> 方法过滤器实现 : {{gFilterMethod(user.gender)}}

看到了叭,filter过滤器能加工数据,computed计算属性和methods方法也都可以加工数据,这样的话,就重复了…

vue3删除了filter就好比:

员工filter会干的活,员工computed和员工methods也会干,而且比员工filter干得多,干的好。这样的话,老板vue就把filter开除了,filter就被fired了。毕竟多一个员工,多一些用工成本(员工filter哇的一声哭了出来)

5.2.12 组件化
在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相
同的部分。
例如可能会有相同的头部导航。
但是如果每个页面都自开发,这无疑增加了我们开发的成本。所以我们会把页面
的不同分拆分成立的组件,然后在不同页面就可以共享这些组件,避免重复开发。
在vue里,所有的vue实例都是组件

组件其实也是一个vue实例,因此它在定义时也会接收:data、methods、生命周期函等

不同的是组件不会与页面的元素綁定,否则就无法复用了,因此没有el属性。
但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组了
data必须是一个函数,不再是一个对象。

1.全局组件:我们通过 Vue 的 component 方法来定义一个全局组件。

2.组件的复用:定义好的组件,可以任意复用多次

3.局部组件:一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着 Vue 的加载而加载。 因此,对于一些并不频繁使用的组件,我们会采用局部注册。

  • components 就是当前 vue 对象子组件集合。
    • 其 key 就是子组件名称
    • 其值就是组件对象名
  • 效果与刚才的全局注册是类似的,不同的是,这个 counter 组件只能在当前的 Vue 实例 中使用

Vue2.x





    
    
    
    Document




    

Vue3.x





    
    
    
    Document



    

    
5.2.13 生命周期钩子函数

生命周期

每个 Vue 实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模 板等等。Vue 为生命周期中的每个状态都设置了钩子函数(监听函数)。每当 Vue 实例处于 不同的生命周期时,对应的函数就会被触发调用。
生命周期:你不需要立马弄明白所有的东西。

钩子函数「Vue2.x」

  • beforeCreated:我们在用 Vue 时都要进行实例化,因此,该函数就是在 Vue 实例化时调 用,也可以将他理解为初始化函数比较方便一点,在 Vue1.0 时,这个函数的名字就是 init。
  • created :在创建实例之后进行调用。
  • beforeMount :页面加载完成,没有渲染。如:此时页面还是{{name}}
  • mounted :我们可以将他理解为原生 js 中的 window.οnlοad=function({.,.}),或许大家也在 用 jquery,所以也可以理解为 jquery 中的$(document).ready(function(){ … .}),他的功能就 是 :在 dom 文档渲染完毕之后将要执行的函数 ,该函数在 Vue1.0 版本中名字为 compiled 。 此时页面中的{{name}}已被渲染成张三
  • beforeDestroy:该函数将在销毁实例前进行调用
  • destroyed :改函数将在销毁实例时进行调用。
  • beforeUpdate :组件更新之前。
  • updated :组件更新之后。

钩子函数「Vue3.x」

  • setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method

  • onBeforeMount() : 组件挂载到节点上之前执行的函数;

  • onMounted() : 组件挂载完成后执行的函数;

  • onBeforeUpdate(): 组件更新之前执行的函数;

  • onUpdated(): 组件更新完成之后执行的函数;

  • onBeforeUnmount(): 组件卸载之前执行的函数;

  • onUnmounted(): 组件卸载完成后执行的函数;

  • onActivated(): 被包含在 中的组件,会多出两个生命周期钩子函数,被激活时执行;

  • onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;

  • onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。
    PS: 使用**** 组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用**** 组件解决。

    与 2.x 版本生命周期相对应的组合式 API
    • beforeCreate -> 使用 setup()
    • created -> 使用 setup()
    • beforeMount -> onBeforeMount
    • mounted -> onMounted
    • beforeUpdate -> onBeforeUpdate
    • updated -> onUpdated
    • beforeDestroy -> onBeforeUnmount
    • destroyed -> onUnmounted
    • errorCaptured -> onErrorCaptured

    可以发现:

    1. beforeCreate 和 created 与 setup 几乎是同时进行的,所以可以把写在beforeCreate 和 created 这两周期的代码直接写在 setup 里即可。
    2. 命名都形如 onXXX。
    3. beforeDestroy 和 destroyed 改为 onBeforeUnmount 和 onUnmounted ,更语义化了。

Vue2.x





    
    
    
    Document



    
{{num}}

{{name}},有{{num}}个人点赞

Vue3.x





    
    
    
    Document



    

    
{{num}}

{{name}},有{{num}}个人点赞

5.2.14 使用Vue脚手架进行开发

Vue2.x

全局安装webpack
1 npm install webpack -g
全局安装vue脚手架
2 npm install -g @vue/cli-init
3 初始化vue项目
vue init webpack appname:vue脚手架使用webpack模板初始化一个appname项目
4 启动vue项目
项目的package.json中有scripts,代表我们能运行的命令
npm start = npm run dev: 启动项目
npm run build:将项目打包

Vue3.x

Vite 是一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动。

通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目。

使用 npm:

# npm 6.x
$ npm init vite@latest  --template vue

# npm 7+,需要加上额外的双短横线
$ npm init vite@latest  -- --template vue

$ cd 
$ npm install
$ npm run dev
5.2.15 使用element-ui

Vue2.x安装element-ui

Vue3.x安装element-ui

Vue2.x案例

推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用。
vue2.x
npm i element-ui -S

在 main.js 中添加以下内容:
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

Vue3.x案例

# NPM
# Vue2.x
$ npm install element-plus --save

在 main.js 中添加以下内容:
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)

app.use(ElementPlus)
app.mount('#app')
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/840150.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号