Java项目:Java脚手架项目的统一模块的封装(四)
统一模块封装摘要 本文介绍了在common工程下创建common-domain模块,并封装统一状态码和响应数据结构的过程。
文章目录
鸡汤:
● 你不是在等待风暴过去,而是在学习如何在雨中起舞。
● 累了就靠在窗边看云,难过了就允许眼泪流下来,迷茫时就对自己说:“今天已经很努力了。”真正的勇敢,不是永不疲惫,而是带着伤痕依然选择温柔;真正的强大,不是完美无缺,而是接纳自己的脆弱后,依然愿意相信明天。
前言
前面我们封装了 common-core 通用基础包 和 实现了 mstemplate 模板服务和 gateway 网关服务,现在让我们封装一下统一模块。
一、在common 工程下创建 common-domain
怎么创建工程我就不再演示了,结果
1.1 封装统一状态码
1.1.1 为什么要封装统一状态码?
● 简化接口使用方开发:接口的使用方无需担心不同接口返回不同的状态码,他们可以编写统一的解析逻辑来处理相应。
● 明确性:状态码提供了一种明确的信息来表示接口的状态。与返回的信息相比,状态码能精准地指出问题所在。
● 易检索:状态码通常是数字,便于日志、监控系统或错误跟踪系统中的检索和过滤。
● 维护性:集中管理状态码使得它们更容易维护和更新。如果业务逻辑发生变化,只需要更新错误码的定义,而不需要修改每个使用它们的地方。
● 错误分类:状态码可以帮助将错误分类为不同的级别或类型,如客户端错误、服务器错误、业务逻辑错误等。
● 统一性:不同的项目可能针对于项目的特殊情况需要一些特殊的状态码,但是对于绝大多数状态码都是可以统一的。
1.1.2 在 common-domain 下创建 package
创建 com.my.commomdomain 的package
1.1.3 在 commomdomain 创建 domain 包

1.1.4 创建 ResultCode 的统一状态码枚举类并封装

ResultCode :
package com.my.commondomain.domain;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 响应码
*/
@AllArgsConstructor
@Getter
public enum ResultCode {
//---------------------------2xx
/**
* 操作成功
*/
SUCCESS (200000, "操作成功"),
//------------------------4xx
//400
/**
* 无效的参数
*/
INVALID_PARA (400000, "无效的参数"),
/**
* 无效的验证码
*/
INVALID_CODE (400001, "无效的验证码"),
/**
* 错误的验证码
*/
ERROR_CODE (400002, "错误的验证码"),
/**
* 手机号格式错误
*/
ERROR_PHONE_FORMAT (400003, "手机号格式错误"),
/**
* 超过每日发送次数限制
*/
SEND_MSG_OVERLIMIT (400004, "超过每日发送次数限制"),
/**
* 无效的区划
*/
INVALID_REGION (400005, "无效的区划"),
/**
* 参数类型不匹配
*/
PARA_TYPE_MISMATCH (400006, "参数类型不匹配"),
/**
* 账号已停用,登录失败
*/
USER_DISABLE (400007, "账号已停用,登录失败"),
//401
/**
* 令牌不能为空
*/
TOKEN_EMPTY (401000, "令牌不能为空"),
/**
* 令牌已过期或验证不正确!
*/
TOKEN_INVALID (401001, "令牌已过期或验证不正确!"),
/**
* 令牌已过期!
*/
TOKEN_OVERTIME (401002, "令牌已过期!"),
/**
* 登录状态已过期!
*/
LOGIN_STATUS_OVERTIME (401003, "登录状态已过期!"),
/**
* 令牌验证失败!
*/
TOKEN_CHECK_FAILED (401004, "令牌验证失败!"),
//404
/**
* 服务未找到!
*/
SERVICE_NOT_FOUND (404000, "服务未找到"),
URL_NOT_FOUND (404001, "url未找到"),
//405
/**
* 请求方法不支持!
*/
REQUEST_METNHOD_NOT_SUPPORTED (405000, "请求方法不支持"),
//---------------------5xx
/**
* 服务繁忙请稍后重试!
*/
ERROR (500000, "服务繁忙请稍后重试"),
/**
* 操作失败
*/
FAILED (500001, "操作失败"),
/**
* 短信发送失败
*/
SEND_MSG_FAILED (500002, "短信发送失败"),
/**
* 获取直传地址失败
*/
PRE_SIGN_URL_FAILED (500003, "获取直传地址失败"),
/**
* 上传oss异常,请稍后重试
*/
OSS_UPLOAD_FAILED (500004, "上传oss异常,请稍后重试"),
/**
* 获取地图数据失败,请稍后重试
*/
QQMAP_QUERY_FAILED (500005, "获取地图数据失败,请稍后重试"),
/**
* 城市信息获取失败
*/
QQMAP_CITY_UNKNOW (500006, "城市信息获取失败"),
/**
* 根据位置获取城市失败
*/
QQMAP_LOCATE_FAILED (500007, "根据位置获取城市失败"),
/**
* 地图特性未开启
*/
MAP_NOT_ENABLED (500008, "地图特性未开启,开启方式参考使用手册"),
/**
* 地图区划特性未开启
*/
MAP_REGION_NOT_ENABLED (500009, "地图区划特性未开启,开启方式参考使用手册"),
//---------------------枚举占位
/**
* 占位专用
*/
RESERVED (99999999, "占位专用");
/**
* 响应码
*/
private int code;
/**
* 响应消息
*/
private String msg;
}
注:
这里只封装了通用的状态码,开发者可以根据自己的意愿进行修改
1.2 封装统一响应数据结构
1.2.1 为什么要封装统一响应数据结构?
● 简化接口使用方(前端)开发:接口的使用方无需担心不同接口返回不同的响应数据结构,他们可以编写统一的解析逻辑来处理响应。
● 状态码和消息:响应数据结构中包含状态码(状态码:code)和消息( msg 一般为状态码消息,也可自定义),帮助接口使用方(前端)快速识别和处理错误。
● 业务逻辑解耦:将业务逻辑与响应格式分离,使得后端开发者可以专注于业务逻辑的实现,而不必关心如何构建HTTP响应。
● 统一性:不同的项目可能针对于项目的特殊情况对响应数据结构进行微调,一般不会有大的调整。
1.2.2 在 domain 在创建 R 类
R:
package com.my.commondomain.domain;
import lombok.Getter;
import lombok.Setter;
/**
* 响应报文封装
*
* @param <T> 响应数据
*/
@Getter
@Setter
public class R<T> {
/**
* 响应码
*/
private int code;
/**
* 消息
*/
private String msg;
/**
* 数据
*/
private T data;
/**
* 成功响应
*
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> success() {
return R.buildResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), null);
}
/**
* 成功响应
* @param data 响应数据
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> success(T data) {
return R.buildResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), data);
}
/**
* 成功响应
* @param data 响应数据
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> success(String msg, T data) {
return R.buildResult(ResultCode.SUCCESS.getCode(), msg, data);
}
/**
* 失败响应
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail() {
return R.buildResult(ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg(), null);
}
/**
* 失败响应
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(String msg) {
return R.buildResult(ResultCode.ERROR.getCode(), msg, null);
}
/**
* 失败响应
* 自定义code要将code放入ResultCode中
* @param code 响应码
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(int code, String msg) {
return R.buildResult(code, msg, null);
}
/**
* 失败响应
* @param data 响应数据
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(T data) {
return R.buildResult(ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg(), data);
}
/**
* 失败响应
* @param data 响应数据
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(String msg, T data) {
return R.buildResult(ResultCode.ERROR.getCode(), msg, data);
}
/**
* 响应结果
* @param data 响应数据
* @param code 响应编码
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
private static <T> R<T> buildResult(int code, String msg, T data) {
R<T> result = new R<>();
result.setCode(code);
result.setMsg(msg);
result.setData(data);
return result;
}
}
1.3 设置自定义异常
1.3.1 为什么需要自定义异常?
在开发过程中内置异常往往不能满足我们的需求。而自定义异常可以给开发者提供明确的提示
优点:
● 语义清晰:命名直指问题,提升代码可读性与维护性
● 携带上下文:可扩展字段存储错误码、业务数据等,助力调试与日志追踪
● 将技术错误与业务逻辑解耦
1.3.2 在 common-domain 下创建 exception 包

1.3.3 在 exception 包下创建 ServiceException 自定义异常

ServiceException:
package com.my.commondomain.domain;
import lombok.Getter;
import lombok.Setter;
/**
* 响应报文封装
*
* @param <T> 响应数据
*/
@Getter
@Setter
public class R<T> {
/**
* 响应码
*/
private int code;
/**
* 消息
*/
private String msg;
/**
* 数据
*/
private T data;
/**
* 成功响应
*
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> success() {
return R.buildResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), null);
}
/**
* 成功响应
* @param data 响应数据
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> success(T data) {
return R.buildResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), data);
}
/**
* 成功响应
* @param data 响应数据
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> success(String msg, T data) {
return R.buildResult(ResultCode.SUCCESS.getCode(), msg, data);
}
/**
* 失败响应
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail() {
return R.buildResult(ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg(), null);
}
/**
* 失败响应
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(String msg) {
return R.buildResult(ResultCode.ERROR.getCode(), msg, null);
}
/**
* 失败响应
* 自定义code要将code放入ResultCode中
* @param code 响应码
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(int code, String msg) {
return R.buildResult(code, msg, null);
}
/**
* 失败响应
* @param data 响应数据
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(T data) {
return R.buildResult(ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg(), data);
}
/**
* 失败响应
* @param data 响应数据
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(String msg, T data) {
return R.buildResult(ResultCode.ERROR.getCode(), msg, data);
}
/**
* 响应结果
* @param data 响应数据
* @param code 响应编码
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
private static <T> R<T> buildResult(int code, String msg, T data) {
R<T> result = new R<>();
result.setCode(code);
result.setMsg(msg);
result.setData(data);
return result;
}
}
二、在common 工程下创建 common-security
创建 common-security:
2.1 添加依赖
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.my</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.my</groupId>
<artifactId>common-security</artifactId>
<version>1.0-SNAPSHOT</version>
<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>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringCloud Loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.my</groupId>
<artifactId>common-domain</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.my</groupId>
<artifactId>common-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
</dependencies>
</project>
2.2 封装统一异常处理
2.2.1 创建包目录

2.2.2 在 commonsecurity 下创建 handler 包

2.2.3 创建 GlobalExceptionHandler 类

GlobalExceptionHandler:
package com.my.commonsecurity.handler;
import com.my.commondomain.domain.R;
import com.my.commondomain.domain.ResultCode;
import com.my.commondomain.exception.ServiceException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import java.util.List;
import java.util.stream.Collectors;
/**
* 全局异常处理器
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 设置http响应码
*
* @param response 响应信息
* @param errcode 响应码
*/
private void setResponseCode(HttpServletResponse response,Integer errcode){
int httpCode = Integer.parseInt(String.valueOf(errcode).substring(0,3));
response.setStatus(httpCode);
}
/**
* 请求方式不支持
* @param e 异常信息
* @param request 请求
* @param response 响应
* @return 异常结果
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public R<?> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
HttpServletRequest request,
HttpServletResponse response) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
setResponseCode(response, ResultCode.REQUEST_METNHOD_NOT_SUPPORTED.getCode());
return R.fail(ResultCode.REQUEST_METNHOD_NOT_SUPPORTED.getCode(), ResultCode.REQUEST_METNHOD_NOT_SUPPORTED.getMsg());
}
/**
* 类型不匹配异常
*
* @param e 异常信息
* @param response 响应
* @return 不匹配结果
*/
@ExceptionHandler({MethodArgumentTypeMismatchException.class})
public R<?> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e,
HttpServletResponse response) {
log.error("类型不匹配异常",e);
setResponseCode(response, ResultCode.PARA_TYPE_MISMATCH.getCode());
return R.fail(ResultCode.PARA_TYPE_MISMATCH.getCode(), ResultCode.PARA_TYPE_MISMATCH.getMsg());
}
/**
* url未找到异常
*
* @param e 异常信息
* @param response 响应
* @return 异常结果
*/
@ExceptionHandler({NoResourceFoundException.class})
public R<?> handleMethodNoResourceFoundException(NoResourceFoundException e,
HttpServletResponse response) {
log.error("url未找到异常",e);
setResponseCode(response, ResultCode.URL_NOT_FOUND.getCode());
return R.fail(ResultCode.URL_NOT_FOUND.getCode(), ResultCode.URL_NOT_FOUND.getMsg());
}
/**
* 业务异常
*
* @param e 异常信息
* @param request 请求
* @param response 响应
* @return 业务异常结果
*/
@ExceptionHandler(ServiceException.class)
public R<?> handleServiceException(ServiceException e, HttpServletRequest request,
HttpServletResponse response) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生业务异常", requestURI, e);
setResponseCode(response,e.getCode());
return R.fail(e.getCode(), e.getMsg());
}
/**
* 参数校验异常
* @param e 异常信息
* @param request 请求
* @param response 响应
* @return 异常报文
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request,
HttpServletResponse response) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生参数校验异常", requestURI, e);
setResponseCode(response, ResultCode.INVALID_PARA.getCode());
String message = joinMessage(e);
return R.fail(ResultCode.INVALID_PARA.getCode(), message);
}
private String joinMessage(MethodArgumentNotValidException e) {
List<ObjectError> allErrors = e.getAllErrors();
if (CollectionUtils.isEmpty(allErrors)) {
return "";
}
// List<String> collect = allErrors.stream().map(ObjectError::getDefaultMessage).collect(Collectors.toList());
return allErrors.stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(", "));
}
/**
* 参数校验异常
* @param e 异常信息
* @param request 请求
* @param response 响应
* @return 异常报文
*/
@ExceptionHandler({ConstraintViolationException.class})
public R<Void> handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request,
HttpServletResponse response) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}', 发生参数校验异常",requestURI, e);
setResponseCode(response,ResultCode.INVALID_PARA.getCode());
String message = e.getMessage();
return R.fail(ResultCode.INVALID_PARA.getCode(),message);
}
/**
* 拦截运行时异常
*
* @param e 异常信息
* @param request 请求信息
* @param response 响应信息
* @return 响应结果
*/
@ExceptionHandler(RuntimeException.class)
public R<?> handleRuntimeException(RuntimeException e, HttpServletRequest request,
HttpServletResponse response) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生运行时异常.", requestURI, e);
setResponseCode(response, ResultCode.ERROR.getCode());
return R.fail(ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg());
}
/**
* 系统异常
* @param e 异常信息
* @param request 请求
* @param response 响应
* @return 响应结果
*/
@ExceptionHandler(Exception.class)
public R<?> handleException(Exception e, HttpServletRequest request,
HttpServletResponse response) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生异常.", requestURI, e);
setResponseCode(response, ResultCode.ERROR.getCode());
return R.fail(ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg());
}
}
2.2.4 在 resources 下创建自动配置
自动配置目录 : META.spring.org.springframework.boot.autoconfigure.AutoConfiguration.imports

将全局异常处理器添加进自动配置目录里
三、在网关层添加异常处理

上面的统一异常处理,作用在服务层,而网关层就无能为力了,所以我们还要在网关层也安排上统一异常处理
3.1 在 gateway 工程下创建 handler 包

3.2 在 handler 包下创建 GatewayExceptionHandler

GatewayExceptionHandler:
package com.my.gateway.handler;
import com.my.commoncore.utils.JsonUtil;
import com.my.commoncore.utils.ServletUtil;
import com.my.commondomain.domain.R;
import com.my.commondomain.domain.ResultCode;
import com.my.commondomain.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.resource.NoResourceFoundException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
/**
* 网关统一异常处理
*/
@Order(-1)
@Configuration
@Slf4j
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
/**
* 处理器
*
* @param exchange ServerWebExchange
* @param ex 异常信息
* @return 无
*/
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
ServerHttpResponse response = exchange.getResponse();
//响应已经提交到客户端,无法再对这个响应进行常规的异常处理修改了,直接返回一个包含原始异常ex的Mono.error(ex)
if (response.isCommitted()) {
return Mono.error(ex);
}
int retCode = ResultCode.ERROR.getCode();
String retMsg = ResultCode.ERROR.getMsg();
if (ex instanceof NoResourceFoundException) {
retCode = ResultCode.SERVICE_NOT_FOUND.getCode();
retMsg = ResultCode.SERVICE_NOT_FOUND.getMsg();
} else if (ex instanceof ServiceException) {
retCode = ((ServiceException) ex).getCode();
retMsg = ((ServiceException) ex).getMsg();
}
int httpCode = Integer.parseInt(String.valueOf(retCode).substring(0,3));
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().
getPath(), ex.getMessage());
// servlet 工具类
return ServletUtil.webFluxResponseWriter(response, HttpStatus.valueOf(httpCode),retMsg, retCode);
// return webFluxResponseWriter(response, HttpStatus.valueOf(httpCode),retMsg, retCode);
}
private Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus httpStatus, String retMsg, int retCode) {
return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE,httpStatus,retMsg,retCode);
}
private Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String applicationJsonValue, HttpStatus httpStatus, String retMsg, int retCode) {
response.setStatusCode(httpStatus);
response.getHeaders().add(HttpHeaders.CONTENT_TYPE,applicationJsonValue);
R<?> result = R.fail(retCode,retMsg);
DataBuffer wrap = response.bufferFactory().wrap(JsonUtil.toJson(result).getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(wrap));
}
}
这个 ServletUtil 工具类是后加进 common-core 里的工具类,开发就是这样的,写着写着就发现有些东西是通用的东西,可以封装一下
ServletUtil:
package com.my.commoncore.utils;
import com.my.commondomain.constants.CommonConstants;
import com.my.commondomain.domain.R;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* Servlet工具类
*/
public class ServletUtil {
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str) {
try {
return URLEncoder.encode(str, CommonConstants.UTF8);
} catch (UnsupportedEncodingException e) {
return StringUtils.EMPTY;
}
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param code 响应状态码
* @param value 响应内容
* @return 无
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value, int code) {
return webFluxResponseWriter(response, HttpStatus.OK, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return 无
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code) {
//修改了
return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param contentType content-type
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return 无
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code) {
response.setStatusCode(status);
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
R<?> result = R.fail(code, value.toString());
DataBuffer dataBuffer = response.bufferFactory().wrap(JsonUtil.toJson(result).getBytes());
return response.writeWith(Mono.just(dataBuffer));
}
/**
* 获取request
*
* @return request对象
*/
public static HttpServletRequest getRequest() {
try {
return getRequestAttributes().getRequest();
} catch (Exception e) {
return null;
}
}
/**
* 获取request属性信息
* 根据当前线程处理的请求获取 ServletRequestAttributes
* ServletRequestAttributes 包含request 和 response
* @return request属性
*/
public static ServletRequestAttributes getRequestAttributes() {
try {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
} catch (Exception e) {
return null;
}
}
}
四、验证
直接拿 mstemplate 模版服务来进行验证,将 common-domain 和 common-security 的依赖引入模板服务,搞一个 controller 层,拿浏览器验证一下

简单测试一下
TestController:
package com.my.mstemplateservice.test;
import com.my.commondomain.domain.R;
import com.my.commondomain.domain.ResultCode;
import com.my.commondomain.exception.ServiceException;
import com.my.mstemplateservice.domain.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
@RequestMapping("/test")
public class TestController {
@GetMapping("/info")
public void info() {
log.info("接口调用测试");
}
// @GetMapping("/result")
// public R<Void> result(int id) {
// if(id > 0) {
// return R.success();
// }else {
// return R.fail();
// }
// }
@GetMapping("/result")
public R<User> result(int id) {
if(id <= 0) {
return R.fail("id小于0");
}
User user = new User();
user.setAge(id);
user.setName("test");
return R.success(user);
}
@GetMapping("/exception")
public R<Void> exception(int id) {
if (id < 0) {
throw new ServiceException(ResultCode.ERROR_CODE);
}
if (id == 1) {
throw new ServiceException("id 不能等于1");
}
if (id == 1000) {
throw new ServiceException("奇奇怪怪的异常信息",344556);
}
return R.success();
}
}
前面的工具类啥的也要测一下,我忘了。。。😅
通过网关调用模板服务的 controller ,检验统一异常处理的结果:


END
接下来开始组件的封装
更多推荐



所有评论(0)