赞
踩
HandlerAdapter处理器适配器就是去调用处理器方法!
// 解析@RequestMapping注解 生成路径和控制器方法得映射关系 RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class); // 查看生成的结果 key为路径信息 | 请求方式,value为method Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods(); handlerMethods.forEach((k,v)->{ System.out.println(k + "=" + v); }); // 请求来了,获取控制器方法 这里返回的不是handlerMethod返回处理器执行链,里面包括了请求的拦截器 HandlerExecutionChain chain = requestMappingHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/test1")); System.out.println(chain); // 拿到 RequestMappingHandlerAdapter MyRequestHandlerAdapter adapter = context.getBean(MyRequestHandlerAdapter.class); adapter.invokeHandlerMethod(new MockHttpServletRequest("GET","test1"),new MockHttpServletResponse(),(HandlerMethod) chain.getHandler());
通过RequestMappingHandlerMapping找到对应请求对应的执行链,然后使用handlerAdapter去执行这个请求对应的方法。
其中HandlerAdapter中又做了对方法参数进行解析的工作;下文中将进行介绍。
// 拿到适配器中的参数解析器解析请求中的参数映射到handlermethod方法上
List<HandlerMethodArgumentResolver> argumentResolvers = adapter.getArgumentResolvers();
for (HandlerMethodArgumentResolver argumentResolver : argumentResolvers) {
System.out.println(argumentResolver);
}
@PostMapping("/test3")
public String test3(@Token String token){
log.info("test3() :{}",token);
return "test3";
}
public class TokenArgumentResolver implements HandlerMethodArgumentResolver { // 解析器是否支持某个参数 判断是否加了我们的@Token注解 @Override public boolean supportsParameter(MethodParameter parameter) { Token token = parameter.getParameterAnnotation(Token.class); return token != null; } // 具体解析参数 @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { // 拿到请求中的token return webRequest.getHeader("token"); } } 将参数解析器加入adapter中 @Bean public MyRequestHandlerAdapter myRequestHandlerAdapter(){ TokenArgumentResolver tokenArgumentResolver = new TokenArgumentResolver(); MyRequestHandlerAdapter handlerAdapter = new MyRequestHandlerAdapter(); handlerAdapter.setCustomArgumentResolvers(List.of(tokenArgumentResolver)); return handlerAdapter; }
具体执行
// 拿到 RequestMappingHandlerAdapter
MyRequestHandlerAdapter adapter = context.getBean(MyRequestHandlerAdapter.class);
// 验证自定义参数解析器
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test3");
request.addHeader("token","fucku");
// 拿到当前请求对应的执行链
HandlerExecutionChain executionChain = requestMappingHandlerMapping.getHandler(request);
// 执行请求对应的方法
adapter.invokeHandlerMethod(request,new MockHttpServletResponse(),(HandlerMethod) executionChain.getHandler());
// 返回值解析器
List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
System.out.println(returnValueHandler);
}
方法上加上此注解代表返回值类型要被解析为yml格式
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Yml {
}
controller中使用
@PostMapping("/test3")
@Yml
public User test3(@Token String token){
log.info("test3() :{}",token);
return new User(token);
}
参数解析器编写
@Slf4j public class YmlReturnValueHandler implements HandlerMethodReturnValueHandler { // 如果要返回的参数得方法加上了yml注解那么就执行 @Override public boolean supportsReturnType(MethodParameter returnType) { Yml yml = returnType.getMethodAnnotation(Yml.class); return yml != null; } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 1.转换返回结果为yml String str = new Yaml().dump(returnValue); // 2.把字符串写入到response字符流中 HttpServletResponse nativeResponse = webRequest.getNativeResponse(HttpServletResponse.class); nativeResponse.setContentType("text/plain;charset=utf-8"); nativeResponse.getWriter().print(str); // 3. 设置请求已经处理完毕 mavContainer.setRequestHandled(true); } }
将自定义的参数解析器加入到配置中
@Bean
public MyRequestHandlerAdapter myRequestHandlerAdapter(){
TokenArgumentResolver tokenArgumentResolver = new TokenArgumentResolver();
// 配置自定义参数解析器
MyRequestHandlerAdapter handlerAdapter = new MyRequestHandlerAdapter();
handlerAdapter.setCustomArgumentResolvers(List.of(tokenArgumentResolver));
// 配置自定义返回值解析器
YmlReturnValueHandler ymlReturnValueHandler = new YmlReturnValueHandler();
handlerAdapter.setCustomReturnValueHandlers(List.of(ymlReturnValueHandler));
return handlerAdapter;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。