一、Spring Cloud(Base工程构建)

一、Spring Cloud(Base工程构建)

1.1 Spring Cloud 简述

1.1.1 Spring Cloud 版本推荐

  • 在讲解 Spring Cloud 之前,首先推荐一下各个依赖的版本,以免出现版本错误

  • 版本推荐

  • 必须根据以上版本,否则可能会出现一些不必要的错误

1.1.2 Spring Cloud 能做什么

  • 它是一种微服务架构的工具包
  • 可以帮助服务找到其他服务并互相连接
  • 能集中管理服务的设置信息
  • 有熔断和限流的功能,让系统更稳定
  • 可以把请求分摊到不同的服务实例上
  • 处理多个服务间的事务问题
  • 能监控服务的状态和性能

1.2.3 Spring Cloud 不同功能对应的不同的组件

Spring Cloud 可以用于实现很多功能,方便我们开发

这些功能都对应着Spring Cloud 中的不同的组件

以下是不同服务分别对应的组件

image-20240314133910116

1.2 微服务架构编码 Base 工程模块构建

这边我们直接使用项目来了解微服务

通过 下订单,做支付这个案例

先做 Base 工程,再依次添加各种模块组件

先简单的做一个通用的 boot微服务

然后逐步挨个引入 cloud 组件纳入微服务支撑体系

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

1、New Project

  • 新建项目,请按照我一下的配置进行创建

  • image-20240319172632663

  • 将这些多余的包删除,这个仅仅是作为我们 maven 的父工程

  • image-20240316104535170

2、聚合总父工程的名字

  • 这个就是父工程的名字
  • image-20240319172720836

3、字符编码

  • 设置字符编码为 UTF-8 ,以防出现乱码

  • image-20240316104839525

  • image-20240316105005801

4、注解激活生效

  • 当引入一些新的组件时,可能会激活不了,所以需要设置

  • image-20240316105236102

5、java 编译版本选择 17

  • image-20240316105338006

1.2.2 Maven 父工程 pom 文件内容

  • 在 maven 中添加 <packaging>pom</packaging>

  • 表示该项目作为一个父工程,用于组织和管理其他子项目的依赖关系、版本控制等

  • image-20240319172921463

  • 将以下依赖和版本复制进 pom文件中

  •  <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <hutool.version>5.8.22</hutool.version>
            <lombok.version>1.18.26</lombok.version>
            <druid.version>1.1.20</druid.version>
            <mybatis.springboot.version>3.0.3</mybatis.springboot.version>
            <mysql.version>8.0.11</mysql.version>
            <swagger3.version>2.2.0</swagger3.version>
            <mapper.version>4.2.3</mapper.version>
            <fastjson2.version>2.0.40</fastjson2.version>
            <persistence-api.version>1.0.2</persistence-api.version>
            <spring.boot.test.version>3.1.5</spring.boot.test.version>
            <spring.boot.version>3.2.0</spring.boot.version>
            <spring.cloud.version>2023.0.0</spring.cloud.version>
            <spring.cloud.alibaba.version>2022.0.0.0-RC2</spring.cloud.alibaba.version>
        </properties>
      
        <dependencyManagement>
            <dependencies>
                <!--springboot 3.2.0-->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-parent</artifactId>
                    <version>${spring.boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--springcloud 2023.0.0-->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring.cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--springcloud alibaba 2022.0.0.0-RC2-->
                <dependency>
                    <groupId>com.alibaba.cloud</groupId>
                    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                    <version>${spring.cloud.alibaba.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--SpringBoot集成mybatis-->
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>${mybatis.springboot.version}</version>
                </dependency>
                <!--Mysql数据库驱动8 -->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>${mysql.version}</version>
                </dependency>
                <!--SpringBoot集成druid连接池-->
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid-spring-boot-starter</artifactId>
                    <version>${druid.version}</version>
                </dependency>
                <!--通用Mapper4之tk.mybatis-->
                <dependency>
                    <groupId>tk.mybatis</groupId>
                    <artifactId>mapper</artifactId>
                    <version>${mapper.version}</version>
                </dependency>
                <!--persistence-->
                <dependency>
                    <groupId>javax.persistence</groupId>
                    <artifactId>persistence-api</artifactId>
                    <version>${persistence-api.version}</version>
                </dependency>
                <!-- fastjson2 -->
                <dependency>
                    <groupId>com.alibaba.fastjson2</groupId>
                    <artifactId>fastjson2</artifactId>
                    <version>${fastjson2.version}</version>
                </dependency>
                <!-- swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
                <dependency>
                    <groupId>org.springdoc</groupId>
                    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
                    <version>${swagger3.version}</version>
                </dependency>
                <!--hutool-->
                <dependency>
                    <groupId>cn.hutool</groupId>
                    <artifactId>hutool-all</artifactId>
                    <version>${hutool.version}</version>
                </dependency>
                <!--lombok-->
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>${lombok.version}</version>
                    <optional>true</optional>
                </dependency>
                <!-- spring-boot-starter-test -->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-test</artifactId>
                    <version>${spring.boot.test.version}</version>
                    <scope>test</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
  • <properties> 标签内的是依赖的版本号

    • 这样分开写版本号,是为了在子工程中添加依赖时,如果依赖没有添加版本号,则会直接使用父工程的版本
    • 更好的实现版本的统一
  • <dependencyManagement> 标签来提供一种管理依赖版本号的方式

    • 一般都会在 pom 父工程中使用
    • 它能够让所有子工程中不用显示的列出版本号
    • 因为 maven 会沿着父子层向上走,直接找到拥有 <dependencyManagement> 元素的项目
    • 然后子工程就会使用 <dependencyManagement> 元素中指定的版本号
    • 可以避免每个子项目中都要引入一个版本号
    • 如果子项目需要另外一个版本,只需要声明 <version> 即可
  • <dependencyManagement> 只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖

  • 如果不在子项目中声明依赖,是不会从父项目中继承下来的

  • 只有在子项目中写了该依赖,并没没有指定版本号,才会从父项目中该项

1.2.3 Mysql 驱动说明

1、如果是 Mysql5

  • JDBC 配置

  • # mysql5.7---JDBC四件套
    jdbc.driverClass = com.mysql.jdbc.Driver
    jdbc.url= jdbc:mysql://localhost:3306/db2024?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    jdbc.user = root
    jdbc.password =123456
    
  • pom 文件依赖

  • # Maven的POM文件处理
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
     
    

2、如果是 Mysql8

  • JDBC 配置

  • # mysql8.0---JDBC四件套
    jdbc.driverClass = com.mysql.cj.jdbc.Driver
    jdbc.url= jdbc:mysql://localhost:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
    jdbc.user = root
    jdbc.password =123456
    
  • pom 文件依赖

  • # MavenPOM
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.11</version>
    </dependency>
    

1.3 Mapper4 一键生成增删改查

1.3.1 数据库搭建

  • 生成增删改查代码之前,首先需要我们的 支付订单的数据库

  • 首先创建数据库,数据库名为 db2024

  • 然后创建数据表,将以下代码导入即可

  • DROP TABLE IF EXISTS `t_pay`;
    
     
    
    CREATE TABLE `t_pay` (
    
      `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    
      `pay_no` VARCHAR(50) NOT NULL COMMENT '支付流水号',
    
      `order_no` VARCHAR(50) NOT NULL COMMENT '订单流水号',
    
      `user_id` INT(10) DEFAULT '1' COMMENT '用户账号ID',
    
      `amount` DECIMAL(8,2) NOT NULL DEFAULT '9.9' COMMENT '交易金额',
    
      `deleted` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
    
      `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    
      `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    
      PRIMARY KEY (`id`)
    
    ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='支付交易表';
    
     
    
    INSERT INTO t_pay(pay_no,order_no) VALUES('pay17203699','6544bafb424a');
    
     
    
    SELECT * FROM t_pay;
    

1.3.2 在项目中创建第一个子工程

  • 创建一个子工程名为 mybatis_generator2024

  • 它与业务无关,就是一个普通的 maven 工程

  • 有他专门生成数据库的增删改查

  • image-20240316145005493

  • image-20240319173105684

  • 在子工程中导入这个模块所需的依赖

  • 复制替换子工程的 pom 文件即可

  • <?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>
        <parent>
            <groupId>com.atguigu.cloud</groupId>
            <artifactId>cloud2024</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <!--我自己独一份,只是一个普通Maven工程,与boot和cloud无关-->
        <artifactId>mybatis_generator2024</artifactId>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <dependencies>
            <!--Mybatis 通用mapper tk单独使用,自己独有+自带版本号-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.13</version>
            </dependency>
            <!-- Mybatis Generator 自己独有+自带版本号-->
            <dependency>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-core</artifactId>
                <version>1.4.2</version>
            </dependency>
            <!--通用Mapper-->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper</artifactId>
            </dependency>
            <!--mysql8.0-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!--persistence-->
            <dependency>
                <groupId>javax.persistence</groupId>
                <artifactId>persistence-api</artifactId>
            </dependency>
            <!--hutool-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
            </dependency>
            <!--lombok-->
            <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>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <build>
            <resources>
                <resource>
                    <directory>${basedir}/src/main/java</directory>
                    <includes>
                        <include>**/*.xml</include>
                    </includes>
                </resource>
                <resource>
                    <directory>${basedir}/src/main/resources</directory>
                </resource>
            </resources>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>1.4.2</version>
                    <configuration>
                        <configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
                        <overwrite>true</overwrite>
                        <verbose>true</verbose>
                    </configuration>
                    <dependencies>
                        <dependency>
                            <groupId>mysql</groupId>
                            <artifactId>mysql-connector-java</artifactId>
                            <version>8.0.33</version>
                        </dependency>
                        <dependency>
                            <groupId>tk.mybatis</groupId>
                            <artifactId>mapper</artifactId>
                            <version>4.2.3</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

1.3.3 设置各种配置

  • 这里需要设置数据库配置和生成增删改查的配置

  • 创建 config.properties 数据库配置文件

  • image-20240316150415056

  • #User表包名
    package.name=com.atguigu.cloud
    # mysql5.7
    jdbc.driverClass = com.mysql.jdbc.Driver
    jdbc.url= jdbc:mysql://localhost:3306/db2024?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    jdbc.user = root
    jdbc.password =123456
    
  • 创建自动生成配置文件 generatorConfig.xml

  • image-20240316150659251

  • <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    
    <generatorConfiguration>
        <properties resource="config.properties"/>
    
        <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
            <property name="beginningDelimiter" value="`"/>
            <property name="endingDelimiter" value="`"/>
    
            <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
                <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
                <property name="caseSensitive" value="true"/>
            </plugin>
    
            <jdbcConnection driverClass="${jdbc.driverClass}"
                            connectionURL="${jdbc.url}"
                            userId="${jdbc.user}"
                            password="${jdbc.password}">
            </jdbcConnection>
    
            <javaModelGenerator targetPackage="${package.name}.entities" targetProject="src/main/java"/>
    
            <sqlMapGenerator targetPackage="${package.name}.mapper" targetProject="src/main/java"/>
    
            <javaClientGenerator targetPackage="${package.name}.mapper" targetProject="src/main/java" type="XMLMAPPER"/>
    
            <table tableName="t_pay" domainObjectName="Pay">
                <generatedKey column="id" sqlStatement="JDBC"/>
            </table>
        </context>
    </generatorConfiguration>
    

1.3.4 一键生成增删改查

  • image-20240316150921837

  • 打开 pom 管理,找到 mybatis_generator2024 的模块,点击 mybatis-genertor:generate 即可一键生成

1.4 标准构建微服务工程

完整构建微服务的步骤

1、建 module 模块

2、改写 pom 文件

3、写 yml,启动类配置

4、创建主启动类

5、创建业务类

首先构建一个微服务的提供者,支付 Module 模块

1.4.1 构建提供者微服务模块

  • 提供者模块名为 cloud-provider-payment8001

  • image-20240316155909923

1.4.2 改写 pom 文件

  • 改写 pom 文件,将需要的依赖导入其中

  • <?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>
        <parent>
            <groupId>org.atguigu.com</groupId>
            <artifactId>cloud2024</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>cloud-provider-payment8001</artifactId>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
    
        <dependencies>
            <!--SpringBoot通用依赖模块-->
            <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>
            <!--SpringBoot集成druid连接池-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
            </dependency>
            <!-- Swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
            <dependency>
                <groupId>org.springdoc</groupId>
                <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            </dependency>
            <!--mybatis和springboot整合-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <!--Mysql数据库驱动8 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!--persistence-->
            <dependency>
                <groupId>javax.persistence</groupId>
                <artifactId>persistence-api</artifactId>
            </dependency>
            <!--通用Mapper4-->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper</artifactId>
            </dependency>
            <!--hutool-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
            </dependency>
            <!-- fastjson2 -->
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.28</version>
                <scope>provided</scope>
            </dependency>
            <!--test-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

1.4.3 编写 yml 文件,启动类配置

  • 编写 yml 文件,启动类的配置

  • server:
      port: 8001
    
    # ==========applicationName + druid-mysql8 driver===================
    spring:
      application:
        name: cloud-payment-service
    
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
        username: root
        password: 123456
    
    # ========================mybatis===================
    mybatis:
      mapper-locations: classpath:mapper/*.xml
      type-aliases-package: com.atguigu.cloud.entities
      configuration:
        map-underscore-to-camel-case: true
    
  • 并且创建一个 mapper 包

  • image-20240316160521841

1.4.4 创建主启动类

  • 创建主启动类,命名为 Main8001

  • image-20240319004538330

  • 添加 @MapperScan 注解

  • image-20240321184139430

  • 注意不要导错包

1.4.5 创建业务类

1、entities(实体类)

  • 创建两个实体 Pay 和 PayDTO

    • Pay 是主实体类
    • PayDTO 是给前端传递数据用的实体类
    • PayDTO 内的属性是前端传给后端的数据
  • Pay 实体类直接复制 mybatis-generator2024 模块内自动生成的实体类即可

  • image-20240316162034838

  • 然后创建 PayDTO 传递数据实体类

  • package com.atguigu.cloud.entities;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.math.BigDecimal;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class PayDTO {
        private Integer id;
        //支付流水号
        private String payNo;
        //订单流水号
        private String orderNo;
        //用户账号ID
        private Integer userId;
        //交易金额
        private BigDecimal amount;
    }
    
    
  • image-20240316162249475

2、mapper

  • 分别在 cloud 包下和 resources 包下创建 mapper 包

  • cloud 包下的 mapper 包存放接口

  • resources 包下的 mapper 存放 xml 文件

  • 也是同样复制 mybatis-generator2024 模块内自动生成的 mapper即可

  • image-20240316162628408

  • image-20240316162934370

3、Service

  • 创建服务接口 PayService,定义增删改查方法

  • image-20240316163741669

  • package com.atguigu.cloud.service;
    
    import com.atguigu.cloud.entities.Pay;
    
    import java.util.List;
    
    public interface PayService {
        //增
        public int add(Pay pay);
        //根据id删
        public int delete(Integer id);
        //改
        public int update(Pay pay);
        //根据id查
        public Pay getById(Integer id);
        //查询所有
        public List<Pay> getAll();
    }
    
    
    • 创建服务实现类 PayServiceImpl,实现增删改查方法
  • image-20240316164349748

  • package com.atguigu.cloud.service.impl;
    
    import com.atguigu.cloud.entities.Pay;
    import com.atguigu.cloud.mapper.PayMapper;
    import com.atguigu.cloud.service.PayService;
    import jakarta.annotation.Resource;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class PayServiceImpl implements PayService {
        @Resource
        PayMapper payMapper;
        @Override
        public int add(Pay pay) {
            return payMapper.insertSelective(pay);
        }
    
        @Override
        public int delete(Integer id) {
            //按照主键删除
            return payMapper.deleteByPrimaryKey(id);
        }
    
        @Override
        public int update(Pay pay) {
            //按照主键,主键不为空则更新
            return payMapper.updateByPrimaryKeySelective(pay);
        }
    
        @Override
        public Pay getById(Integer id) {
            //根据主键查
            return payMapper.selectByPrimaryKey(id);
        }
    
        @Override
        public List<Pay> getAll() {
            return payMapper.selectAll();
        }
    }
    
    

4、controller

  • 创建 PayController

  • image-20240318234657424

  • PayController 代码部分

  • package com.atguigu.cloud.controller;
    
    import cn.hutool.core.bean.BeanUtil;
    import com.atguigu.cloud.entities.Pay;
    import com.atguigu.cloud.entities.PayDTO;
    import com.atguigu.cloud.service.PayService;
    import jakarta.annotation.Resource;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    public class PayController {
        @Resource
        private PayService payService;
        @PostMapping("/pay/add")
        public String addPay(@RequestBody Pay pay){
            int add = payService.add(pay);
            return "添加成功,返回值"+add;
        }
        @DeleteMapping("/pay/delete/{id}")
        public Integer removePay(@PathVariable("id") Integer id){
    
            return payService.delete(id);
        }
        @PutMapping("/pay/update")
        public String updatePay(@RequestBody PayDTO payDTO){
            Pay pay=new Pay();
            BeanUtil.copyProperties(payDTO,pay);
            int i=payService.update(pay);
            return "修改成功,返回值"+i;
        }
        @GetMapping("pay/get/{id}")
        public Pay getById(@PathVariable("id") Integer id){
    
            return payService.getById(id);
        }
        @GetMapping("pay/getAll")
        public List<Pay> getAll(){
            return payService.getAll();
        }
    }
    
    

1.5 Swagger3 代码测试

Swagger3 是一个用于测试接口的框架

使用 Swagger3 之前需要导入一个依赖

 <!-- Swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        </dependency>

1.5.1 Swagger3 常用注解

  • 使用 Swagger3 需要在代码中嵌入注解

  • 以下是常用注解

  • 注解标注位置作用
    @Tagcontroller 类表示 controller 的作用
    @Parmeter参数标识参数作用
    @Parmeters参数参数多重说明
    @Schemamodel 层的 JavaBena描述模型作用及每个属性
    @Operation方法描述方法的作用
    @ApiResponse方法描述响应状态码等
    @Schema实体类或实体类字段描述实体类或实体类字段的作用
  • 在我们编写的 PayController 中加入注解

  • package com.atguigu.cloud.controller;
    
    import cn.hutool.core.bean.BeanUtil;
    import com.atguigu.cloud.entities.Pay;
    import com.atguigu.cloud.entities.PayDTO;
    import com.atguigu.cloud.service.PayService;
    import io.swagger.v3.oas.annotations.Operation;
    import io.swagger.v3.oas.annotations.tags.Tag;
    import jakarta.annotation.Resource;
    import org.springframework.beans.BeanUtils;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @Tag(name = "支付微服务模块",description = "支付CRUD")
    public class PayController {
        @Resource
        PayService payService;
    
        @PostMapping(value = "/pay/add")
        @Operation(summary = "新增", description = "新增支付流水方法,json串做参数")
        public String addPay(@RequestBody Pay pay) {
            System.out.println(pay.toString());
            int i = payService.add(pay);
            return "成功插入记录,返回值:" + i;
        }
    
        @DeleteMapping(value = "/pay/del/{id}")
        @Operation(summary = "删除", description = "删除支付流水方法")
        public Integer deletePay(@PathVariable("id") Integer id) {
            return payService.delete(id);
        }
    
        @PutMapping(value = "/pay/update")
        @Operation(summary = "修改", description = "修改支付流水方法")
        public String updatePay(@RequestBody PayDTO payDTO) {
            Pay pay = new Pay();
            BeanUtils.copyProperties(payDTO, pay);
    
            int i = payService.update(pay);
            return "成功修改记录,返回值:" + i;
        }
    
        @GetMapping(value = "/pay/get/{id}")
        @Operation(summary = "按照ID查流水", description = "查询支付流水方法")
        public Pay getById(@PathVariable("id") Integer id) {
            return payService.getById(id);
        }
    }
    
  • 在我们的实体类 Pay 中添加注解,描述实体类及字段的作用

  • package com.atguigu.cloud.entities;
    
    import io.swagger.v3.oas.annotations.media.Schema;
    
    import javax.persistence.Column;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import java.math.BigDecimal;
    import java.util.Date;
    
    /**
     * 表名:t_pay
    */
    @Table(name = "t_pay")
    @Schema(title = "支付交易表")
    public class Pay {
        @Id
        @GeneratedValue(generator = "JDBC")
        private Integer id;
    
        /**
         * 支付流水号
         */
        @Column(name = "pay_no")
        @Schema(title = "支付流水号")
        private String payNo;
    
        /**
         * 订单流水号
         */
        @Column(name = "order_no")
        @Schema(title = "订单流水号")
        private String orderNo;
    
        /**
         * 用户账号ID
         */
        @Column(name = "user_id")
        @Schema(title = "用户账号ID")
        private Integer userId;
    
        /**
         * 交易金额
         */
        private BigDecimal amount;
    
        /**
         * 删除标志,默认0不删除,1删除
         */
        private Byte deleted;
    
        /**
         * 创建时间
         */
        @Column(name = "create_time")
        @Schema(title = "创建时间")
        private Date createTime;
    
        /**
         * 更新时间
         */
        @Column(name = "update_time")
        @Schema(title = "更新时间")
        private Date updateTime;
    
        /**
         * @return id
         */
        public Integer getId() {
            return id;
        }
    
        /**
         * @param id
         */
        public void setId(Integer id) {
            this.id = id;
        }
    
        /**
         * 获取支付流水号
         *
         * @return payNo - 支付流水号
         */
        public String getPayNo() {
            return payNo;
        }
    
        /**
         * 设置支付流水号
         *
         * @param payNo 支付流水号
         */
        public void setPayNo(String payNo) {
            this.payNo = payNo;
        }
    
        /**
         * 获取订单流水号
         *
         * @return orderNo - 订单流水号
         */
        public String getOrderNo() {
            return orderNo;
        }
    
        /**
         * 设置订单流水号
         *
         * @param orderNo 订单流水号
         */
        public void setOrderNo(String orderNo) {
            this.orderNo = orderNo;
        }
    
        /**
         * 获取用户账号ID
         *
         * @return userId - 用户账号ID
         */
        public Integer getUserId() {
            return userId;
        }
    
        /**
         * 设置用户账号ID
         *
         * @param userId 用户账号ID
         */
        public void setUserId(Integer userId) {
            this.userId = userId;
        }
    
        /**
         * 获取交易金额
         *
         * @return amount - 交易金额
         */
        public BigDecimal getAmount() {
            return amount;
        }
    
        /**
         * 设置交易金额
         *
         * @param amount 交易金额
         */
        public void setAmount(BigDecimal amount) {
            this.amount = amount;
        }
    
        /**
         * 获取删除标志,默认0不删除,1删除
         *
         * @return deleted - 删除标志,默认0不删除,1删除
         */
        public Byte getDeleted() {
            return deleted;
        }
    
        /**
         * 设置删除标志,默认0不删除,1删除
         *
         * @param deleted 删除标志,默认0不删除,1删除
         */
        public void setDeleted(Byte deleted) {
            this.deleted = deleted;
        }
    
        /**
         * 获取创建时间
         *
         * @return createTime - 创建时间
         */
        public Date getCreateTime() {
            return createTime;
        }
    
        /**
         * 设置创建时间
         *
         * @param createTime 创建时间
         */
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    
        /**
         * 获取更新时间
         *
         * @return updateTime - 更新时间
         */
        public Date getUpdateTime() {
            return updateTime;
        }
    
        /**
         * 设置更新时间
         *
         * @param updateTime 更新时间
         */
        public void setUpdateTime(Date updateTime) {
            this.updateTime = updateTime;
        }
    }
    

1.5.2 创建迭代的 config 配置类

  • 使用 Swagger3 之前还需要创建含分组迭代的 config 配置类

  • 因此我们需要创建一个 Swagger3 相关的配置类

  • image-20240319002438753

  • 编写相关代码

  • package com.atguigu.cloud.config;
    
    import io.swagger.v3.oas.models.ExternalDocumentation;
    import io.swagger.v3.oas.models.OpenAPI;
    import io.swagger.v3.oas.models.info.Info;
    import org.springdoc.core.models.GroupedOpenApi;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class Swagger3Config {
    
        @Bean
        public GroupedOpenApi PayApi()
        {
            return GroupedOpenApi.builder().group("支付微服务模块").pathsToMatch("/pay/**").build();
        }
        @Bean
        public GroupedOpenApi OtherApi()
        {
            return GroupedOpenApi.builder().group("其它微服务模块").pathsToMatch("/other/**", "/others").build();
        }
        @Bean
        public OpenAPI docsOpenApi()
        {
            return new OpenAPI()
                    .info(new Info().title("cloud2024")
                            .description("通用设计rest")
                            .version("v1.0"))
                    .externalDocs(new ExternalDocumentation()
                            .description("www.atguigu.com")
                            .url("https://yiyan.baidu.com/"));
        }
    }
    
    
  • 我们微服务的接口会有很多,这个配置类就是专门进行了分组

  • 例如

  • image-20240319002706013

  • 这两个方法分别对应两个不同的模块

    • PayApi() 对应支付模块
    • OtherApi() 对应其他模块
  • PayApi() 方法中调用的 PathsToMatch() 方法当中的参数 /pay/** 就表示,只要开头为 /pay 的都属于这个模块

  • docsOpenApi() 方法中的内容则是对文档的一些说明

1.5.3 使用 Swagger3 进行测试

  • 运行启动类

  • 然后打开浏览器输入网址:http://localhost:8001/swagger-ui/index.html

  • 成功访问的界面

  • image-20240319005405605

  • 此时右上角就是你在配置类中定义的分组

  • image-20240319184525905

  • 这里进行测试即可

1.6 微服务工程项目改进

1.6.1 时间格式问题优化

  • 测试代码时,返回给我们的时间格式不是我们常用的类型

  • 这里我们可以使用两种方式来进行优化

1、在相应的类的属性上使用 @JsonFormat 注解

  • 在实体类的时间格式的属性上添加 @JsonFormat
  • image-20240322144814532

2、在 Spring boot 项目中还可以在 application.yml 文件中指定

  • 在 application.yml 文件中指定如下

  • spring:
    	jackson:
    		date-format: yyyy-MM-dd HH:mm:ss
    		time-zone:GMT+8
    

这里才是返回了我们想要的时间格式

image-20240322145103253

1.6.2 统一返回值格式

1、具体思路

  • 我们需要封装一个对象,给前端返回一个 KV 键值对

  • 定义返回的标准格式(三大标配)

    • code 状态值:由后端统一定义各种返回结果的状态码
    • message描述:本次接口调用的结果描述
    • data数据:本次返回的数据
    • code 和 message 就是我们的 key 值
    • data 就是我们的 value 值
  • 定义接口调用时间之类

    • 用于排查错误
    • 告诉程序员什么时候调用接口
    • 第几次调用接口,什么时间段出的故障
    • 这就会添加 timestamp :接口调用时间

2、主要步骤

  • 新建枚举类 ReturnCodeEnum

  • 让我们的状态码尽量与 HTTP 的相对应

  • HTTP 请求返回的状态码

  • image-20240322150233960

  • 定义 ReturnCodeEnum 枚举类

  • image-20240322151405544

  • 具体代码

  • package com.atguigu.cloud.resp;
    
    import lombok.Getter;
    
    import java.util.Arrays;
    /**
     * @auther zzyy
     * @create 2023-11-04 11:51
     */
    @Getter
    public enum ReturnCodeEnum {
        /**1.举值**/
        /**操作失败**/
        RC999("999","操作XXX失败"),
        /**操作成功**/
        RC200("200","success"),
        /**服务降级**/
        RC201("201","服务开启降级保护,请稍后再试!"),
        /**热点参数限流**/
        RC202("202","热点参数限流,请稍后再试!"),
        /**系统规则不满足**/
        RC203("203","系统规则不满足要求,请稍后再试!"),
        /**授权规则不通过**/
        RC204("204","授权规则不通过,请稍后再试!"),
        /**access_denied**/
        RC403("403","无访问权限,请联系管理员授予权限"),
        /**access_denied**/
        RC401("401","匿名用户访问无权限资源时的异常"),
        RC404("404","404页面找不到的异常"),
        /**服务异常**/
        RC500("500","系统异常,请稍后重试"),
        RC375("375","数学运算异常,请稍后重试"),
    
        INVALID_TOKEN("2001","访问令牌不合法"),
        ACCESS_DENIED("2003","没有权限访问该资源"),
        CLIENT_AUTHENTICATION_FAILED("1001","客户端认证失败"),
        USERNAME_OR_PASSWORD_ERROR("1002","用户名或密码错误"),
        BUSINESS_ERROR("1004","业务逻辑异常"),
        UNSUPPORTED_GRANT_TYPE("1003", "不支持的认证模式");
        /**构造**/
        /**自定义状态码**/
        private final String code;
        /**自定义描述**/
        private final String message;
    
        ReturnCodeEnum(String code, String message){
            this.code = code;
            this.message = message;
        }
        /**遍历**/
        //遍历枚举V1
        public static ReturnCodeEnum getReturnCodeEnum(String code)
        {
            for (ReturnCodeEnum element:ReturnCodeEnum.values()) {
                if (element.code.equals(code)){
                    return element;
                }
            }
            return null;
        }
        //遍历枚举V2
        public static ReturnCodeEnum getReturnCodeEnumV2(String code)
        {
            return Arrays.stream(ReturnCodeEnum.values()).filter(x -> x.getCode().equalsIgnoreCase(code)).findFirst().orElse(null);
        }
    
    
        /*public static void main(String[] args)
        {
            System.out.println(getReturnCodeEnumV2("200"));
            System.out.println(getReturnCodeEnumV2("200").getCode());
            System.out.println(getReturnCodeEnumV2("200").getMessage());
        }*/
    }
    
    

3、如何定义一个通用的枚举类

  • 这里主要讲解一下我们定义枚举的三个小步骤

  • 举值-构造-遍历

  • 举值

    • 罗列出你的枚举值每一个 code 对应的 message 分别是什么

    • 例如我们上面的代码中

    • 第一个举值 RC999

    • image-20240322151822444

    • 在这个枚举里面,第一个举值 999

    • 对应的 message 就是 操作失败

  • 构造

    • 我们的枚举是有两个具体的值
    • 所以在构造上面我们就要创建有两个参数的构造函数
    • 这个就叫做构造
    • image-20240322152116475
  • 遍历

    • 我们需要遍历我们的枚举
    • 根据我们传过来的 code 状态码,来返回所需要的枚举
    • 如果没有找到对应的枚举,就需要返回一个 null
    • 我们这里遍历枚举用了两种方法
    • image-20240322152339441

4、新建统一返回对象 ResultData

  • 新建类 ResultData

  • image-20240322153349457

  • 添加四个变量 codemessagedatatimestamp

  • 在构造函数中,给 timestamp 设置时间,表示方法的调用时间

  • 创建两个方法,成功和失败,设置返回结果

  • package com.atguigu.cloud.resp;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    
    @Data
    @Accessors(chain = true)
    public class ResultData<T> {
        private String code;
        private String message;
        private T data;
        private long timestamp;
    
        public ResultData(){
            this.timestamp=System.currentTimeMillis();
        }
        //成功
        public static<T> ResultData<T> success(T data){
            ResultData resultData=new ResultData();
            resultData.setCode(ReturnCodeEnum.RC200.getCode());
            resultData.setMessage(ReturnCodeEnum.RC200.getMessage());
            resultData.setData(data);
            return resultData;
        }
        //失败
        public static <T> ResultData<T> fail(String code,String message){
            ResultData resultData=new ResultData();
            resultData.setCode(code);
            resultData.setMessage(message);
            resultData.setData(null);
            return resultData;
        }
    }
    

5、修改 PayController 类中的返回值

  • 设置好同意的返回值后,我们需要修改先前的 PayController 类中的返回值

  • 将当中方法的返回值实现统一

  • 修改后的代码

  • package com.atguigu.cloud.controller;
    
    import cn.hutool.core.bean.BeanUtil;
    import com.atguigu.cloud.entities.Pay;
    import com.atguigu.cloud.entities.PayDTO;
    import com.atguigu.cloud.resp.ResultData;
    import com.atguigu.cloud.service.PayService;
    import io.swagger.v3.oas.annotations.Operation;
    import io.swagger.v3.oas.annotations.tags.Tag;
    import jakarta.annotation.Resource;
    import org.springframework.beans.BeanUtils;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @Tag(name = "支付微服务模块",description = "支付CRUD")
    public class PayController {
        @Resource
        PayService payService;
    
        @PostMapping(value = "/pay/add")
        @Operation(summary = "新增", description = "新增支付流水方法,json串做参数")
        public ResultData<String> addPay(@RequestBody Pay pay) {
            System.out.println(pay.toString());
            int i = payService.add(pay);
            return ResultData.success("成功插入记录,返回值:" + i);
        }
    
        @DeleteMapping(value = "/pay/del/{id}")
        @Operation(summary = "删除", description = "删除支付流水方法")
        public ResultData<Integer> deletePay(@PathVariable("id") Integer id) {
            return ResultData.success(payService.delete(id));
        }
    
        @PutMapping(value = "/pay/update")
        @Operation(summary = "修改", description = "修改支付流水方法")
        public ResultData<String> updatePay(@RequestBody PayDTO payDTO) {
            Pay pay = new Pay();
            BeanUtils.copyProperties(payDTO, pay);
    
            int i = payService.update(pay);
            return ResultData.success("成功修改记录,返回值:" + i);
        }
    
        @GetMapping(value = "/pay/get/{id}")
        @Operation(summary = "按照ID查流水", description = "查询支付流水方法")
        public ResultData<Pay> getById(@PathVariable("id") Integer id) {
            return ResultData.success(payService.getById(id));
        }
    }
    
  • 然后进行测试即可

  • image-20240322155020704

1.6.3 全局异常处理

  • 定义全局异常处理后将不需要再使用 try-cath 来解决异常了

  • 首先给我们 Controller 类中抛出一个错误

  • 当传输的 id 为 -4 时,抛出错误

  • image-20240323135725722

  • 定义全局异常处理类 GlobalExceptionHandler

  • package com.atguigu.cloud.exp;
    
    import com.atguigu.cloud.resp.ResultData;
    import com.atguigu.cloud.resp.ReturnCodeEnum;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    @RestControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(RuntimeException.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        public ResultData<String> exception(Exception e){
            System.out.println("#### come in GlobalExceptionHandler");
            return ResultData.fail(ReturnCodeEnum.RC500.getCode(), ReturnCodeEnum.RC500.getMessage());
        }
    }
    
    
  • image-20240323140316521

  • @ExceptionHandler 注解是具体要捕获的异常类型

  • @ResponseStatus 注解中的 HttpStatus枚举是定义异常和 BUG 的一个标准和规范

  • @ResponseStatus主要作用是为了改变 Http 响应的状态码

  • 测试一下即可,执行查询方法,传入 id 为 -4

  • image-20240323140751358

1.7 引入微服务理念

这里主要讲解不同模块之间如何调用

订单微服务80如何才能调用到支付微服务8001

1.7.1 RestTemplate

  • 在引入微服务之前,需要介绍一下 API RestTemplate

  • RestTemplate 提供了多种远程范围 HTTP 服务的方法

  • 是一种简单便捷的 restful 服务类

  • 是 Spring 提供的用于访问 Rest 服务的客户端模板工具集

  • 官网访问地址:https://docs.spring.io/spring-framework/docs/6.0.11/javadoc-api/org/springframework/web/client/RestTemplate.html

  • image-20240323144554418

  • image-20240323144614769

  • 看官网的方法便可得知,它提供了两个微服务之间调用的增删改查的方法

  • 使用restTemplate访问restful接口非常的简单粗暴无脑

  • (url, requestMap, ResponseBean.class)这三个参数分别代表

  • REST请求地址、请求参数、HTTP响应转换被转换成的对象类型

  • HTTP响应转换被转换成的对象类型简单理解就是要返回的对象

常用方法

  • image-20240323144928815

  • 如果访问的是 getForEntity 方法,则返回是 RestTemplate 自己封装的一层对象

    • 主要包含了一些重要信息
    • 例如响应头,响应状态码,响应体等
  • 如果访问的是 getForObject方法,则直接返回我们指定的返回的对象

  • GET 请求方法

  • image-20240323145343867

  • POST 请求方法

  • image-20240323145417260

使用 RestTemplate 的两种方式

  • 直接 new 出来

  • 使用 配置类来返回 RestTemplate

    • @Configuration
      public class RestTemplateConfig
      {
          @Bean
          public RestTemplate restTemplate()
          {
              return new RestTemplate();
          }
      }
      
      

1.7.2 RestTemplate 增删改查使用的方法

以下推荐一下我自己增删改查使用的方法

  • 增:postForObject(url,传递参数,返回的对象)
  • 删:delete(url,传递参数,返回的对象)
  • 改:put(url,传递参数,返回的对象)
  • 查:getForObject(url,返回的对象,传递的参数)

1.7.3 新建模块 80

  • 按照之前的步骤:建模块-改pom-写yml-创建主启动类-创建业务类,来创建模块

  • 创建模块 cloud-consumer-order80

  • image-20240323143244052

  • 改写 pom 文件

  • <?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>
        <parent>
            <groupId>com.atguigu.cloud</groupId>
            <artifactId>cloud2024</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>cloud-consumer-order80</artifactId>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
        <dependencies>
            <!--web + actuator-->
            <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>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <!--hutool-all-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
            </dependency>
            <!--fastjson2-->
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
            </dependency>
            <!-- swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
            <dependency>
                <groupId>org.springdoc</groupId>
                <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
  • 写 yml 文件

  • server:
      port: 80
    
  • 创建主启动类,名为 Main80

  • image-20240323143613653

  • package com.atguigu.cloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Main80 {
        public static void main(String[] args) {
            SpringApplication.run(Main80.class,args);
        }
    }
    
  • 创建业务类

  • 创建实体类 PayDTO 与 8001 模块的 DTO 一致

  • 因为消费者 80 产生的数据只应该是 支付者 8001 暴露出来的东西

  • 给消费者 80 尝试填写,对于其他敏感信息,其他信息是不应该暴露的

  • 所以需要使用 DTO 来传输数据

  • image-20240323144105487

  • 将之前在 8001 模块内定义的 统一返回对象拷贝过来

  • image-20240323150629399

  • 创建 RestTemplat 配置类

  • image-20240323150025269

  • 创建 Controller

  • 定义两个属性

    • REST请求地址
    • RestTemplate
  • image-20240323153003718

  • package com.atguigu.cloud.controller;
    
    import jakarta.annotation.Resource;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    public class OrderController {
        public static final String PaymentSrv_URL ="https://localhost:8001";
    
        @Resource
        private RestTemplate restTemplate;
        
    }
    

1.7.4 微服务调用,实现 80 模块调用 8001 模块中的增删改查方法

  • 然后就可以编写我们的增删改查方法了

  • 首先我们编写一个增加方法,用于测试

  • image-20240323155207448

  • package com.atguigu.cloud.controller;
    
    import com.atguigu.cloud.entities.PayDTO;
    import com.atguigu.cloud.resp.ResultData;
    import io.swagger.v3.oas.annotations.Operation;
    import io.swagger.v3.oas.annotations.tags.Tag;
    import jakarta.annotation.Resource;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    @Tag(name = "微服务消费模块",description = "消费调用支付的CRUD")
    public class OrderController {
        public static final String PaymentSrv_URL ="http://localhost:8001";
    
        @Resource
        private RestTemplate restTemplate;
    
        @PostMapping("/consumer/pay/add")
        @Operation(summary = "消费调用支付的新增", description = "新增支付流水方法,json串做参数")
        public ResultData addOrder(PayDTO payDTO){
            return restTemplate.postForObject(PaymentSrv_URL+"/pay/add", payDTO, ResultData.class);
        }
    }
    
    
  • postForObject 方法传递的三个参数就是对应 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型(及返回的对象类型)

  • 然后启动两个程序 Main8001 和 Main80

  • 一个个启动的话会比较麻烦,这边推荐设置到一起启动

  • 右上角编辑配置

  • image-20240323152420370

  • 选择 Spring boot,添加新的运行配置

  • image-20240323152505949

  • 命名,并且指定模块

  • image-20240323152550319

  • 选择模块内的主启动类

  • image-20240323152641358

  • 然后右键运行即可

  • image-20240323152726750

  • 然后进行测试即可

  • 增删改查的所有代码如下

  • package com.atguigu.cloud.controller;
    
    import com.atguigu.cloud.entities.PayDTO;
    import com.atguigu.cloud.resp.ResultData;
    import io.swagger.v3.oas.annotations.Operation;
    import io.swagger.v3.oas.annotations.tags.Tag;
    import jakarta.annotation.Resource;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    @Tag(name = "微服务消费模块",description = "消费调用支付的CRUD")
    public class OrderController {
        public static final String PaymentSrv_URL ="http://localhost:8001";
    
        @Resource
        private RestTemplate restTemplate;
        //增
        @PostMapping("/consumer/pay/add")
        @Operation(summary = "消费调用支付的新增", description = "新增支付流水方法,json串做参数")
        public ResultData addOrder(PayDTO payDTO){
            return restTemplate.postForObject(PaymentSrv_URL+"/pay/add", payDTO, ResultData.class);
        }
        //删
        @DeleteMapping( "/consumer/pay/del/{id}")
        @Operation(summary = "消费调用支付删除", description = "删除支付流水方法")
        public ResultData delByIdOrder(@PathVariable("id") Integer id){
            restTemplate.delete(PaymentSrv_URL+"/pay/del/{id}",id,ResultData.class);
            return ResultData.success("okx");
        }
        //改
        @PutMapping("/consumer/pay/update")
        @Operation(summary = "消费调用支付的修改",description = "修改支付流水方法")
        public ResultData updatePay(@RequestBody PayDTO payDTO){
            restTemplate.put(PaymentSrv_URL+"/pay/update",payDTO,ResultData.class);
            return ResultData.success("ok");
        }
        //查
        @GetMapping("/consumer/pay/get/{id}")
        @Operation(summary = "消费调用支付的按照ID查流水", description = "查询支付流水方法")
        public ResultData getById(@PathVariable("id") Integer id){
            return restTemplate.getForObject(PaymentSrv_URL+"/pay/get/{id}",ResultData.class,id);
        }
    }
    

1.8 工程重复代码提取

1.8.1 观察问题

  • 在我们的 8001 支付模块和 80 订单模块 两个模块当中,都存在一些相同的类,例如

  • image-20240326104757465

  • 可见系统中存在相同的部分

  • 此时我们可以新建一个模块,当作项目的一个包

  • 将这些重复的部分写入模块,在使用时即可直接调用

1.8.2 新建通用组件模块

  • 新建模块 cloud-api-commons

  • 用于对外暴露通用的组件/api/接口/工具类等

  • image-20240326105159622

  • 改写 pom 文件

  • <?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>
        <parent>
            <groupId>com.atguigu.cloud</groupId>
            <artifactId>cloud2024</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>cloud-api-commons</artifactId>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
        <dependencies>
            <!--SpringBoot通用依赖模块-->
            <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.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <!--hutool-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
            </dependency>
        </dependencies>
    </project>
    
  • 将两个模块通用的部分添加进新模块

  • image-20240326105535265

  • 使用 maven,将 cloud-api-commons 模块打成一个公用的 jar 包

  • image-20240326105747881

1.8.3 对模块 8001 和 80 进行改造

  • 将模块 cloud-api-commons 打成 jar 包后,需要在 8001 和 80 两个模块之间进行引用

  • 在 pom 文件中添加此依赖进行引用

  • <!-- 引入自己定义的api通用包 -->
    <dependency>
        <groupId>com.atguigu.cloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    
  • image-20240326110107012

  • 既然已经引入公用的部分了,那么两个模块之间公用的部分就可以删除了

  • 未标题-3

rg/xsd/maven-4.0.0.xsd">
4.0.0

com.atguigu.cloud
cloud2024
1.0-SNAPSHOT

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

  <properties>
      <maven.compiler.source>17</maven.compiler.source>
      <maven.compiler.target>17</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
      <!--SpringBoot通用依赖模块-->
      <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.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <optional>true</optional>
      </dependency>
      <!--hutool-->
      <dependency>
          <groupId>cn.hutool</groupId>
          <artifactId>hutool-all</artifactId>
      </dependency>
  </dependencies>
~~~
  • 将两个模块通用的部分添加进新模块

  • [外链图片转存中…(img-4MEDou8X-1711422961090)]

  • 使用 maven,将 cloud-api-commons 模块打成一个公用的 jar 包

  • [外链图片转存中…(img-ZhjxjmYb-1711422961090)]

1.8.3 对模块 8001 和 80 进行改造

  • 将模块 cloud-api-commons 打成 jar 包后,需要在 8001 和 80 两个模块之间进行引用

  • 在 pom 文件中添加此依赖进行引用

  • <!-- 引入自己定义的api通用包 -->
    <dependency>
        <groupId>com.atguigu.cloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    
  • [外链图片转存中…(img-HllNT61C-1711422961091)]

  • 既然已经引入公用的部分了,那么两个模块之间公用的部分就可以删除了

  • [外链图片转存中…(img-Fqj8AVYG-1711422961091)]

  • 然后自行测试即可

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值