SpringMVC自定义注入controller变量
问题描述
在SpringMVC中默认可以注入Model,ModelAndView,@RequestParam,@PathVariable 等,那么这个是怎么实现的,以及怎么注入一个自定义的参数呢
HandlerMethodArgumentResolver
在SpringMVC中有一个接口HandlerMethodArgumentResolver,这个就是用来控制解析controller中的参数类型来进行注入的,下面是一个自定义参数的例子
首先自定义resolver
public class MyHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
//用来判断参数是否支持当前resolver
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> klass = parameter.getParameterType();
if (klass == String.class) {//这里使用参数类型匹配,MethodParameter还包含了方法注解和参数注解信息,可以使用它们来进行识别
return true;
}
return false;
}
//真正返回要注入的值
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
return "custom string";
}
}
注册在配置文件中
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="web.controller.MyHandlerMethodArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
之后就可以使用了
@RequestMapping("test")
@ResponseBody
public String test(String a){
return a;
}
在页面访问test连接显示的就是自定义的“custom string”。
实现
下面来看下这个的实现,在MVC启动时会生成一个Resolver的Composite对象,这个包含了所有的注册的Resolver
在HandlerMethodArgumentResolverComposite中有如下几个方法
//每个参数都会调用resolveArgument进行解析
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)throws Exception {
//获得对应的resolver
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");
//使用resolver进行解析
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
//获得相应的resolver
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
//这里有个ConcurrentHashMap构成的cache可以避免重复的解析
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
//如果cache没有命中则进行解析
if (result == null) {
//遍历所有resolver
for (HandlerMethodArgumentResolver methodArgumentResolver : argumentResolvers) {
if (logger.isTraceEnabled()) {
logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
parameter.getGenericParameterType() + "]");
}
//找到对应resolver并存入cache
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
那自定义的resolver是如何被springmvc探测到的呢,这里列出argumentResolvers初始化时的赋值
// Annotation-based argument resolution
//基于注解的resolver明显有RequestParam,PathVariable等
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// Type-based argument resolution
//基于类型的resolver如Request,Response等
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
//这里就是自定义的了resolver了
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
//垫底的resolver,第一个RequestParamMethodArgumentResolver与前面注册的第二个构造参数不同主要用来拦截未标注注解的普通变量(如CharSequence,Number,List等)
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
总结
本文看了自定义controller参数的解析过程
SpringMVC自定义注入controller变量的更多相关文章
- SpringMVC常用注解@Controller,@Service,@repository,@Component
SpringMVC常用注解@Controller,@Service,@repository,@Component controller层使用@controller注解 @Controller 用于标记 ...
- SpringMVC——自定义拦截器、异常处理以及父子容器配置
自定义拦截器: 一.若想实现自定义拦截器,需要实现 org.springframework.web.servlet.HandlerInterceptor 接口. 二.HandlerIntercepto ...
- SpringMVC页面向Controller传参
关于SpringMVC页面向Controller传参的问题,看了网上不少帖子,大多总结为以下几类: 1.直接把页面表单中相关元素的name属性对应的值作为Controller方法中的形参. 这个应该是 ...
- SpringMVC自定义类型转换器
SpringMVC 自定义类型转换器 我们在使用SpringMVC时,常常需要把表单中的参数映射到我们对象的属性中,我们可以在默认的spring-servlet.xml加上如下的配置即可做到普通数据 ...
- ThinkPHP框架配置自定义的模板变量(十)
原文:ThinkPHP框架配置自定义的模板变量(十) 模板替换(手册有详细介绍对应的目录) __PUBLIC__:会被替换成当前网站的公共目录 通常是 /Public/ __ROOT__: 会替换成当 ...
- Spring注入静态变量的方法,以及CXF如何获取客户端IP
1.如果使用@Resource注解来注入静态变量的,服务器启动就会报错的.可以新增一个set方法,同时在set方法上用@Resource注解来注入. 2.或者直接在Spring的配置文件中使用< ...
- SpringBoot使用@Value从yml文件取值为空--注入静态变量
SpringBoot使用@Value从yml文件取值为空--注入静态变量 1.application.yml中配置内容如下: pcacmgr: publicCertFilePath: ...
- SpringMVC自定义视图Excel视图和PDF视图
SpringMVC自定义视图 Excel视图和PDF视图 SpringMVC杂记(十一) 使用Excel视图 Spring MVC 视图解析器(ViewResolver ) java实现导出excel ...
- SpringMvc问题记录-Controller对于静态变量的访问分析
问题描述 在于朋友的讨论中分析到一种场景,即:Controller对于一个类中的静态变量进行访问时,如果第一个接口修改该静态变量的数据,另外一个接口获取该静态变量的数据,那么返回的结果是什么? 操作步 ...
随机推荐
- BZOJ 1026: [SCOI2009]windy数
题目 人生中的第一道数位dp,很有趣,虽然我很快推出了结构,但是过程却迟迟没有写出来,最后看别人的题解才恍然大悟 d[i][j]表示数位为i,最高位为j的方案数 DpInit非常简单,复杂度应该是O( ...
- IIS报错 试图加载格式不正确 的程序集解决办法
一般都是由于系统位数不一致导致的 方法:64位启用32应用程序兼容(推荐) 思路就是把程序池设置为对应的应用程序(即到底要不要启用32位应用程序)
- input输入内容时放大问题
最近做的微信网站有一个关于input输入框页面放大的问题.比如登录页面刚打开时正常,但用户输入信息登录时,页面就会放大.解决这个问题,首先需要在头部加一个 <meta name="vi ...
- The Strategy pattern
public class Strategy {public static void main(String[] args) {int [] array=new int[]{26,25,15,42,36 ...
- Spring 学习笔记 7. 尚硅谷_佟刚_Spring_Bean 的作用域
1,理论 •在 Spring 中, 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域. •默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创 ...
- JDBC学习笔记(2)
上一篇博客简单介绍了JDBC连接的简单知识,下面就详细介绍.李勇老师对JDBC连接有很好的比喻: 首先加载驱动,其实就是一些类,就是jar包,要加载到classpath里面的.实际的程序,服务和数据库 ...
- MySQL入门手册
本文内容摘自MySQL5.6官方文档,主要选取了在实践过程中所用到的部分文字解释,力求只摘录重点,快速学会使用MySQL,本文所贴代码地方就是我亲自练习过的代码,凡本文没有练习过的代码都没有贴在此处, ...
- bdb mvcc: buffer 何时可以被 看到; mvcc trans何时被移除
# txn.h struct __db_txnregion SH_TAILQ_HEAD(__active) active_txn; SH_TAILQ_HEAD(__mvcc) mvcc_txn; # ...
- Django 中 如何使用 settings.py 中的常量
在用django 框架开发 python web 程序的时候 , 在模板页面经常会用到 settings.py 中设置的常量,比如MEDIA_URL, 我尝试过在模板页面用类似如下的方式 程序代码 { ...
- PYTHON学习之路_PYTHON基础(3)
学习内容: 1.Python字典 2.Python集合 3.Python字符编码 4.Python文件操作 5.Python实例 一.Python字典 1.定义: dic1={'name':'alex ...