SpringMVC的controller传递HttpServletResponse参数的那点事

简介:
 @RequestMapping(value = "cardDown", method = RequestMethod.GET, headers = "Accept=text/html")
    public void cardDown(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, String id, int status){
    ......
    }

之前在使用Spring mvc的时候发现这么一回事:在spring mvc的controller的参数里如果有HttpServletResponse(类似上面的代码),那么必须有返回值框架才会去在执行完handler后去搜索相应的viewResolver和view从而展现数据。如果没有返回值,那么默认就是返回null的。我初步推测框架的处理过程大致如此:如果controller参数里传递HttpServletResposne的话,框架就认为视图由handler自己生成可以不参于这个过程,但是如果handler有返回值的话,那么仍然认为还需要参与到视图生成的过程中。

翻了一下spring mvc的代码,验证了自己的想法。在DispatchServlet的921行

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

这里的mv就是视图生成的结果。接着经历下面的过程:

  1. AbstractHandlerMethodAdapter.handle
  2. RequestMappingHandlerAdapter.handleInternal
  3. RequestMappingHandlerAdapter.invokeHandleMethod

    这地方有一个关键的变量mavContainer

     ModelAndViewContainer mavContainer = new ModelAndViewContainer();
     
    mavContainer有一个属性requestHandled,其标志着此次请求是否是由handler自己控制的。默认为false。

  4. ServletInvocableHandlerMethod.invokeAndHandle

  5. InvocableHandlerMethod.invokeForRequest
  6. InvocableHandlerMethod.getMethodArgumentValues

    这个方法的功能在名字上大体就能看出来:获取controller中每一个参数的值。关键的地方在于

     args[i] = argumentResolvers.resolveArgument(parameter, mavContainer, request, dataBinderFactory);
     
    这一行代码关联的是对每一中paramerter的处理类。接下来的调用见7

  7. HandlerMethodArgumentResolverComposite.resolveArgument

     HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
     Assert.notNull(resolver, “Unknown parameter type [” + parameter.getParameterType().getName() + “]”);
     return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
     

    这里的代码就三行,第一步是根据参数不同,获取不同的argumentResolver。当参数为HttpServletResponse的时候,就会调用ServletResponseMethodArgumentResolver.resolveArgument

  8. ServletResponseMethodArgumentResolver.resolveArgument

    最核心的一段代码来了

     if (mavContainer != null) {
         mavContainer.setRequestHandled(true);
     }
     

    这里就把mavContainer的requestHandled设置为了true.

  9. 回到4,调用完InvocableHandlerMethod.invokeForRequest

     if (returnValue == null) {
         if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
             mavContainer.setRequestHandled(true);
             return;
         }
     }else if (StringUtils.hasText(this.responseReason)) {
         mavContainer.setRequestHandled(true);
         return;
     }
    

    mavContainer.setRequestHandled(false);

    当handler的返回值为null的时候,直接返回。否则将mavContainer的requestHandled设置为false。

  10. 接着回到3,调用完ServletInvocableHandlerMethod.invokeAndHandle后,接着调用getModelAndView(mavContainer, modelFactory, webRequest)

  11. ServletInvocableHandlerMethod.getModelAndView

    modelFactory.updateModel(webRequest, mavContainer);
    

    if (mavContainer.isRequestHandled()) { return null; }

    这里当mavContainer的requestHandled被设置为true时,视图返回null。

整个大体的流程就是这样的,如果需要使用HttpServletResponse同时还需要框架控制视图生成的话,可以给controller method一个返回值(随便什么都行)。









原文出处:后端技术杂谈
转载请与作者联系,同时请务必标明文章原始出处和原文链接及本声明。
目录
相关文章
|
4月前
|
存储 前端开发 Java
SpringMVC中重定向请求时传输参数原理分析与实践
SpringMVC中重定向请求时传输参数原理分析与实践
95 2
SpringMVC中重定向请求时传输参数原理分析与实践
|
6月前
47SpringMVC - 参数绑定(绑定包装pojo)
47SpringMVC - 参数绑定(绑定包装pojo)
19 0
|
6月前
|
应用服务中间件 数据库
46SpringMVC - 参数绑定(绑定pojo类型)
46SpringMVC - 参数绑定(绑定pojo类型)
33 0
|
6月前
45SpringMVC - 参数绑定(绑定简单类型)
45SpringMVC - 参数绑定(绑定简单类型)
44 0
|
5月前
|
Java Spring
SpringMVC中请求传输的各种类型参数分析
SpringMVC中请求传输的各种类型参数分析
27 0
|
3月前
|
JSON 前端开发 JavaScript
JAVAEE框架技术之5-springMVC参数绑定和异步交互
JAVAEE框架技术之5-springMVC参数绑定和异步交互
57 0
JAVAEE框架技术之5-springMVC参数绑定和异步交互
|
JSON 前端开发 数据格式
SpringMVC学习笔记(获取参数,传递参数——关于前后端传参交互的总结、from表单、Ajax数据提交))(下)
SpringMVC学习笔记(获取参数,传递参数——关于前后端传参交互的总结、from表单、Ajax数据提交))(下)
|
前端开发 Java API
SpringMVC学习笔记(获取参数,传递参数——关于前后端传参交互的总结、from表单、Ajax数据提交))(上)
SpringMVC学习笔记(获取参数,传递参数——关于前后端传参交互的总结、from表单、Ajax数据提交))(上)
137 0
|
前端开发 Java 索引
Spring MVC Controller 方法参数 Map 的实现类是什么?
问题 题主问题描述如下: 在SpringBoot中,Controller的参数中有Map接口类型的,请问他的实现类是什么? 突发奇想,在SpringBoot中,Controller的参数中有Map接口类型的
349 0
Spring MVC Controller 方法参数 Map 的实现类是什么?
|
数据采集 前端开发 Java
SpringMVC【参数绑定、数据回显、文件上传】
我们在Controller使用方法参数接收值,就是把web端的值给接收到Controller中处理,这个过程就叫做参数绑定…
127 0
SpringMVC【参数绑定、数据回显、文件上传】