对于前后端分离的项目,采用统一的返回格式可以有效减少前后端开发人员的交流成本,对于Spring MVC可以利用切面无侵入地、优雅地实现这一点。
Spring MVC提供了AbstractMappingJacksonResponseBodyAdvice抽象类对返回的JSON做二次处理
首先定义返回结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Data @AllArgsConstructor @NoArgsConstructor public class CommonResponse {
private Integer status; @JsonInclude(JsonInclude.Include.NON_NULL) private String error; private String message; @JsonInclude(JsonInclude.Include.NON_NULL) private Object data;
public static CommonResponse success(Integer status, Object data) { return new CommonResponse(status, null, "success", data); }
public static CommonResponse success(Integer status, String message, Object data) { return new CommonResponse(status, null, message, data); }
public static CommonResponse fail(Integer status, String error, String message, Object data) { return new CommonResponse(status, error, message, data); }
}
|
编写切面继承AbstractMappingJacksonResponseBodyAdvice并注入容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @RestControllerAdvice public class GlobalResponseAdvice extends AbstractMappingJacksonResponseBodyAdvice {
@Override protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) { HttpStatus code = HttpStatus.OK; final ResponseStatus responseStatus = returnType.getMethodAnnotation(ResponseStatus.class); if (responseStatus != null) { code = responseStatus.code(); }
Object body = bodyContainer.getValue(); if (!CommonResponse.class.isAssignableFrom(body.getClass())) { bodyContainer.setValue(CommonResponse.success(code.value(), body)); } }
}
|
效果
1 2 3 4 5 6 7 8 9
| { "status": 200, "message": "success", "data": { "id": 1, "username": "user1", "role": "ADMIN" } }
|