0. 课前说明

0.1 课程内容

SpringCloud + SpringCloud alibaba

0.2 技术要求

java8+maven+git、github+Nginx+RabbitMQ+SpringBoot2.0

0.3 课程大纲

  • 零基础:1~4章
  • 初级:5~9章
  • 中级:10~16章
  • 高级:17~21章

1. 微服务架构零基础理论入门(小白必看)

1.1 大纲

sentinel spring cloud版本_spring cloud

1.2 理论介绍

1.2.1 微服务架构概述

1)什么是微服务

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相协作(通常是基于HTP协议的RESTful API)。每个服务都围绕着具本业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言)应根据上下文,选择合适的语言、工具对其进行构建。

2)主题词01:95后数字化生活-落地维度
  • 以下一系列的商品可以是来自不同的品牌,也可以是都来自于一个品牌比如华为。微服务也是如此,选用同一个厂家来提供所有的解决方案,它的兼容性会更好。
3)主题词02:分布式微服务架构-落地维度
  • 满足哪些维度?
  • 支撑起这些维度的具体技术?? ? ?
4)服务调用关系
  • 服务提供者:暴露接口给其它微服务调用
  • 服务消费者:调用其它微服务提供的接口
  • 提供者与消费者角色其实是相对
  • 一个服务可以同时是服务提供者和服务消费者
  • eg:A调用B,B调用C。那么B相对于A来说是服务提供者,B相对于C来说是服务的消费者。

1.2.2 Spring Cloud简介.

  • 是什么?
    SpringCloud=分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶
  • 猜猜SpringCloud这个大集合里有多少种技术?
  • sentinel spring cloud版本_微服务_02

  • SpringCloud俨然已成为微服务开发的主流技术栈,在国内开发者社区非常火爆。
  • eg:18年京东的促销节的系统架构:
  • sentinel spring cloud版本_spring cloud_03

  • eg:阿里其中一个系统的架构:
  • sentinel spring cloud版本_spring cloud_04

1.2.3 Spring Cloud技术栈

  • Spring Cloud技术栈包含二十多种技术,当然不可能全部用到,有些技术反而做的不是太好,所以我们在这里只学习经过各大厂商实践和磨砺脱颖而出的一些最主流、常见和常用的技术。
  • sentinel spring cloud版本_spring_05

  • 目前微服务架构通用的技术:
  • sentinel spring cloud版本_spring_06

2. boot和cloud版本选择

2.1 大纲

sentinel spring cloud版本_spring cloud_07

2.2 本次SpringCloud分为上下篇

  • 上篇:SpringBoot2.X版和SpringCloud H版
  • 下篇:SpringCloud Alibaba

2.3 Springboot版本选择

  • git源码地址:https://github.com/spring-projects/spring-boot/releases/(本视频看的最新预发布版本是v2.3.0.M2)
  • sentinel spring cloud版本_spring cloud_08

  • SpringBoot2.0新特性:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes
  • 通过上面官网发现,Boot官方强烈建议你升级到2.X以上版本(2020.2-本视频)
  • SpringBoot3.0新特性:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes
  • 通过上面官网发现,Boot官方强烈建议你升级到3.X以上版本(2023.8-现在)
  • 官网看Boot版本:springboot(截至2023.8.17)

2.4 Springcloud版本选择

  • git源码地址:https://github.com/spring-projects/spring-cloud
  • sentinel spring cloud版本_Cloud_09

  • 官网:https://spring.io/projects/spring-cloud
  • 官网看Cloud版本:springcloud(截至2023.8.17)
  • sentinel spring cloud版本_微服务_10

2.5 Springcloud和Springboot之间的依赖关系如何看

2.6 SpringCloud第二季定稿版(截止2020.2.15)

本视频用到的软件版本:

  • cloud:Hoxton.SR1
  • boot: 2.2.2.RELEASE
  • cloud alibaba:2.1.0.RELEASE
  • Java:Java8
  • Maven:3.5及以上
  • Mysql:5.7及以上

题外话:boot版已经到2.2.4为最新,为什么选2.2.2?

  • 只用boot,可以直接使用最新版本,但是要同时使用boot和cloud,需要照顾cloud,由cloud决定boot版本

3. 关于Cloud各种组件的停更/升级/替换

3.1 大纲

sentinel spring cloud版本_spring_11

3.2 由停更引发的“升级惨案”

  • 停更不停用
  • 被动修复bugs:小bug没人管了
  • 不再接受合并请求
  • 不再发布新版本
  • 明细条目
  • 以前
  • sentinel spring cloud版本_架构_12

  • now2020
  • 服务注册中心:Eureka(原来SpringCloud原生自带的,停更不停用)-----》ZooKeeper、Consul、Nacos(现在)
  • 服务调用:Ribbon(cloud老产品还在用)----》LoadBalancer(cloud即将退出的新品,现在已经推出来了)
  • 服务调用2:Feign----》OpenFeign
  • 服务降级:Hystrix----》resilience4j(国外用的比较多)、sentienl(阿里的,国内用的比较多)
  • 服务网:Zuul----》Zuul2(没推出来)、gateway(spring提供)
  • 服务配置:Config----》Nacos(阿里)
  • 服务总线:Bus----》Nacos(阿里)

3.3 参考资料见官网

  • Spring Cloud
  • https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
  • sentinel spring cloud版本_spring cloud_13

  • Spring Cloud中文文档:https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md
  • sentinel spring cloud版本_微服务_14

  • Spring Boot
  • https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/
  • sentinel spring cloud版本_spring_15


  • 注意以上的版本都不是最新版。

4. 微服务架构编码构建

4.1 大纲

sentinel spring cloud版本_spring cloud_16

4.2 搭建父工程

4.2.1 微服务cloud整体聚合父工程Project

说明:IDEA里面没有工作空间的概念,所以新建project工作空间就是创建工程。

  • 创建:父工程名字(cloud2020)、包名(com.atguigu.springcloud)、以Maven方式创建
  • sentinel spring cloud版本_微服务_17

  • 配置Maven:每次新创建一个Project都要重新配置一下Maven,idea的其它配置只要配置一次即可
  • sentinel spring cloud版本_Cloud_18

  • 设置编码
  • sentinel spring cloud版本_spring cloud_19

  • 注解生效激活
  • sentinel spring cloud版本_Cloud_20

  • java编译版本选17
  • sentinel spring cloud版本_spring_21

4.2.2 父工程pom文件

说明:

  • 本次学习还是按照老师的版本来学。
  • 父工程的src目录没用可以删掉
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!--项目坐标-->
    <groupId>com.atguigu.springcloud</groupId>
    <artifactId>cloud2020</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--表示此项目是个父工程-->
    <packaging>pom</packaging>

    <!-- 统一管理jar包版本 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17/</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <!--德鲁伊的版本号-->
        <druid.version>1.1.16</druid.version>
        <!--mybatis和spring.boot整合的版本号-->
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>

    <!--子模块继承之后,提供作用:锁定版本+子module不用写groupId和version-->
    <dependencyManagement>
        <!-- 下面三个基本是微服务架构的标配 -->
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
                <scope>runtime</scope>
            </dependency>
            <!-- druid-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>

            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</version>
            </dependency>
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <!--log4j-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.12.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

4.2.3 pom文件细节学习

1) Maven中的DependencyManagement和Dependencies
  • Maven使用dependencyManagement元素来提供了一种管理依赖版本号的方式
  • 通常会在一个组织或者项目的最顶层的父POM中看到dependencyManagement元素。
  • 使用pom.xml中的dependencyManagement元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用这个dependencyManagement元素中指定的版本号。

举例

  • 父项目的pom.xml
<dependencyManagement>
    <dependencies>
        <dependency>
        <groupId>mysq1</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.2</version>
        </dependency>
        ...
    <dependencies>
</dependencyManagement>
  • 子项目的pom.xml:在添加mysql-connector时就可以不指定版本号
<dependencies>
    <dependency>
    <groupId>mysq1</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

这样做的好处就是

  • 如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改;
  • 另外如果某个子项目需要另外的一个版本,只需要声明自己的version就可。

注意事项

  • dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。
  • 如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom。
  • 如果子项目中指定了版本号,那么会使用子项目中指定的jar版本
2) maven中跳过单元测试

sentinel spring cloud版本_Cloud_22

4.2.4 父工程发布到仓库

  • 父工程创建完成执行mvn:install将父工程发布到仓库方便子工程继承

4.3 构建子工程:支付模块

4.3.1 微服务提供者支付Module模块

微服务提供者支付Module模块(cloud-provider-payment8001)

步骤:

  • 建module
  • sentinel spring cloud版本_spring cloud_23

  • 创建完成后请回到父工程查看pom文件变化
  • sentinel spring cloud版本_spring_24

  • 改pom
  • sentinel spring cloud版本_spring cloud_25

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8001</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!--web场景启动依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--boot指标监控依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <!--子工程写了版本号,就使用子工程的版本号,如果没写版本,找父工程中规定的版本号-->
            <version>1.1.20</version>
        </dependency>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
  • 写yml
#微服务建议一定要写服务端口号和微服务名称
server:
  #端口号
  port: 8001

spring:
  application:
    #微服务名称
    name: cloud-payment-service
  #数据库配置
  datasource:
    #引入的数据库驱动类型
    type: com.alibaba.druid.pool.DruidDataSource
    #mysql5.x的没有cj
    driver-class-name: com.mysql.jdbc.Driver
    #记得先创建数据库
    url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root

#mybatis配置
mybatis:
  mapper-locations: classpath:mapper/*.xml #mapper.xml文件的位置
  type-aliases-package: com.angenin.springcloud.entities  #所有Entity别名类所在包(所有实体类所在的包)
  • 主启动类:在java包下创建主启动类com.angenin.springcloud.PaymentMain8001
package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
    }
}
  • 业务类:
  • 建表SQL
  • entities
  • dao
  • service
  • controller

4.3.2 业务类详解

  • 建表SQL:先创建数据库db2020
CREATE TABLE `payment`(
	`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
	`serial` VARCHAR(200) DEFAULT '',
	PRIMARY KEY(`id`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO payment(`serial`)VALUES("张三");

select * from payment
  • entities:在springcloud包下新建实体类entities.Payment
package com.angenin.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

//这三个注解是lombok的,除了导入依赖,idea还需要安装插件(具体操作问度娘)
@Data   //set/get方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor  //无参构造器
public class Payment implements Serializable {
    private long id; //创建表的这个字段用的是BIGINT类型
    private String serial;
}
  • entities:在entities包下新建CommonResult(json封装体,传给前端的)
package com.angenin.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//返回给前端的通用json数据串
@Data   //set/get方法
@AllArgsConstructor //全参构造器
@NoArgsConstructor  //无参构造器
public class CommonResult<T> { //使用泛型比较通用,根据传入的实体类行来进行对应的展现。
    private Integer code;  //状态码
    private String message; //异常提示信息说明
    private T data; //泛型,对应类型的json数据

    //自定义两个参数的构造方法(全参的由注解生成)
    public CommonResult(Integer code, String message){
        this(code, message, null);
    }
}
  • dao:在springcloud包下新建Dao.PaymentDao接口
package com.angenin.springcloud.Dao;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper  //mybatis提供的
public interface PaymentDao{
    //增
    int create(Payment payment);

    //改     加上@Param注解,mapper中就可以采用#{}的方式把@Param注解括号内的参数进行引用
    Payment getPaymentById(@Param("id") Long id);

    //这里用增和改进行演示,有兴趣的可以自己加其他的方法

}
  • mapper.xml:在resources目录下新建mapper目录,然后新建PaymentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.angenin.springcloud.Dao.PaymentDao">

    <resultMap id="BaseResultMap" type="com.angenin.springcloud.entities.Payment">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <id column="serial" property="serial" jdbcType="VARCHAR"/>
    </resultMap>


    <!--  增  -->
    <!--  Payment标红了不用管,因为我们已经在yml文件中指定了Payment的位置了  -->
    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial)values(#{serial});
    </insert>

    <!--  改  -->
    <!--返回用resultMap,防止命名不规范-->
    <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
        select * from payment where id=#{id};
    </select>
</mapper>
  • service:在springcloud包下新建service.PaymentService接口
package com.angenin.springcloud.service;

import com.angenin.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;


public interface PaymentService {

    int create(Payment payment);

    Payment getPaymentById(@Param("id") Long id);
}
  • service:在service包下新建impl.PaymentServiceIpml实现类
package com.angenin.springcloud.service.impl;


import com.angenin.springcloud.Dao.PaymentDao;
import com.angenin.springcloud.entities.Payment;
import com.angenin.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Resource   //这是java自带的,@Autowired也可以 是spring提供的
    private PaymentDao paymentDao;

    @Override
    public int create(Payment payment) {
        return paymentDao.create(payment);
    }

    @Override
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }
}
  • controller:在springcloud包下新建controller.PaymentController
package com.angenin.springcloud.controller;

import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import com.angenin.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@RestController
@Slf4j  //日志
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    //前后端分离,所以不能直接返回对象,数据要先经过CommonResult封装再返回
    @PostMapping("/payment/create")
    public CommonResult create(@RequestBody Payment payment){
        int result = paymentService.create(payment);
        log.info("******插入的数据为:" + payment);
        log.info("******插入结果:" + result);

        if(result > 0){
            //插入成功
            return new CommonResult(200, "插入数据库成功", result);
        }else{
            return new CommonResult(444, "插入数据库失败",null);
        }
    }


    @GetMapping("/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        Payment payment = paymentService.getPaymentById(id);
        log.info("******查询结果:" + payment);

        if(payment != null){
            //查询成功
            return new CommonResult(200, "查询成功", payment);
        }else{
            return new CommonResult(444, "没有对应记录,查询ID:" + id,null);
        }
    }

}

4.3.3 测试

  • 启动项目
  • 注意:浏览器只支持get不支持post
  • 测试get请求:浏览器输入http://localhost:8001/payment/get/1,查询成功。
  • 测试post请求:使用Postman输入http://localhost:8001/payment/create发送post请求,往数据库中插入一条数据,需要把数据写到body中。

4.3.4 Run和Run DashBoard/Services

  • Run:项目比较少时使用的是run窗口启动项目
  • sentinel spring cloud版本_微服务_26

  • Run DashBoard:项目多了之后idea会自动切换到此窗口进行启动(新版本idea改名为Services
  • 好处:此窗口可以更好地启动多系列环境的微服务
  • 一般情况下项目多了之后idea会自动切换,如果切换不了需要进行以下配置
  • 通过修改idea的workspace.xml的方式来快速打开Run Dashboard窗口
  • sentinel spring cloud版本_spring_27

    sentinel spring cloud版本_Cloud_28


  • sentinel spring cloud版本_Cloud_29

  • 开启Run DashBoard/Services(idea新版本叫法)
  • sentinel spring cloud版本_spring cloud_30

<component name="RunDashboard">
    <option name="configurationTypes">
      <set>
        <option value="SpringBootApplicationConfigurationType" />
      </set>
    </option>
</component>
  • 部分同学可能由于idea版本不同,需要关闭重启

4.4 热部署Devtools(选做)

  • 每次代码修改后不需要手动重启,它会自动重启。
  • 开发时使用,生产环境关闭

4.4.1 Adding devtools to your project

  • 添加jar包:之前子项目已经导入过了
<!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

4.4.2 Adding plugin to your pom.xml

  • 添加一个插件到pom.xml中(之前父项目已经插入过了)
<build>
        <!--你自己的工程名字。这一步写不写都行-->
        <!--<finalName>cloud2020</finalName>-->
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.12.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

4.4.3 Enabling automatic build

  • 开启自动编译的选项

4.4.4 Update the value of

  • 热注册开启
  • idea2021.2以下版本
  • 组合键Shift+Ctrl+Alt+/(Mac系统的把Ctrl换成command键),选中Registry…
  • idea2021.2及以上版本
  • 重启IDEA:修改代码后会自动重启(效果非常慢,和电脑性能有关)
  • 测试后把热部署关闭掉,电脑性能不好。

4.5 构建子工程:消费者订单模块

4.5.1 微服务消费者订单Module模块

微服务消费者订单Module模块(cloud-consumer-order80)

  • 建cloud-consumer-order80
  • sentinel spring cloud版本_Cloud_31

  • 改POM
  • sentinel spring cloud版本_spring_32

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-order80</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
  • 写YML:在resources目录下新建application.yml文件
#访问一个网站时,默认是80端口,给用户80端口,用户就可以不用加端口直接访问页面
server:
  port: 80
  • 主启动
package com.angenin.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
    }
}
  • 业务类

4.5.2 业务类详解

  • 问题:业务类在客户端是否也要写数据层、业务层、控制层呢???
  • 答:不需要,只需要控制层,以及实体类。
  • 解释:当前场景是消费者80去调用8081微服务提供者,真正干活的是8081微服务提供者,所以消费者80只需要有一个控制层去调用服务提供者即可。
1)创建实体类
  • 和之前的字符模块的子项目中的实体类相同:
package com.angenin.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//返回给前端的通用json数据串
@Data   //set/get方法
@AllArgsConstructor //全参构造器
@NoArgsConstructor  //无参构造器
public class CommonResult<T> { //使用泛型比较通用,根据传入的实体类行来进行对应的展现。
    private Integer code;  //状态码
    private String message; //异常提示信息说明
    private T data; //泛型,对应类型的json数据

    //自定义两个参数的构造方法(全参的由注解生成)
    public CommonResult(Integer code, String message){
        this(code, message, null);
    }
}


-----------------------------------------------

package com.angenin.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

//这三个注解是lombok的,除了导入依赖,idea还需要安装插件(具体操作问度娘)
@Data   //set/get方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor  //无参构造器
public class Payment implements Serializable {
    private long id; //创建表的这个字段用的是BIGINT类型
    private String serial;
}
2)RestTemplate介绍
  • 场景:现在是需要2个服务之间进行调用,80端口调用8001,在原始web阶段学习了2个之间的服务通信用的是协议httpClient,现在用的是封装后的restTemplate,它封装了一次httpClient。可以实现订单微服务和支付微服务之间的横向调用。

sentinel spring cloud版本_spring_33

  • 是什么?
  • RestTemplate提供了多种便捷访问远程Http服务的方法, 是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集
  • 官网及使用:
  • 官网地址:(以spring5为例)
    https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
  • 使用:
    使用restTemplate访问restful接口非常的简单粗暴无脑。(url, requestMap, ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
3)config配置类

说明:Springboot是容器类的方式,所以要将RestTemplate这个对象注入到Springboot容器中。

sentinel spring cloud版本_spring cloud_34

package com.angenin.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {

    //往容器中添加一个RestTemplate
    //RestTemplate提供了多种便捷访问远程http访问的方法
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}
4)controller
  • 在springcloud包下新建controller.OrderController
package com.angenin.springcloud.controller;

import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderController {

    public static final String PAYMENT_URL = "http://localhost:8001";

    @Resource
    private RestTemplate restTemplate;

    //因为浏览器只支持get请求,为了方便这里就用get
    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        log.info("********插入的数据:" + payment);
        //postForObject分别有三个参数:请求地址,请求参数,返回的对象类型----写操作
        return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        log.info("********查询的id:" + id);
        //getForObject两个参数:请求地址,返回的对象类型----读操作
        return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
    }
}

4.5.3 测试

  • 启动消费者、生产者
  • 在浏览器中输入http://localhost/consumer/payment/get/1成功查询到数据。(80可以省略----测试查询)
  • 在浏览器中输入http://localhost/consumer/payment/create?serial=王五成功查询到数据。(测试插入数据)
  • 注意:只有子项目支付模块加上了@RequestBody注解才能插入成功。
  • @RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。
  • 如果运行窗口没有自动由Run切换到Run DashBoard,需要进行配置,详情查看4.3.4

4.6 工程重构

  • 观察问题:系统中有重复部分,重构。
  • 解决:把重复和相似的代码提取到一个公开公用的一个工程中,供大家统一调配使用。
  • 这个工程不但可以提交重复的代码,而且可以将服务的接口、第三方的接口、工具类都可以当到此工程中。

4.6.1 创建公共工程:cloud-api-commons

  • 使用maven构建或者boot插件Spring Initializr构建都可以
  • maven构建:不需要联网,需要手动添加主启动类,配置类,手动添加jar包。
  • 插件Spring Initializr构建:需要联网,会自动创建主启动类,配置类,基础jar包、测试类。当然额外的jar包也需要手动添加。
  • static目录是加了web依赖后才生成的。

sentinel spring cloud版本_Cloud_35

4.6.2 修改pom文件

  • Hutool只是一个JAVA工具包,有助于简化代码,避免重复造轮子,每个程序员都有自己的工具包,它代表了你工作的积累,Hutool只是收集了大家积累的工具,Hutool几乎涵盖了工作中大部分业务的工具。
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-api-commons</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--   hutool是个功能强大的JAVA工具包,官网:https://hutool.cn/    -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.0</version>
        </dependency>
    </dependencies>


</project>

4.6.3 修改entitie实体类

  • 把通用的2个实体类复制到此公共工程中
package com.angenin.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//返回给前端的通用json数据串
@Data   //set/get方法
@AllArgsConstructor //全参构造器
@NoArgsConstructor  //无参构造器
public class CommonResult<T> { //使用泛型比较通用,根据传入的实体类行来进行对应的展现。
    private Integer code;  //状态码
    private String message; //异常提示信息说明
    private T data; //泛型,对应类型的json数据

    //自定义两个参数的构造方法(全参的由注解生成)
    public CommonResult(Integer code, String message){
        this(code, message, null);
    }
}

************************************************
package com.angenin.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

//这三个注解是lombok的,除了导入依赖,idea还需要安装插件(具体操作问度娘)
@Data   //set/get方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor  //无参构造器
public class Payment implements Serializable {
    private long id; //创建表的这个字段用的是BIGINT类型
    private String serial;
}

4.6.4 maven命令clean install

  • 把这个公共的项目打包到发布到公用的本地仓库里面,以便其它另外2个工程调用。

4.6.5 订单80和支付8001分别改造

  • 删除各自的原先有过的entities文件夹
  • 各自粘贴POM内容
<!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.angenin.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

4.6.6 测试

  • 启动生产者 消费者
  • 分别测试:查询 插入
    http://localhost/consumer/payment/get/1http://localhost/consumer/payment/create?serial=赵六
  • sentinel spring cloud版本_Cloud_36


  • sentinel spring cloud版本_Cloud_37


  • sentinel spring cloud版本_架构_38


4.6.7 目前工程样图

sentinel spring cloud版本_spring cloud_39