博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringMVC 中利用RequestMappingHandlerAdapter实现入参和出参的自定义封装
阅读量:7095 次
发布时间:2019-06-28

本文共 7179 字,大约阅读时间需要 23 分钟。

  hot3.png

首先来看下RequestMappingHandlerAdapter这个类的源码

/** * An {@link AbstractHandlerMethodAdapter} that supports {@link HandlerMethod}s * with the signature -- method argument and return types, defined in * {@code @RequestMapping}. * * 

Support for custom argument and return value types can be added via * {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}. * Or alternatively to re-configure all argument and return value types use * {@link #setArgumentResolvers} and {@link #setReturnValueHandlers(List)}. * * @author Rossen Stoyanchev * @since 3.1 * @see HandlerMethodArgumentResolver * @see HandlerMethodReturnValueHandler */public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { private List

customArgumentResolvers; private HandlerMethodArgumentResolverComposite argumentResolvers; private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers; private List
customReturnValueHandlers; private HandlerMethodReturnValueHandlerComposite returnValueHandlers; private List
modelAndViewResolvers; private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(); private List
> messageConverters; private WebBindingInitializer webBindingInitializer; private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync"); private Long asyncRequestTimeout;............................................

从注释中可以了解到通过设置setCustomArgumentResolvers and setCustomReturnValueHandlers可以实现自定义出参和入参的相关规则

由于RequestMappingHandlerAdapter实现了InitializingBean接口所以在初始化的时候会调用afterPropertiesSet()方法

public void afterPropertiesSet() {		if (this.argumentResolvers == null) {			List
resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this.initBinderArgumentResolvers == null) { List
resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this.returnValueHandlers == null) { List
handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } initControllerAdviceCache(); }

RequestMappingHandlerAdapter方法中有两个方法,getDefaultArgumentResolvers和getDefaultReturnValueHandlers方法,当然我们这边自定义是通过RequestMappingHandlerAdapter的customArgumentResolvers和customReturnValueHandlers属性来实现的,如果通过argumentResolvers和returnValueHandlers属性来直接设置的话,会将spring默认的请求入参和出参覆盖掉

getDefaultArgumentResolvers()方法可以看到我们自定义的入参处理类是被放在中后位置的,同样的getDefaultReturnValueHandlers()方法也是这样

/**	 * Return the list of return value handlers to use including built-in and	 * custom handlers provided via {@link #setReturnValueHandlers}.	 */	private List
getDefaultReturnValueHandlers() { List
handlers = new ArrayList
(); // Single-purpose return value types handlers.add(new ModelAndViewMethodReturnValueHandler()); handlers.add(new ModelMethodProcessor()); handlers.add(new ViewMethodReturnValueHandler()); handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager)); handlers.add(new CallableMethodReturnValueHandler()); handlers.add(new DeferredResultMethodReturnValueHandler()); handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory)); // Annotation-based return value types handlers.add(new ModelAttributeMethodProcessor(false)); handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager)); // Multi-purpose return value types handlers.add(new ViewNameMethodReturnValueHandler()); handlers.add(new MapMethodProcessor()); // Custom return value types if (getCustomReturnValueHandlers() != null) { handlers.addAll(getCustomReturnValueHandlers()); } // Catch-all if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) { handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers())); } else { handlers.add(new ModelAttributeMethodProcessor(true)); } return handlers; }

此处需要注意的是返回值的处理,由于我们自定义的是处于偏后的位置,如果其他处理类已经返回了,那么我们这边是不会再进入我们自定义的处理类中的

我们可以看到HandlerMethodArgumentResolverComposite 类

public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {      ............................/**	 * Whether the given {@linkplain MethodParameter method parameter} is supported by any registered	 * {@link HandlerMethodArgumentResolver}.	 */	public boolean supportsParameter(MethodParameter parameter) {		return getArgumentResolver(parameter) != null;	}	/**	 * Iterate over registered {@link HandlerMethodArgumentResolver}s and invoke the one that supports it.	 * @exception IllegalStateException if no suitable {@link HandlerMethodArgumentResolver} is found.	 */	public Object resolveArgument(			MethodParameter parameter, ModelAndViewContainer mavContainer,			NativeWebRequest webRequest, WebDataBinderFactory binderFactory)			throws Exception {		HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);		Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");		return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);	}......................................

实现了HandlerMethodArgumentResolver接口

而在其中

/**	 * Find a registered {@link HandlerMethodArgumentResolver} that supports the given method parameter.	 */	private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {		HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);		if (result == null) {			for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {				if (logger.isTraceEnabled()) {					logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +							parameter.getGenericParameterType() + "]");				}				if (methodArgumentResolver.supportsParameter(parameter)) {					result = methodArgumentResolver;					this.argumentResolverCache.put(parameter, result);					break;				}			}		}		return result;	}

这里的argumentResolvers就是前文指定添加的

public void afterPropertiesSet() {		if (this.argumentResolvers == null) {			List
resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this.initBinderArgumentResolvers == null) { List
resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this.returnValueHandlers == null) { List
handlers = getDefaultReturnValueHandlers(); /*********就是这里************/ this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); /*********就是这里************/ } initControllerAdviceCache(); }

 

转载于:https://my.oschina.net/guanhe/blog/974135

你可能感兴趣的文章
ajax格式,转入后台
查看>>
oracle 反向索引
查看>>
物理地址扩展PAE
查看>>
Promise
查看>>
C#编写数学集合
查看>>
利用MVC Chart 打造后台图表、前端图表(转)
查看>>
【Java】使用CSVUtils生成文件并供下载
查看>>
用户态和内核态
查看>>
VR+生物plus 遐想
查看>>
Java并发编程:线程控制
查看>>
今天聊一聊Java引用类型的强制类型转换
查看>>
把数据保存到数据库archives表时出错,请检查
查看>>
JavaSE基本语法、数据类型、操作符等:int、long、Integer、Long、if、else、for、while...
查看>>
解析XML文件
查看>>
牛客练习赛46
查看>>
netty线程模型
查看>>
Codeforces Round #237 Div.2 A
查看>>
initrd.gz的解压和制作
查看>>
LeetCode:Edit Distance(字符串编辑距离DP)
查看>>
设计流程及工具记录
查看>>