统一出参管理
统一出参只要实现 ResponseBodyAdvice
接口,并且注解增强 @RestControllerAdvice
就可以了。
实现类:
/**
* @Description:
* @author: LinQin
* @date: 2020/01/08
*/
@RestControllerAdvice
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
if (methodParameter.getMethod().getName().equals("login")) {
return true;
}
return false;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if (o instanceof ResultModel) {
((ResultModel) o).setPath(serverHttpRequest.getURI().getPath());
return o;
}
// 这里进行封装返回
ResultModel resultModel = new ResultModel();
if (isPrimitiveOrVoid(methodParameter.getParameterType())) {
ObjectNode resultNode = objectMapper.createObjectNode();
resultNode.putPOJO("result", o);
o = resultNode;
}
resultModel.setData(o);
String result = null;
try {
result = objectMapper.writeValueAsString(resultModel);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
boolean isString = methodParameter.getParameterType() == String.class;
//当返回值为字符串时,springMVC会使用StringHttpMessageConverter来处理,返回值必须为String,否则会转换异常
if (isString) {
serverHttpResponse.getHeaders().add("Content-Type",
"application/json;charset=UTF-8");
return result;
}
return resultModel;
}
private boolean isPrimitiveOrVoid(Class<?> returnType) {
return returnType.isPrimitive()
|| Number.class.isAssignableFrom(returnType)
|| CharSequence.class.isAssignableFrom(returnType)
|| Character.class.equals(returnType)
|| Boolean.class.equals(returnType);
}
}
**注意:**异常处理后的也会入到经过出参,意味着如果统一异常处理过程中进行了封装,到这里还会执行一次。因此会有封装了两层的报文,但是正常情况是正确的这种现象。
解决方案:
增加一个判断返回即可。
if (o instanceof ResultModel) {
((ResultModel) o).setPath(serverHttpRequest.getURI().getPath());
return o;
}
项目地址:GitHub