spring mvc中的控制器方法中的参数从哪里传进来?
编写控制器方法的时候很奇怪,spring是怎么知道你控制器方法的参数类型,并且注入正确的对象呢?
比如下面这样
@RequestMapping(value="/register", method=GET)
public String showRegistrationForm(Model model) {
model.addAttribute(new Spitter());
return "registerForm";
}
他怎么知道Model对应啥呢?
其实,spring首先会反射这个方法,然后获得参数的类型,另外在spring中,保存着一系列的argumentResolvers参数理器对象,这些参数处理器都是不同的HandlerMethodArgumentResolver类的不同子类的实例。然后用循环,一个个测试这些参数处理器是否支持这个参数的类型,如果支持,就返回这个参数处理器,并用这个参数处理器的resolveArgument方法,该方法会返回一个合适的参数对象,这个参数对象是我们写的控制方法参数的子类。比如上面showRegistrationForm(Model model)的参数对象是Model,那么支持Model参数的参数处理器就是ModelAndViewContainer类的对象,然后然后这个参数处理器对象的resolveArgument方法会返回一个BindingAwareModelMap对象,这个BindingAwareModelMap对象正好是Model的子类,传入showRegistrationForm(Model model)中,我们就可以通过model操作这个对象了。
这个循环检测是在HandlerMethodArguementResolverComposite类的getArgumentResolver方法中进行的:
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;
}
另外还可以看到,这个方法中用了缓存,这样当以后再次进入这个控制器方法是,就直接从缓存中取得argumentResolver就可以了。
如果是控制器方法的参数是一个普通的pojo(不是ioc容器中管理的spring bean),比如对应一个表单的数据,比如下面这样,应该怎么处理呢?
@RequestMapping(value="/register", method=POST)
public String processRegistration(
@Valid Spitter spitter,
Errors errors) {
if (errors.hasErrors()) {
return "registerForm";
} spitterRepository.save(spitter);
return "redirect:/spitter/" + spitter.getUsername();
}
processRegistration的第一个参数是Spitter,他只是一个普通的自定义的pojo,那么这个参数将被看作是一个模型属性,并且用ModleAttributeMethodProcessor这个参数处理器来处理。ModleAttributeMethodProcessor的resolveArgument 方法如下:
public final Object resolveArgument(
MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest request, WebDataBinderFactory binderFactory)
throws Exception { String name = ModelFactory.getNameForParameter(parameter);
Object attribute = (mavContainer.containsAttribute(name)) ?
mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request); WebDataBinder binder = binderFactory.createBinder(request, attribute, name);
if (binder.getTarget() != null) {
bindRequestParameters(binder, request);
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors()) {
if (isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
}
看山上面第8行,如果模型中没有这个属性对象,那么就会createAttribute创建这个属性,再看creat4eAttribute这个方法是怎么创建pojo对象的:
protected Object createAttribute(String attributeName, MethodParameter parameter,
WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { return BeanUtils.instantiateClass(parameter.getParameterType());
}
果然没错,就是用java的反射,根据对象的类型instance一个实例,最后返回,完毕。
spring mvc中的控制器方法中的参数从哪里传进来?的更多相关文章
- 在Spring MVC Controller的同一个方法中,根据App还是WEB返回JSON或者HTML视图。
如有高见,欢迎交流! 最近在做一个web的项目,web版已经开发完毕,现在正在进行手机APP的开发,开发中遇到一个问题: 就是web版和app版都有登录功能,本想着是分别走不同的URL,实际开发的时候 ...
- spring mvc: 多动作控制器(Controller下面实现多个访问的方法)MultiActionController / BeanNameUrlHandlerMapping
spring mvc: 多动作控制器(Controller下面实现多个访问的方法) 比如我的控制器是UserController.java,下面有home, add, remove等多个方法 访问地址 ...
- Spring MVC的核心控制器DispatcherServlet的作用
关于Spring MVC的核心控制器DispatcherServlet的作用,以下说法错误的是( )? 它负责接收HTTP请求 加载配置文件 实现业务操作 初始化上下应用对象ApplicationC ...
- 为何Spring MVC可获取到方法参数名,而MyBatis却不行?【享学Spring MVC】
每篇一句 胡适:多谈些问题,少聊些主义 前言 Spring MVC和MyBatis作为当下最为流行的两个框架,大家平时开发中都在用.如果你往深了一步去思考,你应该会有这样的疑问: 在使用Spring ...
- Spring MVC 分离了控制器、模型对象、过滤器以及处理程序对象的角色
通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages(JSP)技术.Velocity.Tiles.iText和POI.Spring MVC 框架 ...
- 为什么局部内部类中访问同一方法中的变量,该变量一定要是final修饰的
最近有一个疑惑:为什么局部内部类中访问同一方法中的变量,该变量一定要是final修饰的 首先,我们看一个局部内部类的例子: class OutClass { ...
- Spring MVC page render时jsp中元素相对路径的解决办法
前段时间做了用Spring Security实现的登录和访问权限控制的功能,但是page render使用的是InternalResourceResolver,即在spring的servlet配置文件 ...
- spring MVC 管理HttpClient---实现在java中直接向Controller发送请求
在spring MVC中,大多数时候是由客户端的页面通过ajax等方式向controller发送请求,但有时候需要在java代码中直接向controller发送请求,这时可以使用HttpCilent实 ...
- 【spring mvc】springmvc在tomcat中的执行过程
一.WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象(每个web应用程序唯一),它代表当前web应用web容器提供其一个全局的上下文环境,其为后面的spri ...
随机推荐
- java中介者模式
中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改.如果使用中介者模式,只需关心和Mediator类的关系 ...
- EF 查询视图返回重复数据的问题
在特殊的情况下查询过滤视图 会出现重复的数据结果集(返回的多条数据结果一致). 原因是啥:主键 在数据库设计的理念中:每个表都应该的唯一的主键.但视图不同,EF中会自动按视图的最前几个非空型字段设置为 ...
- putty连接fedora
putty提示“Connection refused” 但可以ping通 经查,解决方法如下: 首先判断是否安装ssh rpm -qa openssh rpm -qa openssh-server 之 ...
- .netcore 与 Docker
CentOS下Docker与.netcore(一) 之 安装 CentOS下Docker与.netcore(二) 之 Dockerfile CentOS下Docker与.netcore(三)之 三剑客 ...
- asp.net core + 前端H5 页面视频站制作尝试
.net core 2.1出来一段时间了,一直关注,前周花了半天时间学习了一下,特制作了一个视频小站(欢迎扫码体验): 页面首页效果如下: 播放页面效果如下: 部分代码: using ENT.IBLL ...
- Flex + Bison: Scanning from memory buffer
Found from StackOverflow: ========================================================================== ...
- sublime 插件安装之sublime highlight 如何优雅拷贝代码到word
首先:打开preference => Package Control,输入 Add Repository ,用它来为Sublime 添加插件安装源, https://github.com/n ...
- Ubuntu16.04 JAVA配置!
下面是转发的文章,写得不错,不过有些地方需要注意: 1,以root身份登入,安装和配置JDK,这样JDK是全局的,其他用户也可以使用! 2,下面文章中的JDK版本应该比我们目前能够下载的要旧,我们把下 ...
- bootstrap-table教程演示
Bootstrap Admin 效果展示 Table of contents Create Remove Update Export Tree Create 相关插件 bootstrap-valida ...
- CentOS6.9 ARM虚拟机扩容系统磁盘
由于扩容磁盘的操作非同小可,一旦哪一步出现问题,就会导致分区损坏,数据丢失等一系列严重的问题,因此建议:在进行虚拟机分区扩容之前,一定要备份重要数据文件,并且先在测试机上验证以下步骤,再应用于您的生产 ...