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一个返回值(随便什么都行)。









原文出处:后端技术杂谈
转载请与作者联系,同时请务必标明文章原始出处和原文链接及本声明。
目录
相关文章
|
存储 前端开发 Java
SpringMVC中重定向请求时传输参数原理分析与实践
SpringMVC中重定向请求时传输参数原理分析与实践
227 2
SpringMVC中重定向请求时传输参数原理分析与实践
47SpringMVC - 参数绑定(绑定包装pojo)
47SpringMVC - 参数绑定(绑定包装pojo)
41 0
|
应用服务中间件 数据库
46SpringMVC - 参数绑定(绑定pojo类型)
46SpringMVC - 参数绑定(绑定pojo类型)
84 0
45SpringMVC - 参数绑定(绑定简单类型)
45SpringMVC - 参数绑定(绑定简单类型)
65 0
|
2月前
|
前端开发 Java UED
SpringMVC全局异常处理+拦截器使用+参数校验
通过使用 SpringMVC 的全局异常处理、拦截器和参数校验,可以有效提升 Web 应用程序的安全性、稳定性和用户体验。这些技术的合理应用,不仅可以保证代码的健壮性,还能提高代码的可维护性,为开发高质量的 Web 应用程序提供了坚实的基础。
62 6
|
Java Spring
SpringMVC中请求传输的各种类型参数分析
SpringMVC中请求传输的各种类型参数分析
77 0
|
8月前
|
JSON 前端开发 JavaScript
JAVAEE框架技术之5-springMVC参数绑定和异步交互
JAVAEE框架技术之5-springMVC参数绑定和异步交互
89 0
JAVAEE框架技术之5-springMVC参数绑定和异步交互
|
JavaScript
springMVC接收数组参数
springMVC接收数组参数
43SpringMVC - 参数绑定(默认支持的参数类型)
43SpringMVC - 参数绑定(默认支持的参数类型)
59 0
|
前端开发 Java 索引
Spring MVC Controller 方法参数 Map 的实现类是什么?
问题 题主问题描述如下: 在SpringBoot中,Controller的参数中有Map接口类型的,请问他的实现类是什么? 突发奇想,在SpringBoot中,Controller的参数中有Map接口类型的
417 0
Spring MVC Controller 方法参数 Map 的实现类是什么?