1. 場景
在springmvc 的controller需要統(tǒng)一的返回接口骑祟,比如:需要在后臺所有接口返回統(tǒng)一的json字符串放坏∠耄可以通過自定義注解巩螃,通過 HandlerMethodReturnValueHandler 對返回值的處理甚淡,該接口會在返回值之前大诸,執(zhí)行該接口的內(nèi)部邏輯。
假設(shè)現(xiàn)在想返回一個接送字符串贯卦。格式:
{
status: 200
code : success
data :{
age: 100,
name : 小明
}
}
1. 創(chuàng)建返回結(jié)果類
public class ResponseResult<T> {
public Integer status;
public String code;
public T data;
// 構(gòu)造 setter...
}
1. 創(chuàng)建一個返回結(jié)果的自定義注解包裝類:
public @Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseJson{
public String className() default "ResponseResult"; // 全路徑名
}
2. 定義controller 邏輯资柔,假設(shè)有如下一個接口,我們需要對返回值進行包裝成ResponseResulltJson結(jié)構(gòu),加上自定義注解撵割。
@ResponseResulltJson
@GetMapping(“/test”)
public Student test(@RequestParam(value="name") String name){
// 處理邏輯
Student student = new Student();
student.setName(name);
return student;
}
- 創(chuàng)建HandlerMethodReturnValueHandler接口實現(xiàn)類,下面的o就是上面test接口的返回值贿堰。
public class ExampleHandler implements HandlerMethodReturnValueHandler {
@Override
publicboolean supportsReturnType(MethodParameter methodParameter) {
return methodParameter.hasMethodAnnotation(ResponseJson.class);
}
@Override
public void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest)throws Exception {
HttpServletResponse response =
nativeWebRequest.getNativeResponse(HttpServletResponse.class);
response.setConentTpye(MediaType.APPLICATION_JSON_VALUE);
response.setCharactrer("UTF-8");
ResponseJson json = methodParameter.getAnnation(ResponseJson .class);
// 得到需要反射類對象,即結(jié)果類
Class responseResult= json.className();
// 通過反射從構(gòu)造放入注入啡彬,需要注意羹与,通過構(gòu)造器注入的參數(shù)和newInstance傳入的必須一致。
Object rp = Class.forName(responseResult).getConstrtor(Object.class).newInstance(o);
// 通過guava中Gson來json化庶灿,或者FastJson
Gson gson = new GSon();
response.getWriter().write(gson.toJson(rp));
}
}
4. 把上面的的handler添加進RequestMappingHandlerAdapter適配器中
public class RequestMappingHandlerAdapterWrapper{
@Autowired
private RequestMappingHandlerAdapter handlerAdapter;
@PostConstruct
public void register(){
handlerAdapter.setReturnValueHandlers(new ArrayList<RequestMappingHandlerAdapter >({{
this.add(new ExampleHandler ());
this.addAll(RequestMappingHandlerAdapterWrapper.this.handlerAdapter.[getReturnValueHandlers](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.html#getReturnValueHandlers--)())纵搁;
}}))
}
}
為什么上面這樣寫就可以在Controller中的返回結(jié)果調(diào)用到這個處理器。
在RequestMappingHandlerAdapter中實現(xiàn)了InitializingBean這個接口往踢,該接口具有唯一的函數(shù)AfterPropertiesSet(),意思是在容器啟動時腾誉,會調(diào)用這個方法,該方法主要設(shè)置了一些默認的handlers,在初始化方法中主要有三種利职,@PostContruct趣效、xml的init-method,實現(xiàn)InitalizingBean接口猪贪。這三種的執(zhí)行順序時@PostContruct英支、InitalizingBean、init-method,因此上面的register會先于AfterPropertiesSet方法執(zhí)行哮伟,自然可以在設(shè)置默認的handler時起作用干花。
Data:2019/3/10