# the-aggregate **Repository Path**: hip202/the-aggregate ## Basic Information - **Project Name**: the-aggregate - **Description**: 来自202一床的祝福 搭建spring boot集群项目,进行技术验证 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-10-12 - **Last Updated**: 2026-04-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目用途 搭建spring boot集群项目,进行技术验证 1. MySql,Postgres数据库,mybatis工具的使用 2. 全局异常处理,全局响应报文处理 3. 单点登录功能 # 项目环境搭建 * IntelliJ IDEA 2023.3.6 (Community Edition) * Docker version 26.1.3, build b72abbb * DBeaver 版本: 24.0.2.202404071654 * java: openjdk version "1.8.0_402" 使用docker搭建: docker搭建教程自行查阅 windows 10: https://zhuanlan.zhihu.com/p/441965046 ubuntu 22.04: https://blog.csdn.net/u011278722/article/details/137673353 docker更换国内源:https://zhuanlan.zhihu.com/p/347643668 ```shell sudo vi /etc/docker/daemon.json # 在里面加入网易docker镜像源 { "registry-mirrors": ["http://hub-mirror.c.163.com"] } # 重启docker服务 systemctl restart docker ``` 1. MySql,version:8.3.0 ```shell # 拉取最新版本的MySql docker pull mysql:8.3.0 # 运行Sql # docker run -p 主机端口:容器端口 --name 容器实例名称 -e 容器参数=参数值 -v 主机目录/容器目录 -d 镜像名称:镜像版本 docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.20 ``` 2. Postgres: 16.3 ```shell # postgres使用教程:https://www.runoob.com/postgresql/postgresql-create-database.html docker pull Postgres:16.3 docker run -it --name postgres -e POSTGRES_PASSWORD='123456' -p 5432:5432 -v ~/workspace_postgres:/var/lib/postgresql/data -d postgres:latest ``` 3. redis: 7.0.12 ```shell docker pull redis:7.0.12 docker run -p 6379:6379 --name myredis -d redis:7.0.12 --requirepass myredis ``` ## 功能介绍 ### 一、统一返回报文 使用`@RestControllerAdvice(basePackages = "com.deng")`注解ResponseBodyAdvice的实现类,实现他的supports()和beforeBodyWrite()方法 ```java @RestControllerAdvice(basePackages = "com.deng") public class ControllerResponseHandler implements ResponseBodyAdvice { private static final Logger logger = LoggerFactory.getLogger(ControllerResponseHandler.class); @Override public boolean supports(MethodParameter returnType, Class> converterType) { return !(returnType.getParameterType().isAssignableFrom(ResultVo.class) || returnType.hasMethodAnnotation(ResultSkipPack.class)); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //需要对String类型的值做额外的处理 if (returnType.getParameterType().equals(String.class)) { ObjectMapper objectMapper = new ObjectMapper(); try { return objectMapper.writeValueAsString(new ResultVo<>(body)); } catch (Exception e) { logger.warn("包装返回值失败", e); return new ResultVo<>(ResultCode.RESPONSE_PACK_ERROR); } } return new ResultVo<>(body); } } ``` ```java public class ResultVo implements Serializable { private final int code; private final String msg; private final T data; } ``` ```java public enum ResultCode { //成功、正常 SUCCESS(1000, "请求成功"), //失败 @SuppressWarnings("unused") FAILED(1001, "请求失败"), //未知错误 @SuppressWarnings("SpellCheckingInspection") UNKNOW_ERROR(1002, "未知错误"), //返回包装错误 RESPONSE_PACK_ERROR(1003, "response返回包装失败"); private final int code; private final String msg; ResultCode(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public String getMsg() { return msg; } } ``` ### 二、全局异常处理 基于springboot,使用`@ExceptionHandler({BindException.class})`,来对ResponseBodyAdvice的实现类进行注解 ```java @RestControllerAdvice(basePackages = "com.deng") public class ControllerResponseHandler { /** * 参数异常 * @param e 异常对象 * @return 异常返回体 */ @Order(Ordered.HIGHEST_PRECEDENCE) @ExceptionHandler({BindException.class}) public ResultVo methodArgumentNotValidExceptionHandler(BindException e) { //从异常对象中拿到ObjectError对象 String localizedMessage = e.getLocalizedMessage(); return new ResultVo<>(ResultCode.REQUEST_PARAM_ERROR, localizedMessage); } /** * Token校验异常 * @param e 异常对象 * @return 异常返回体 */ @Order(Ordered.HIGHEST_PRECEDENCE) @ExceptionHandler({InvalidTokenException.class}) public ResultVo methodArgumentNotValidExceptionHandler(InvalidTokenException e) { //从异常对象中拿到ObjectError对象 String localizedMessage = e.getLocalizedMessage(); return new ResultVo<>(ResultCode.UNAUTH, localizedMessage); } /** * 其他异常 * @param e 异常对象 * @return 异常返回体 */ @Order @ExceptionHandler({Exception.class}) public ResultVo otherExceptionHandler(Exception e) { //从异常对象中拿到ObjectError对象 String localizedMessage = e.getLocalizedMessage(); return new ResultVo<>(ResultCode.UNKNOW_ERROR, localizedMessage); } } ``` ### 三、精简打包文件 为了防止依赖包过大,每一次更新jar包不方便,于是将依赖移动到lib文件夹里,在启动的时候,指定依赖路径 ```xml TheOne org.springframework.boot spring-boot-maven-plugin null null ZIP org.apache.maven.plugins maven-dependency-plugin copy-dependencies package copy-dependencies ${project.build.directory}/lib false false true ``` 部署服务的时候的命令: ```shell nohup java -jar -Dloader.path=lib theDemo.jar & ``` theDemo.jar改成你自己的包名,lib改成你自己的依赖包路径