目前比较流行的架构大多都是前后端分离,后端提供服务能力,供前端调用打造业务场景功能。前后端根据定义好的协议报文进行数据交互,为了方便处理,一般报文都会是标准化格式,如下:
json 代码解读复制代码{
"Code": "string",
"ErrorMsg": "string",
"Data": [ //当ErrorMsg不为空的时候,一般是出现异常的情况,则Data为空
{
"...": "...",
"...": "..."
}
]
}
上述Data才是每个接口返回的不一样的数据,这样标准格式,很方便调用方统一处理。但如果在每一个接口返回的地方都要做一次标准格式的处理,系统中大量存在重复代码。
下面我来给大家讲述通过Spring接口统一进行处理。
认识Spring框架两个接口
RequestBodyAdvice 和 ResponseBodyAdvice 是Spring框架中的两个接口,主要用于实现全局的请求体(RequestBody)和响应体(ResponseBody)的处理,它们在Spring MVC中用于拦截和修改进入控制器方法的请求数据以及从控制器方法返回的响应数据。这两个接口的设计遵循了Spring的AOP(面向切面编程)思想,使得开发者可以在不改动原有业务逻辑的前提下,对数据进行统一的处理,比如日志记录、数据加密解密、结果封装等。
RequestBodyAdvice
RequestBodyAdvice 是Spring框架提供的一个接口,主要用于拦截和处理进入控制器方法之前的HTTP请求体(RequestBody)。它是Spring MVC中处理请求体数据的一个灵活且强大的扩展点,允许开发者在请求体被实际的方法参数绑定之前对其进行预处理或者后处理。这对于日志记录、数据转换、安全性检查或是其他任何需要在请求体数据到达具体处理器方法前进行的操作非常有用。
RequestBodyAdvice 接口定义了以下四个方法:
public interface RequestBodyAdvice {
boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException;
Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
@Nullable
Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
}
supports(MethodParameter, Class<?>):
该方法用于判断当前的RequestBodyAdvice 实例是否支持给定的方法参数和目标类型。返回true表
示支持,此时beforeBodyRead、afterBodyRead 或 handleEmptyBody 方法会被调用;反之则不
<beforeBodyRead(HttpInputMessage, MethodParameter, Type, Class<?>):
在读取请求体之前被调用,可以在这里修改输入消息,比如添加或修改HTTP头信息。
afterBodyRead(HttpInputMessage, MethodParameter, Type, Class<?>, Object):
在请求体被读取并转换为对象之后被调用。开发者可以在此方法中对转换后的对象进行进一步的处
理或修改。
handleEmptyBody(HttpInputMessage, MethodParameter, Type, Class<?>):
当请求体为空时被调用,允许自定义如何处理空请求体的情况。
ResponseBodyAdvice
ResponseBodyAdvice 是Spring框架提供的另一个接口,与RequestBodyAdvice相对应,它用于在响应体(ResponseBody)发送给客户端之前对其进行拦截和处理。这个接口允许开发者在控制器方法已经处理完业务逻辑并准备返回响应时,对响应内容进行修改、日志记录、数据转换等操作,而不必在每个控制器方法中重复相同的处理逻辑。
ResponseBodyAdvice 接口定义了以下两个方法:
public interface ResponseBodyAdvice<T> {
boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
@Nullable
T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response);
}
supports(MethodParameter, Class<?>):
同RequestBodyAdvice中的方法,用于判断当前ResponseBodyAdvice 实例是否支持给定的方法参数和
返回类型。返回true表示将介入处理过程。
-beforeBodyWrite(Object, MethodParameter, MediaType, Class<?>, ServerHttpRequest, ServerHttpResponse):
在响应体写回客户端之前被调用。开发者可以在这个方法里修改响应体对象,转换其格式,或者基于响应内容做出其他处理。返回的对象将会被序列化并写入响应流中。
请求结果返回统一格式封装
supports方法:判断是否要交给 beforeBodyWrite 方法执行,ture:需要;false:不需要。
beforeBodyWrite方法:对 response 进行具体的处理。
1)定义返回Code枚举类,定义好接口返回的code值和对应的错误描述,通过枚举类来实现。示例代码如下:
import lombok.AllArgsConstructor;
import lombok.ToString;
/**
* 接口返回code枚举类
*
*
*/
@ToString
@AllArgsConstructor
public enum CodeEnum {
SUCCESS("001","成功"),
FAIL("000","失败"),
EXCEPTION("999","接口异常");
public final String code;
public final String message;
}
2)定义统一返回结果对象,定义一个统一返回结果对象 ResultVO,示例代码如下:
import com.holmium.framwork.core.enums.CodeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.http.HttpStatus;
/**
* 统一返回结果类
*
*
*/
@Data
@AllArgsConstructor
@EqualsAndHashCode
@Builder
public class ResultVO<T> {
/**
* 请求状态
*/
private Integer status;
/**
* 请求响应代码,如:001-成功,000-失败
*/
private String code;
/**
* 请求返回信息描述或异常信息
*/
private String message;
/** * 接口请求返回业务对象数据 */
private T data;
public ResultVO() {
}
/**
* 请求成功,对返回结果进行封装
*/
public static ResultVO<?> success(Object data) {
return build(CodeEnum.SUCCESS.code,CodeEnum.SUCCESS.message,data);
}
/**
* 请求失败,对返回结果进行封装
*/
public static ResultVO<?> failed(String message) {
return build(CodeEnum.FAIL.code,message,null);
}