保姆级教程构建SpringCloud工程(图文结合)

引言:

SpringCloud Alibaba 系列目录

一、搭建SpringCloud工程,请前往:保姆级教程构建SpringCloud工程(图文结合)
二、集成服务注册配置管理中心Nacos,请前往:SpringCloud集成服务注册配置管理中心Nacos
三、集成HTTP客户端工具OpenFeign,请前往:SpringCloud集成HTTP客户端工具OpenFeign
四、集成统一网关SpringCloud Gateway,请前往:SpringCloud集成微服务API网关Gateway(详解)

前言

什么是SpringCloud?
Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的开发便利性简化了分布式系统的开发,比如服务注册、服务发现、网关、路由、链路追踪等。Spring Cloud 并不是重复造轮子,而是将市面上开发得比较好的模块集成进去,进行封装,从而减少了各模块的开发成本。也可以说Spring Cloud 提供了构建分布式系统所需的“全家桶”。
SpringCloud的优缺点:
优点:

  1. 简化开发: 提供了丰富的组件和模式,可以快速开发分布式系统。
  2. 微服务支持: 支持微服务架构,提供了服务注册与发现、负载均衡等功能。
  3. 分布式配置管理: 提供了分布式配置管理的能力,可以动态管理配置信息。
  4. 监控与管理: 提供了监控、管理和调优的工具,方便运维管理和故障排查。
  5. 生态系统: 有庞大的社区支持和活跃的开发,生态系统完善。

缺点:

  1. 配置繁多且复杂,体量越大,部署治理成本越高,不利于维护,对团队挑战大
  2. 版本兼容性:需要注意 Spring Cloud各个组件的版本兼容性,不同版本之间可能存在不兼容的情况。

1. SpringCloud版本选型

以SpringCloud-alibaba的版本为基准进行选择SpringCloud,SpringBoot版本,这里选择(2021.0.4.0)
版本选型

2.选择SpringCloud、SpringBoot版本

https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明
从上边网页中找到 Springcloud-alibaba 2021.0.4.0 所对应的版本 ,如下图:
这里使用的JDK 为 11.0.18
Spring Cloud Version 对应的版本为 Spring Cloud 2021.0.4
Spring Boot Version 对应的版本为 2.6.11

在这里插入图片描述

3.选好版本,接开始搭建SpringCloud项目

最好的练习就是动手实践,接下来创建一个父工程,管理下边的不同服务(不同业务放到不同的服务中去,各个服务相互调用)。全程使用Maven进行搭建。

3.1 构建父工程

构建父工程, 点击 File -> New -> Project
在这里插入图片描述

3.2 选择Maven和JDK

选择创建Maven项目,选择本机安装JDK ,点击Next
在这里插入图片描述

3.3 填写项目名称

填写 Name、 GroupId、ArtifactId、Version ,填写完成,点击Finish
在这里插入图片描述
在这里插入图片描述

3.4 配置父工程pom.xml

项目的父工程已经建好了,根据前边选择的版本依赖配置父工程pom.xml
父工程不需要写业务代码,可以删除src文件目录和没用的文件。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.waves</groupId>
    <artifactId>wavesservice</artifactId>
    <version>1.0-SNAPSHOT</version>


    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot.version>2.6.11</spring-boot.version>
        <spring-cloud.version>2021.0.4</spring-cloud.version>
        <spring-dloud-alibaba.version>2021.0.4.0</spring-dloud-alibaba.version>
        <lombok.version>1.18.10</lombok.version>
        <log4j.version>1.2.17</log4j.version>
        <mysql.version>8.0.29</mysql.version>
        <druid.version>1.2.11</druid.version>
        <mybatisPlus.spring.boot.version>3.5.3</mybatisPlus.spring.boot.version>
        <amqp.version>2.3.9.RELEASE</amqp.version>
        <junit.version>4.12</junit.version>
        <test-version>2.3.9.RELEASE</test-version>
        <jackson-version>2.11.4</jackson-version>
        <aop.version>2.4.5</aop.version>
        <commons-collections.version>3.2.2</commons-collections.version>
        <fastjson.version>2.0.12</fastjson.version>
        <pagehelper.boot.version>1.4.3</pagehelper.boot.version>
        <lombok.version>1.18.24</lombok.version>
        <hutool.core.version>5.8.20</hutool.core.version>
        <hutool.all.version>5.8.20</hutool.all.version>
        <bootstrap.version>3.0.1</bootstrap.version>
    </properties>

    <!--  因为是总项目,所以用dependencyManagement来管理,子项目不用管理版本了,可以直接引用 子模块继承之后,提供作用:锁定版本+子module不用写groupId和version -->
    <dependencyManagement>
        <dependencies>

            <!-- SpringCloud 依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- SpringBoot 依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- SpringCloud-Alibaba 依赖 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-dloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>

            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
                <scope>runtime</scope>
            </dependency>

            <!-- druid-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>

            <!-- MybatisPlus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatisPlus.spring.boot.version}</version>
            </dependency>

            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <!--log4j-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>

            <!--单元测试-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>${test-version}</version>
            </dependency>

            <!-- Collection 增强Java集合框架 -->
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>${commons-collections.version}</version>
            </dependency>

            <!-- JSON 解析器和生成器 -->
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>${fastjson.version}</version>
            </dependency>

            <!-- pagehelper 分页插件 -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper.boot.version}</version>
            </dependency>

            <!-- Spring boot aop 拦截器 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
                <version>${aop.version}</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-core -->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-core</artifactId>
                <version>${hutool.core.version}</version>
            </dependency>

            <!-- hutool 工具 -->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool.all.version}</version>
            </dependency>

            <!--bootstrap 启动器加载上下文-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-bootstrap</artifactId>
                <version>${bootstrap.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <release>11</release>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <repositories>
        <repository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>

3.5创建子模块(服务)

完成上述步骤,父工程就已经搭建完成了。接下来就可以继续搭建其他的微服务工程了。首先搭建一个公共模块,为其他服务提供公共服务。

选中父工程,右键点击 New -> Module
在这里插入图片描述

3.6 选择Maven ,JDK

到这里创建和上边创建父工程一致,选择Maven,选择自己本机安装的JDK ,点击Next
在这里插入图片描述

3.7 填写模块服务名称

填写子模块服务名称,参考下图, 点击Finish 。
就创建好一个common父服务了。
在这里插入图片描述

3.8 新建 cloud-common-core模块

上边建的cloud-common是父模块,并不是只有一个,这里边会有core(基础核心)、后续集成feign时,会在cloud-common下新建cloud-common-feign-api模块,以及其他等公共子模块
在common下边新建cloud-common-core模块
和上述创建模块一样 New -> Module
在这里插入图片描述
在这里插入图片描述
这里需要注意,Parent是cloud-common
在这里插入图片描述
将父工程(四. 配置父工程pom.xml)声明的依赖添加到cloud-common-core的pom.xml中,这样后边建模块时,模块所需依赖,直接引入cloud-common-core 就可以了

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-common</artifactId>
        <groupId>com.waves</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-common-core</artifactId>

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

    <dependencies>
        <!-- Spring Context Support -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

        <!-- Spring Web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>

        <!-- MybatisPlus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

        <!--log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>

        <!-- Collection 增强Java集合框架 -->
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
        </dependency>

        <!-- JSON 解析器和生成器 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>

        <!-- pagehelper 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>

        <!-- Spring boot aop 拦截器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-core -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
        </dependency>

        <!-- hutool 工具 -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

        <!--bootstrap 启动器加载上下文-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

    </dependencies>

</project>

3.9 增加MybatisPlusConfig配置

项目中使用的是MybatisPlus,所以在cloud-common-core增加MybatisPlusConfig配置
配置写在common-core模块时,引入cloud-common-core依赖的服务启动类需要增加@ComponentScan(“com.waves”) 注解,扫描 “com.waves” 包下的配置类

package com.waves.core.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author waves
 * @date 2024/4/24 17:06
 */
@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 添加执行分析插件
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        // 添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

}

3.10 封装公共响应体

封装一个公共响应体是很有必要的
在cloud-common-core封装公共响应体,
创建响应码常量

/**
 * 返回状态码
 *
 * @author waves
 * @date 2024/4/24 17:06
 */
public class HttpStatus {

    /** 操作成功 */
    public static int SUCCESS = 100;

    /** 警告消息 */
    public static int WARM = 101;

    /** 操作失败 */
    public static int ERROR = 103;

}

创建ResponseResult

package com.waves.core.web.domain;
import com.waves.core.constant.HttpStatus;
import java.util.HashMap;
import java.util.Objects;
/**
 * @author waves
 * @date 2024/4/24 17:28
 */
public class ResponseResult extends HashMap<String, Object> {

    private static final long serialVersionUID = 1L;
    /** 状态码 */
    public static final String CODE_TAG = "code";
    /** 返回内容 */
    public static final String MSG_TAG = "message";
    /** 数据对象 */
    public static final String DATA_TAG = "data";
    /** 无参构造对象 初始化一个对象,表示一个空消息 */
    public ResponseResult(){
    }

    /**
     * 初始化一个新创建的 ResponseResult 对象
     * @param code 状态码
     * @param msg 返回内容
     */
    public ResponseResult(int code, String msg)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
    }

    /**
     * 初始化一个新创建的 ResponseResult 对象
     * @param code 状态码
     * @param msg 返回内容
     * @param data 数据对象
     */
    public ResponseResult(int code, String msg, Object data)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        if (Objects.nonNull(data))
        {
            super.put(DATA_TAG, data);
        }
    }

    /**
     * 返回成功消息
     * @return 成功消息
     */
    public static ResponseResult success()
    {
        return ResponseResult.success("操作成功");
    }

    /**
     * 返回成功数据
     * @return 成功消息
     */
    public static ResponseResult success(Object data)
    {
        return ResponseResult.success("操作成功", data);
    }

    /**
     * 返回成功消息
     * @param msg 返回内容
     * @return 成功消息
     */
    public static ResponseResult success(String msg)
    {
        return ResponseResult.success(msg, null);
    }

    /**
     * 返回成功消息
     * @param msg 返回内容
     * @param data 数据对象
     * @return 成功消息
     */
    public static ResponseResult success(String msg, Object data)
    {
        return new ResponseResult(HttpStatus.SUCCESS, msg, data);
    }

    /**
     * 返回警告消息
     * @param msg 返回内容
     * @return 警告消息
     */
    public static ResponseResult warn(String msg)
    {
        return ResponseResult.warn(msg, null);
    }

    /**
     * 返回警告消息
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static ResponseResult warn(String msg, Object data)
    {
        return new ResponseResult(HttpStatus.WARN, msg, data);
    }

    /**
     * 返回错误消息
     * @return 错误消息
     */
    public static ResponseResult error()
    {
        return ResponseResult.error("操作失败");
    }

    /**
     * 返回错误消息
     * @param msg 返回内容
     * @return 错误消息
     */
    public static ResponseResult error(String msg)
    {
        return ResponseResult.error(msg, null);
    }

    /**
     * 返回错误消息
     * @param msg 返回内容
     * @param data 数据对象
     * @return 错误消息
     */
    public static ResponseResult error(String msg, Object data)
    {
        return new ResponseResult(HttpStatus.ERROR, msg, data);
    }

    /**
     * 返回错误消息
     * @param code 状态码
     * @param msg 返回内容
     * @return 错误消息
     */
    public static ResponseResult error(int code, String msg)
    {
        return new ResponseResult(code, msg, null);
    }

    /**
     * 是否为成功消息
     * @return 结果
     */
    public boolean isSuccess()
    {
        return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
    }

    /**
     * 是否为警告消息
     * @return 结果
     */
    public boolean isWarn()
    {
        return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
    }

    /**
     * 是否为错误消息
     * @return 结果
     */
    public boolean isError()
    {
        return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
    }

    /**
     * 方便链式调用
     * @param key
     * @param value
     * @return
     */
    @Override
    public ResponseResult put(String key, Object value)
    {
        super.put(key, value);
        return this;
    }
}

3.11 创建支付服务

与创建cloud-common同理创建cloud-provider-payment服务

在cloud-provider-payment模块的pom.xml中引入cloud-common-core,spring-boot-starter-web 的依赖
(cloud-provider-payment)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">
    <parent>
        <artifactId>wavesservice</artifactId>
        <groupId>com.waves</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment</artifactId>

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

    <dependencies>

        <!-- 内嵌web服务器(tomcat),不引入就需要引入spring-boot-starter-tomcat,否则项目会启动后自动关闭 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 引入公共核心模块 -->
        <dependency>
            <groupId>com.waves</groupId>
            <artifactId>cloud-common-core</artifactId>
        </dependency>
    </dependencies>

</project>

3.12 编写支付代码和接口

1. 创建bootstrap.yml配置文件

使用的是MybatisPlus,只MybatisPlus配置,不需要配置Mybatis

# 服务端口
server:
  port: 8088
  servlet:
    # 服务访问路径
    context-path: /paymentservice

spring:
  application:
    # 服务名称
    name: paymentservice

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      url: jdbc:mysql://localhost:3306/waves_cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
      username: root
      password: root

  #mybatis:
  #配置mapper的扫描,找到所有的mapper:xml映射文件:
  #  mapper-locations: classpath:mapper/*.xml
  # 搜索指定包别名
#  type-aliases-package: com.waves.**.domain
mybatis-plus:
  # 不支持多包, 如有需要可在注解配置 或 提升扫包等级
  # 例如 com.**.**.mapper
  mapperPackage: com.waves.**.mapper
  # 对应的 XML 文件位置
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # 实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.waves.**.domain
  # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
  checkConfigLocation: false
  configuration:
    # 自动驼峰命名规则(camel case)映射
    mapUnderscoreToCamelCase: false
    # MyBatis 自动映射策略
    # NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射
    autoMappingBehavior: PARTIAL
    # MyBatis 自动映射时未知列或未知属性处理策
    # NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息
    autoMappingUnknownColumnBehavior: NONE
    # 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
    # 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl
    # 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
    logImpl: org.apache.ibatis.logging.nologging.NoLoggingImpl
  global-config:
    # 是否打印 Logo banner
    banner: true
    dbConfig:
      # 主键类型
      # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
      idType: ASSIGN_ID
      # 逻辑已删除值
      logicDeleteValue: 2
      # 逻辑未删除值
      logicNotDeleteValue: 0
      # 字段验证策略之 insert,在 insert 的时候的字段验证策略
      # IGNORED 忽略 NOT_NULL 非NULL NOT_EMPTY 非空 DEFAULT 默认 NEVER 不加入 SQL
      insertStrategy: NOT_NULL
      # 字段验证策略之 update,在 update 的时候的字段验证策略
      updateStrategy: NOT_NULL
      # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
      where-strategy: NOT_NULL

# 日志配置
logging:
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
  level:
    com.waves: debug
    org.springframework: warn
2.创建Payment支付服务的启动类
package com.waves.payment;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author waves
 * @date 2024/4/24 22:39
 */
@SpringBootApplication
@MapperScan("${mybatis-plus.mapperPackage}") // 配置要扫描的包
//@ComponentScan(basePackages = {"com.waves.core", "com.waves.payment"}) //配置要扫描的组件和配置
@ComponentScan("com.waves")
public class PaymentApplication {
    public static void main(String[] args) {
        SpringApplication.run(PaymentApplication.class,args);
        System.out.println("支付服务启动成功 (^-^)V。。。。");
    }
}
3.创建Payment表
#创建sys_payment_type 支付类型表
CREATE TABLE `sys_payment_type`  (
  `pay_id` bigint(20) NOT NULL COMMENT '支付类型主键',
  `pay_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '支付类型名称',
  `remark` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`pay_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;

#插入数据
INSERT INTO `sys_payment_type` (`pay_id`, `pay_name`, `remark`) VALUES (1, '支付宝', '使用支付宝进行支付');
INSERT INTO `sys_payment_type` (`pay_id`, `pay_name`, `remark`) VALUES (2, '微信支付', '使用微信支付进行支付');
INSERT INTO `sys_payment_type` (`pay_id`, `pay_name`, `remark`) VALUES (3, '银行转账', '通过银行转账进行支付');
4.写Payment接口
1.新建Payment实体类

在cloud-common-core 中新建 payment实体类

package com.waves.core.web.domain.entities;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * 支付类型实体 如果进行网络通信 一定要实现序列化
 * @author waves
 * @date 2024/4/25 9:44
 */
@Data //: 该注解会自动生成类的 getter、setter、equals、hashCode 和 toString 方法,从而减少样板代码。
@NoArgsConstructor //: 自动生成一个无参构造方法,用于创建对象实例时不需要传入任何参数。
@AllArgsConstructor //: 自动生成一个包含所有参数的构造方法,用于创建对象实例时需要传入所有字段的值。
@Accessors(chain = true) //: 启用方法链(method chaining),允许在对象实例上连续调用多个 setter 方法,可以使代码更加简洁。
@TableName("sys_payment_type") //:对应数据库表的名称
public class SysPaymentType implements Serializable {

    /**
     * 支付Id
     * TableId 加在表主键上面 value 对应 字段名 ,type 为数据库ID自增
     */
    @TableId(value = "pay_id", type = IdType.AUTO)
    private Long payId;

    /**
     * 支付类型名称
     * TableField value 对应 字段名 
     */
    @TableField(value = "pay_name")
    private String payName;

    /**
     * 备注
     */
    @TableField(value = "remark")
    private String remark;

}
2.新建mapper层

SysPaymentMapper继承MybatisPlus 的 BaseMapper,

package com.waves.payment.web.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.waves.core.web.domain.entities.SysPaymentType;

/**
 * @author waves
 * @date 2024/4/25 9:44
 */
@Mapper
public interface SysPaymentMapper extends BaseMapper<SysPaymentType> {
}
3.新建Service

ISysPaymentService 继承MybatisPlus 的 IService

package com.waves.payment.web.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.waves.core.web.domain.entities.SysPaymentType;

/**
 * @author waves
 * @date 2024/4/25 9:44
 */
@Service
public interface ISysPaymentService extends IService<SysPaymentType> {
}
4.新建ServiceImpl

SysPaymentServiceImpl继承 继承MybatisPlus 的 IService 的 ServiceImpl 同时实现 我们自己的ISysPaymentService

package com.waves.payment.web.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.waves.core.web.domain.entities.SysPaymentType;
import com.waves.payment.web.mapper.SysPaymentMapper;
import com.waves.payment.web.service.ISysPaymentService;
import org.springframework.stereotype.Service;

/**
 * @author waves
 * @date 2024/4/25 9:44
 */
@Service
public class SysPaymentServiceImpl extends ServiceImpl<SysPaymentMapper,SysPaymentType> implements ISysPaymentService {
}
5.新建Controller
package com.waves.payment.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.waves.core.web.domain.entities.SysPaymentType;
import com.waves.payment.web.service.ISysPaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Objects;

/**
 * @author waves
 * @date 2024/4/25 9:44
 */
@RestController
@RequestMapping("/payment")
public class SysPaymentController {

    @Autowired
    private ISysPaymentService paymentService;

    /**
     * 分页查询PaymentType,条件 payId ,payName
     * @return
     */
    @GetMapping("/listPage/{pageNum}/{pageSize}")
    public IPage<SysPaymentType> list(@PathVariable("pageNum") Integer pageNum
            , @PathVariable("pageSize") Integer pageSize
            , SysPaymentType paymentType){

        QueryWrapper<SysPaymentType> queryWrapper = new QueryWrapper<>();
        //判断支付类型名称 不为空,则进行条件查询
        queryWrapper.lambda()
                .like(Objects.nonNull(paymentType.getPayName()),SysPaymentType::getPayName,paymentType.getPayName())
                .eq(Objects.nonNull(paymentType.getPayId()),SysPaymentType::getPayId,paymentType.getPayId());
        return paymentService.page(new Page<>(pageNum,pageSize),queryWrapper);

    }

    /**
     * 根据支付Id查询支付类型
     * @param payId
     * @return
     */
    @GetMapping("/findById/{payId}")
    public SysPaymentType findById(@PathVariable("payId") Long payId){
        return paymentService.getById(payId);
    }

    /**
     * 根据Id进行删除
     * @param payId
     * @return
     */
    @GetMapping("/removeById/{payId}")
    public ResponseResult removeById(@PathVariable("payId") Long payId){
       return ResponseResult.success(paymentService.removeById(payId));
    }
}
5.测试Payment接口

测试获取列表接口
http://localhost:8088/paymentservice/payment/listPage/1/10
返回数据如下:

{
  "records": [
    {
      "payId": 1,
      "payName": "支付宝",
      "remark": "使用支付宝进行支付"
    },
    {
      "payId": 2,
      "payName": "微信支付",
      "remark": "使用微信支付进行支付"
    },
    {
      "payId": 3,
      "payName": "银行转账",
      "remark": "通过银行转账进行支付"
    }
  ],
  "total": 3,
  "size": 10,
  "current": 1,
  "orders": [],
  "optimizeCountSql": true,
  "searchCount": true,
  "maxLimit": null,
  "countId": null,
  "pages": 1
}

测试根据ID查询
http://localhost:8088/paymentservice/payment/findById/1
返回数据如下:

{
  "payId": 1,
  "payName": "支付宝",
  "remark": "使用支付宝进行支付"
}

测试删除接口
http://localhost:8088/paymentservice/payment/removeById/1
返回数据如下:

{
  "code": 100,
  "data": true,
  "message": "操作成功"
}

到这里项目就搭建完成了,下为项目结构图
在这里插入图片描述

3.13 创建订单服务并使用RestTemplate实现远程调用

1、创建cloud-consumer-order服务

与创建cloud-common(创建Common子模块(服务))同理创建cloud-consumer-order服务,在cloud-consumer-order模块的pom.xml中引入cloud-common-core,spring-boot-starter-web 的依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>wavesservice</artifactId>
        <groupId>com.waves</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-order</artifactId>

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

    <dependencies>
        <!-- 内嵌web服务器(tomcat),不引入就需要引入spring-boot-starter-tomcat,否则项目会启动后自动关闭 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 引入公共核心模块 -->
        <dependency>
            <groupId>com.waves</groupId>
            <artifactId>cloud-common-core</artifactId>
        </dependency>
    </dependencies>

</project>
2、创建订单服务的YML配置类
# 服务端口
server:
  port: 18088
  servlet:
    # 服务访问路径
    context-path: /orderservice

spring:
  application:
    # 服务名称
    name: orderservice

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      url: jdbc:mysql://localhost:3306/waves_cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
      username: root
      password: dwdtec2015


  #mybatis:
  #配置mapper的扫描,找到所有的mapper:xml映射文件:
  #  mapper-locations: classpath:mapper/*.xml
  # 搜索指定包别名
#  type-aliases-package: com.waves.**.domain
mybatis-plus:
  # 不支持多包, 如有需要可在注解配置 或 提升扫包等级
  # 例如 com.**.**.mapper
  mapperPackage: com.waves.**.mapper
  # 对应的 XML 文件位置
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # 实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.waves.**.domain
  # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
  checkConfigLocation: false
  configuration:
    # 自动驼峰命名规则(camel case)映射
    mapUnderscoreToCamelCase: false
    # MyBatis 自动映射策略
    # NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射
    autoMappingBehavior: PARTIAL
    # MyBatis 自动映射时未知列或未知属性处理策
    # NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息
    autoMappingUnknownColumnBehavior: NONE
    # 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
    # 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl
    # 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
    logImpl: org.apache.ibatis.logging.nologging.NoLoggingImpl
  global-config:
    # 是否打印 Logo banner
    banner: true
    dbConfig:
      # 主键类型
      # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
      idType: ASSIGN_ID
      # 逻辑已删除值
      logicDeleteValue: 2
      # 逻辑未删除值
      logicNotDeleteValue: 0
      # 字段验证策略之 insert,在 insert 的时候的字段验证策略
      # IGNORED 忽略 NOT_NULL 非NULL NOT_EMPTY 非空 DEFAULT 默认 NEVER 不加入 SQL
      insertStrategy: NOT_NULL
      # 字段验证策略之 update,在 update 的时候的字段验证策略
      updateStrategy: NOT_NULL
      # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
      where-strategy: NOT_NULL


# 日志配置
logging:
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
  level:
    com.waves: debug
    org.springframework: warn
3、创建订单服务的启动类
package com.waves.order;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;

/**
 * @author waves
 * @date 2024/5/20 14:53
 *
 * SpringBootApplication 启动注解
 * MapperScan 配置要扫描的包
 * ComponentScan 扫描com.waves 下的组件
 */
@SpringBootApplication
@MapperScan("${mybatis-plus.mapperPackage}")
@ComponentScan("com.waves")
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class,args);
        System.out.println("订单服务启动成功!o(* ̄▽ ̄*)ブ");
    }

    /**
     * 基于RestTemplate的远程调用
     * @return
     */
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();    
    }
}
4、创建订单服务的Controller
package com.waves.order.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.waves.core.web.domain.entities.SysOrder;
import com.waves.core.web.domain.entities.SysPaymentType;
import com.waves.order.web.service.ISysOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Objects;

/**
 * @author waves
 * @date 2024/5/20 15:37
 */
@RestController
@RequestMapping("/system/order")
public class SysOrderController {

    @Autowired
    private ISysOrderService sysOrderService;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 分页查询PaymentType,条件 payId ,payName
     * @return
     */
    @GetMapping("/listPage/{pageNum}/{pageSize}")
    public IPage<SysOrder> list(@PathVariable("pageNum") Integer pageNum
            , @PathVariable("pageSize") Integer pageSize
            , SysOrder order){

        QueryWrapper<SysOrder> queryWrapper = new QueryWrapper<>();
        //判断支付类型名称 不为空,则进行条件查询
        queryWrapper.lambda()
                .eq(Objects.nonNull(order.getUserId()),SysOrder::getUserId,order.getUserId());
        return sysOrderService.page(new Page<>(pageNum,pageSize),queryWrapper);
    }

    /**
     * 查询单个订单
     * @return sysOrder
     */
    @GetMapping("/getOrder/{orderId}")
    public SysOrder getOrder(@PathVariable("orderId") Long orderId){
        //1.查询订单
        SysOrder sysOrder = sysOrderService.getById(orderId);
        //2.查询订单的支付类型
        String url = "http://localhost:8088/paymentservice/payment/findById/"+ sysOrder.getPaymentType();
        SysPaymentType paymentType = restTemplate.getForObject(url,SysPaymentType.class);
        //3.封装支付类型信息
        sysOrder.setPaymentTypeData(paymentType);
        return sysOrder;
    }
}
5、创建订单服务的Service
package com.waves.order.web.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.waves.core.web.domain.entities.SysOrder;

/**
 * @author waves
 * @date 2024/5/20 15:39
 */
public interface ISysOrderService extends IService<SysOrder> {
}


package com.waves.order.web.service.Impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.waves.core.web.domain.entities.SysOrder;
import com.waves.order.web.mapper.SysOrderMapper;
import com.waves.order.web.service.ISysOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author waves
 * @date 2024/5/20 15:40
 */
@Service
public class ISysOrderServiceImpl extends ServiceImpl<SysOrderMapper, SysOrder> implements ISysOrderService {

    private SysOrderMapper sysOrderMapper;

    @Autowired
    public void setSysOrderMapper(SysOrderMapper sysOrderMapper) {
        this.sysOrderMapper = sysOrderMapper;
    }
}

6、创建订单服务的Mapper
package com.waves.order.web.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.waves.core.web.domain.entities.SysOrder;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author waves
 * @date 2024/5/20 15:41
 */
@Mapper
public interface SysOrderMapper extends BaseMapper<SysOrder> {
}

测试接口:

http://localhost:18088/orderservice/system/order/getOrder/2
//返回结果
{
  "orderId": 2,
  "userId": 2,
  "userName": "小明",
  "orderAmount": 8888.88,
  "orderDate": "2024-05-20T07:20:23.000+00:00",
  "paymentType": 1,
  "remark": "送货上门",
  "paymentTypeData": {
    "payId": 1,
    "payName": "支付宝",
    "remark": "通过支付宝进行支付"
  }
}
  • 26
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
对于Spring Cloud项目的部署,可以采用以下步骤: 1. 准备环境:首先确保服务器上已经安装了Java运行环境和相关依赖。可以使用Docker容器化技术来快速搭建开发环境。 2. 编译打包:将Spring Cloud项目编译打包成可执行的jar包或war包。可以使用Maven或Gradle进行构建。 3. 配置文件:根据项目需要,编写相应的配置文件,比如application.properties或application.yml,配置数据库连接、端口号等信息。 4. 启动服务:使用命令行或脚本来启动Spring Cloud服务。可以使用nohup命令将服务放在后台运行。 5. 健康检查:确保服务正常运行后,可以使用健康检查工具(如Actuator)来监控服务状态。 6. 负载均衡:如果需要进行负载均衡,可以使用Nginx等反向代理工具来实现。 7. 日志管理:配置日志系统,记录和管理项目的日志信息。可以使用ELK(Elasticsearch + Logstash + Kibana)等工具进行日志集中管理和分析。 8. 监控与调优:使用监控工具(如Prometheus、Grafana)来收集和展示系统运行指标,并进行性能调优和故障排查。 9. 安全加固:根据实际需求,配置相关的安全策略,如防火墙、SSL证书等,保障系统的安全性。 10. 自动化部署:可以使用CI/CD工具(如Jenkins、GitLab CI/CD)实现自动化部署,提高部署效率和稳定性。 以上是一个简要的部署步骤,根据具体项目和环境的不同,可能会有一些细节上的差异。希望对你有所帮助!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧歌*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值