SpringMvc 在配置多个mvc:argument-resolvers
(目前是分开在不同的配置文件)
会出现覆盖问题;
实际spring容器中只会有一个文件里配置的bean
原因
debug 后发现,MVC实际是在调用一个name为org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
的RequestMappingHandlerAdapter
同时多个配置文件会导致初始化多个RequestMappingHandlerAdapter
,但是其他name的都没有用
解决方案
结合RequestMappingHandlerAdapter
存储HandlerMethodArgumentResolver
的原理
自定义类如下
package com.hui.handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 处理注入参数处理
* <p>当在多个context.xml中配置arm -resolver时,会因为加载顺序导致覆盖问题</p>
*
* @author 墨盒
* @date 19-4-9
*/
public abstract class AbstractResolverHandler implements HandlerMethodArgumentResolver, InitializingBean {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Resource(name = "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter")
protected RequestMappingHandlerAdapter adapter;
@Override
public void afterPropertiesSet() throws Exception {
if (!adapter.getArgumentResolvers().contains(this)) {
List<HandlerMethodArgumentResolver> list = adapter.getArgumentResolvers();
List<HandlerMethodArgumentResolver> nList = new ArrayList<>(list.subList(0, list.size() - 2));//原list为不可修改list,因此需要重新new一个普通list,同时可在此调整顺序
nList.add(this);//必须放过最后两个
nList.addAll(list.subList(list.size() - 2, list.size()));
adapter.setArgumentResolvers(nList);
}
//查看此时bean里注册的数据
// String[] names = context.getBeanDefinitionNames();
// for (int i = 0; i < names.length; i++) {
// logger.debug("name={},class={}", names[i], context.getBean(names[i]));
// }
}
@Override
public abstract boolean supportsParameter(MethodParameter parameter);
@Override
public abstract Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}
使用方法
继承该类,并将其托管到springMVC容器即可