1、概要
本章节讲解如何构建SpringCloud alibaba项目,以父子工程形式搭建。
- 父工程规范Springboot版本、SpringCloud版本、SpringCloud alibaba版本;
- 子工程包括公共方法库(公共的DTO、http统一返回类(枚举code码等)),Gateway网关(集成Sentinel)、内网微服务统一接口层、内网微服务发布方、内网微服务调用方等;
2、整体架构流程
2.1、技术结构组成部分
此次框架选型是对Spring Cloud Netflix 框架组件的升级与替换。
Spring Cloud alibaba组件包括:Nacos (discovery、config)、Sentinel
Spring Cloud 组件包括:OpenFeign+ LoadBalancer 、Sleuth、Gateway
其他组件:RabbitMQ 、redis、mybatis-plus、knife4j、JWT、ShardingSphere-jdbc
3、技术名词解释
例如:
- Nacos discovery: 英文全称为 Dynamic Naming and Configuration Service,是一个由阿里巴巴团队使用 Java 语言开发的开源项目,有注册中心、服务注册、发现功能。
- Nacos config: 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。
- Sentinel:是由阿里巴巴中间件团队开发的开源项目,是一种面向分布式微服务架构的轻量级高可用流量控制组件
- Sleuth:可以将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式请求的调用情况集中展示。
- OpenFeign: 全称 Spring Cloud OpenFeign,它是 Spring 官方推出的一种声明式服务调用与负载均衡组件。我们可以像调用本地方法一样来调用远程服务,而完全感觉不到这是在进行远程调用,结合LoadBalancer 一起使用。
- RabbitMQ:RabbitMQ整体上是一个生产者与消费者模型,主要负责接收、存储和转发消息。常用于系统解耦、削峰使用,常见于微服务、业务活动等场景。
- mybatis-plus:数据库操作工具;
- knife4j:基于swagger升级的文档管理工具。
- JWT:JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案,基于JSON的开发标准,用户信息加密到token里,服务器不保存任何用户信息。
- Apache ShardingSphere : 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强
4、技术细节
4.1、构建父工程
4.1.1、选择构建Maven项目
4.1.2、修改父工程文件
- 删除src目录及底下的所有文件
- 保留pom.xml
4.1.3、修改父工程pom.xml配置
4.1.3.1、添加springboot支持
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.10</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.kelvin</groupId> <artifactId>onlinestore</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging>
4.1.3.2、修改JDK版本、编码、springboot版本配置
<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.7.10</spring-boot.version> </properties>
4.1.3.3、添加Spring Cloud、Spring Cloud alibaba版本规范配置
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.5</version> <type>pom</type> <scope>import</scope> </dependency> <!--spring cloud alibaba 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2021.0.4.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
4.1.3.4、增加lombok依赖配置
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>compile</scope> </dependency> </dependencies>
4.1.3.5、增加build配置,整个工程使用maven打包
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> </configuration> </plugin> </plugins> </build>
4.2、构建公共子工程
4.2.1、添加子工程store-common
4.2.2、修改文件
- 删除test文件夹
- pom.xml去掉junit
4.2.3、添加统一返回类
package com.kelvin.common.http; /*** * @title HttpStatusInfoInterface * @desctption HTTP状态信息接口 * @author Administrator * @create 2023/5/18 10:28 **/ public interface HttpStatusInfoInterface { int getCode(); String getMessage(); }
package com.kelvin.common.http; /*** * @title HttpStatusEnum * @desctption Http状态码 * @author Administrator * @create 2023/5/18 10:30 **/ public enum HttpStatusEnum implements HttpStatusInfoInterface{ //定义状态枚举值 SUCCESS(200 , "成功!"), NOROLE(300 , "权限不足!"), USER_TOKEN_NOT_EXISTS(301 , "无效的token信息!"), PRODUCT_STOCK_NOT_ENOUGH(302 , "商品的库存不足!"), BODY_NOT_MATCH(400 , "数据格式不匹配!"), NOT_FOUND(404 , "访问资源不存在!"), FLOW_LIMIT(490 , "接口流量已超出,限制访问!"), INTERNAM_SERVER_ERROR(500 , "服务器内部错误!"), SERVER_BUSY(503 , "服务器正忙,请稍后再试!"), REQUEST_METHOD_SUPPORT_ERROR(10001 , "当前请求方法不支持!"), REQUEST_DATA_NULL(10002 , "当前请求参数为空!"), USER_NOT_EXISTS(10003 , "该用户不存在!"), USER_INVALID(10004 , "当前登录信息已失效,请重新登录!"), PASSWORD_ERROR(10005 , "密码错误!"), USER_NAME_LOCK(10006 , "该账号已被锁定!") ; //状态码 private int code; //提示信息 private String message; HttpStatusEnum(int code, String message) { this.code = code; this.message = message; } @Override public int getCode() { return this.code; } @Override public String getMessage() { return this.message; } }
package com.kelvin.common.http; import lombok.Data; /*** * @title ResultDTO * @desctption 控制器的统一返回类 * @author Administrator * @create 2023/5/16 9:48 **/ @Data public class ResultDTO<T> { private Integer code ; private String message; private T data; public ResultDTO() { } public ResultDTO(Integer code, String message, T data) { this.code = code; this.message = message; this.data = data; } }
package com.kelvin.common.http; /*** * @title HttpResultGenerator * @desctption <TODO description class purpose> * @author Administrator * @create 2023/5/18 10:43 **/ public class HttpResultGenerator { //正常返回时调用方法 public static ResultDTO success(Object data) { return new ResultDTO(HttpStatusEnum.SUCCESS.getCode() , "接口调用成功!" , data); } //失败时调用方法(入参是异常枚举) public static ResultDTO fail(HttpStatusEnum httpStatusEnum) { return new ResultDTO(httpStatusEnum.getCode() , httpStatusEnum.getMessage() , null); } //失败时调用方法(提供给GlobalExceptionHandler类使用) public static ResultDTO fail(int code , String message) { return new ResultDTO(code , message , null); } }