自定义结果包装类要实现接口
HandlerMethodReturnValueHandler
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter var1);
void handleReturnValue(@Nullable Object var1, MethodParameter var2, ModelAndViewContainer var3, NativeWebRequest var4) throws Exception;
}
- supportsReturnType 表示是否支持该返回类型
- handleReturnValue 对于返回值的处理
spring的默认处理类是
RequestResponseBodyMethodProcessor
,它是根据判断是否有
@ResponseBody
注解来处理的。
public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// Try even with null return value. ResponseBodyAdvice could get involved.
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
}
看一下
RequestResponseBodyMethodProcessor
的注入方式:
可以看到
RequestResponseBodyMethodProcessor
在
RequestMappingHandlerAdapter
通过new直接创建的。我们是不是可以通过在
customReturnValueHandlers
添加自定义返回处理类呢,但是spring在选择handler的时候是根据顺序进行选取的,所以自定义包装处理类肯定在
RequestResponseBodyMethodProcessor
后面,达不到我们的要求。
所以我们的做法就是把handlers里的
RequestResponseBodyMethodProcessor
替换成我们的自定义包装类。
首先我们看我们的自定义包装类:
@Slf4j
public class ExampleHandler implements HandlerMethodReturnValueHandler {
/**
* 表示是否支持该返回类型
*/
@Override
public boolean supportsReturnType(MethodParameter methodParameter) {
boolean hasJSONAnno = methodParameter.getMethodAnnotation(ResponseJson.class) != null || methodParameter.getMethodAnnotation(ResponseJson.class) != null;
return hasJSONAnno;
}
/**
* o 就是接口返回值
* methodParameter 方法参数
*/
@Override
public void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest)throws Exception {
modelAndViewContainer.setRequestHandled(true);
HttpServletResponse response = (HttpServletResponse)nativeWebRequest.getNativeResponse(HttpServletResponse.class);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
this.log.info("请求成功,返回消息转换");
Map<String, Object> rsp = new HashMap();
rsp.put("code", "0");
rsp.put("message", "成功");
if (o != null)
rsp.put("data", o);
this.returnMsg(rsp, response);
}
private void returnMsg(Object msg, HttpServletResponse response) {
try(PrintWriter writer = response.getWriter();){
response.setContentType("text/plain;charset=UTF-8");
writer.write(this.objToJsonString(msg));
writer.flush();
} catch (IOException var8) {
this.log.error("统一格式返回", var8);
}
}
private String objToJsonString(Object msg) {
return JSON.toJSONString(msg, new SerializerFeature[]{SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.WriteNullBooleanAsFalse});
}
}
自己写一个配置类,注入
RequestMappingHandlerAdapter
把其中的handlers中的
RequestResponseBodyMethodProcessor
替换成我们自定义的包装类就可以了
/**
* @创建人 liuzhihui
* @创建时间 2019/11/27
* @描述 把spingmvc 自带的ReturnValueHandlersList(含@ResponseBody的handler) 替换成带自定义的ReturnValueHandlersList
*/
@Configuration
public class ReturnValueConfig implements InitializingBean {
@Autowired
RequestMappingHandlerAdapter requestMappingHandlerAdapter;
@Override
public void afterPropertiesSet() throws Exception {
List<HandlerMethodReturnValueHandler> handlerMethodReturnValueHandlers=requestMappingHandlerAdapter.getReturnValueHandlers();
List<HandlerMethodReturnValueHandler> handlerMethodReturnValueHandlers1=new ArrayList<>(handlerMethodReturnValueHandlers.size());
handlerMethodReturnValueHandlers.forEach(handlerMethodReturnValueHandler -> {
if (handlerMethodReturnValueHandler instanceof RequestResponseBodyMethodProcessor )
handlerMethodReturnValueHandlers1.add(new ExampleHandler());
else
handlerMethodReturnValueHandlers1.add(handlerMethodReturnValueHandler);
});
requestMappingHandlerAdapter.setReturnValueHandlers(handlerMethodReturnValueHandlers1);
}
}
注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseJson {
}
测试:
@RestController
public class HandlerController {
@ResponseJson
@GetMapping("/test")
public Teacher test(@RequestParam(value="name") String name){
// 处理逻辑
Teacher student = new Teacher();
student.setName(name);
return student;
}
}
结果:
{“code”:“0”,“data”:{“age”:0,“id”:0,“name”:“123”},“message”:“成功”}
具体代码:
https://github.com/lzhharvey/ReturnValueDemo
参考:
https://www.jianshu.com/p/bad06d4fe9df