前言
之前有写过博客简单过了一下,如果修改回包格式的。现在又找到一种新的方法,并且这样的方式好像更加合理。所以特地记录一下。
需求
对回包格式经行统一的封装。比如:
public class Response {
private int code;
private String requestId;
private T data;
}
而我们的业务,一般都是回复Modle对象,比如:
@RestController
public class HelloController {
@PostMapping("/hello/{name}")
public String hello(@PathVariable String name) {
return "hello " + name;
}
}
因此我们要将回包经行封装。
分析
主要用到两个接口:
- ResponseBodyAdvice
- RequestBodyAdvice
作用时机:
- ResponseBodyAdvice应用于流被写出前
- RequestBodyAdvice应用于参数被@RequestBody使用之前
实践
回包
@RestControllerAdvice
public class CommonResponse implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (!(body instanceof Response)) {
try {
Object requestId = RequestContextHolder.currentRequestAttributes().getAttribute("requestId", RequestAttributes.SCOPE_REQUEST);
Response<?> commonResponse = new Response<>(body);
if (requestId != null) {
commonResponse.setRequestId(requestId.toString());
}
return new ObjectMapper().writeValueAsString(commonResponse);
} catch (JsonProcessingException e) {
return body;
}
}
return body;
}
}
请求包
@RestControllerAdvice
public class CommonRequest implements RequestBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
int available = httpInputMessage.getBody().available();
byte[] bytes = new byte[available];
int read = httpInputMessage.getBody().read(bytes);
if (read <= 0) {
return httpInputMessage;
}
JsonNode jsonNode = new ObjectMapper().readValue(bytes, JsonNode.class);
if (!jsonNode.hasNonNull("requestId")) {
RequestContextHolder.currentRequestAttributes().setAttribute("requestId", UUID.randomUUID().toString(), RequestAttributes.SCOPE_REQUEST);
}
return new MappingJacksonInputMessage(new ByteArrayInputStream(bytes), httpInputMessage.getHeaders());
}
@Override
public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return o;
}
@Override
public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return o;
}
}
效果
效果就不展示了,markdown不好贴图。。。感兴趣的小伙伴可以下载代码试试看