一、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 中的不同的组件

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

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

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

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

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

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

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

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

1、New Project

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

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

2、聚合总父工程的名字

  • 这个就是父工程的名字

3、字符编码

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

4、注解激活生效

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

5、java 编译版本选择 17

1.2.2 Maven 父工程 pom 文件内容

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

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

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

xml 复制代码
 <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 配置

xml 复制代码
# 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 文件依赖

xml 复制代码
# Maven的POM文件处理
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
 

2、如果是 Mysql8

  • JDBC 配置

xml 复制代码
# 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 文件依赖

java 复制代码
# Maven的POM
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>

1.3 Mapper4 一键生成增删改查

1.3.1 数据库搭建

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

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

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

mysql 复制代码
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 工程

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

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

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

xml 复制代码
<?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 数据库配置文件

properties 复制代码
#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

xml 复制代码
<?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 一键生成增删改查

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

1.4 标准构建微服务工程

完整构建微服务的步骤

1、建 module 模块

2、改写 pom 文件

3、写 yml,启动类配置

4、创建主启动类

5、创建业务类

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

1.4.1 构建提供者微服务模块

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

1.4.2 改写 pom 文件

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

xml 复制代码
<?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 文件,启动类的配置

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 包

1.4.4 创建主启动类

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

  • 添加 @MapperScan 注解

  • 注意不要导错包

1.4.5 创建业务类

1、entities(实体类)

  • 创建两个实体 Pay 和 PayDTO

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

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

java 复制代码
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;
}

2、mapper

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

  • cloud 包下的 mapper 包存放接口

  • resources 包下的 mapper 存放 xml 文件

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

3、Service

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

java 复制代码
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,实现增删改查方法

java 复制代码
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

  • PayController 代码部分

java 复制代码
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 之前需要导入一个依赖

xml 复制代码
 <!-- 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 需要在代码中嵌入注解

  • 以下是常用注解

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

java 复制代码
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 中添加注解,描述实体类及字段的作用

java 复制代码
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 相关的配置类

  • 编写相关代码

java 复制代码
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/"));
    }
}
  • 我们微服务的接口会有很多,这个配置类就是专门进行了分组

  • 例如

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

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

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

1.5.3 使用 Swagger3 进行测试

  • 运行启动类

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

  • 成功访问的界面

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

  • 这里进行测试即可

1.6 微服务工程项目改进

1.6.1 时间格式问题优化

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

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

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

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

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

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

yml 复制代码
spring:
	jackson:
		date-format: yyyy-MM-dd HH:mm:ss
		time-zone:GMT+8

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

1.6.2 统一返回值格式

1、具体思路

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

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

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

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

2、主要步骤

  • 新建枚举类 ReturnCodeEnum

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

  • HTTP 请求返回的状态码

  • 定义 ReturnCodeEnum 枚举类

  • 具体代码

java 复制代码
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

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

    • 对应的 message 就是 操作失败

  • 构造

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

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

4、新建统一返回对象 ResultData

  • 新建类 ResultData

  • 添加四个变量 codemessagedatatimestamp

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

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

java 复制代码
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 类中的返回值

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

  • 修改后的代码

java 复制代码
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));
    }
}
  • 然后进行测试即可

1.6.3 全局异常处理

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

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

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

  • 定义全局异常处理类 GlobalExceptionHandler

java 复制代码
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());
    }
}
  • @ExceptionHandler 注解是具体要捕获的异常类型

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

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

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

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

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

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

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

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

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

常用方法

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

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

  • GET 请求方法

  • POST 请求方法

使用 RestTemplate 的两种方式

  • 直接 new 出来

  • 使用 配置类来返回 RestTemplate

    java 复制代码
    @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

  • 改写 pom 文件

xml 复制代码
<?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 文件

yml 复制代码
server:
  port: 80
  • 创建主启动类,名为 Main80

java 复制代码
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 来传输数据

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

  • 创建 RestTemplat 配置类

  • 创建 Controller

  • 定义两个属性

    • REST请求地址
    • RestTemplate
java 复制代码
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 模块中的增删改查方法

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

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

java 复制代码
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

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

  • 右上角编辑配置

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

  • 命名,并且指定模块

  • 选择模块内的主启动类

  • 然后右键运行即可

  • 然后进行测试即可

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

java 复制代码
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 订单模块 两个模块当中,都存在一些相同的类,例如

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

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

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

1.8.2 新建通用组件模块

  • 新建模块 cloud-api-commons

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

  • 改写 pom 文件

xml 复制代码
<?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>
  • 将两个模块通用的部分添加进新模块

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

1.8.3 对模块 8001 和 80 进行改造

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

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

xml 复制代码
<!-- 引入自己定义的api通用包 -->
<dependency>
    <groupId>com.atguigu.cloud</groupId>
    <artifactId>cloud-api-commons</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
  • 既然已经引入公用的部分了,那么两个模块之间公用的部分就可以删除了

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 文件中添加此依赖进行引用

xml 复制代码
<!-- 引入自己定义的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 分钟前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼15 分钟前
Java基础-单例模式的实现
java·开发语言·单例模式
热爱嵌入式的小许3 小时前
Linux基础项目开发1:量产工具——显示系统
linux·运维·服务器·韦东山量产工具
ok!ko4 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2402_857589364 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰5 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
哎呦没5 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
编程、小哥哥6 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
IT学长编程7 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇7 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器