Spring MVC DispatcherServlet处理请求过程示例详解

 更新时间:2023年09月14日 10:46:47   作者:福  
这篇文章主要介绍了Spring MVC DispatcherServlet处理请求过程示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

前面讲过了DispatcherServlet的初始化过程(源码角度的DispatcherServlet的具体初始化过程还没说,先放一放),今天说一下DispatcherServlet处理请求的过程。

处理过程

  • WebApplicationContext绑定在当前request属性上(属性键值DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE)
  • localResolver绑定在request的属性上(属性键值LOCALE_RESOLVER_ATTRIBUTE)
  • themeResolver绑定在request属性上(属性键值HEME_RESOLVER_ATTRIBUTE)
  • servlet容器配置了multipart resolver,并且当前请求包含multpart file,则包装当前request为MultipartHttpServletRequest。
  • 匹配当前请求的handlerMappings,获取到HandlerExecutionChain,匹配getHandlerAdapter
  • 调用HandlerExecutionChain的applyPreHandle方法:获取拦截器,调用拦截器的preHandle方法
  • 调用HandlerAdapter的handle方法,这儿会匹配并执行Conroller方法
  • 执行HandlerExecutionChain的applyPostHandle方法:调用拦截器的postHandle方法
  • 执行processDispatchResult方法,其中会调用拦截器的afterCompletion方法

以上过程都被try catch包围起来了,所以才会有Spring MVC的异常处理机制:应用层不管哪里(controller、service、dao层...)抛出的异常,都会在这里被捕获到,注册到WebApplicationContext容器中的HandlerExceptionResolver beans就有机会统一处理异常。

可以通过DispatcherServlet的初始化参数来定制化其行为,参数可以通过web.xml指定,包括:

  • contextClass:指定当前DispatcherServlet绑定的容器类(ConfigurableWebApplicationContext的实现类),默认为XmlWebApplicationContext 。
  • contextConfigLocation:上述contextClass指定的容器类的配置文件的位置,可以指定多个配置文件,逗号分割。
  • namespace:WebApplicationContext的namespace,默认[servlet-name]-servlet。
  • throwExceptionIfNoHandlerFound:某一请求request没有匹配到handle的话,是否抛出NoHandlerFoundException异常,NoHandlerFoundException随后可以被HandlerExceptionResolver捕获并处理。默认情况下该参数设置为false,DispatherServlet不抛出异常、直接导航到404。注意:如果配置了默认Servlet Handler(default servlet handling)的话,那么没匹配到的request会导航到默认handler处理,永远不会出现404。

拦截

HandlerMapping支持拦截器,拦截器需实现SpringMVC的HandlerInterceptor接口(org.springframework.web.servlet),包含如下方法:

  • preHandle:HandlerMapping处理请求之前发生。
  • postHandle:HandlerMapping处理请求之后发生。
  • afterCompletion:整个请求处理完成之后。

preHandle返回true则请求继续被处理,返回false则后续不会再处理请求。

postHandle对@ResponseBody和ResponseEntity方法几乎没有什么作用,因为response已经在postHandle之前被HandlerAdapter处理完成了,因此不可能被postHandle修改了。比如你想通过postHandle在response header中增加一个头信息是不可能的了。这种需求只能通过ResponseBodyAdvice、 Controller Advice 或者直接在RequestMappingHandlerAdapter中直接实现。

异常处理

HandleMapping、HandlerAdapter、Controller中发生的任何异常,都可以被DispatcherServlet捕获、交给HandlerExceptionResolver bean去处理异常。

SpringMVC提供如下异常处理的实现类:

异常处理链我们可以配置多个HandlerExceptionResolver作为异常处理链(exception resolver chain)来处理异常,可以通过order属性指定其处理顺序,order值越大、在chain中排名越靠后。

HandlerExceptionResolver可以返回:

  • ModelAndView :错误页面。
  • 空ModelAndView:错误已经被处理,不需要导航到错误页面。
  • Null:当前Resolver不处理,异常继续向上抛给chain中后面的Resolver,直到最后如果没有Resolver处理该异常的话,异常会抛出给Servlet容器(比如给到Tomcat,这种情况下Tomcat也不处理,可能就会直接抛出给前台)。

SpringMVC会自动配置内建的异常处理器,我们可以通过配置客户化异常处理器。SpringMVC的异常处理相对比较重要,后面我们还会从源码和应用角度做一次分析。

容器错误页面

如果异常没有被任何HandlerExceptionResolver处理,而且,如果response status被设置为4xx、5xx的话,servlet容器(比如tomcat)会导航到默认的错误处理页面,假如容器配置了错误处理页面的话。可以通过web.xml配置:

<error-page>
    <location>/error</location>
</error-page>

以上配置需要DispatcherServlet进一步处理:

@RestController
public class ErrorController {
    @RequestMapping(path = "/error")
    public Map<String, Object> handle(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.put("status", request.getAttribute("jakarta.servlet.error.status_code"));
        map.put("reason", request.getAttribute("jakarta.servlet.error.message"));
        return map;
    }
}

以上就是Spring MVC 六 - DispatcherServlet处理请求过程的详细内容,更多关于Spring MVC 六 - DispatcherServlet处理请求过程的资料请关注脚本之家其它相关文章!

相关文章

  • 详解ArrayList的扩容机制

    详解ArrayList的扩容机制

    ArrayList基于动态数组实现,在添加和删除的时候存在扩容和缩容这样重新规划数组大小的机制。在ArrayList中,维护Object[] elementData数组来管理元素,但是ArrayList是动态可变的,所以elementData数组长度并不代表ArrayList实际元素个数,所以使用size显示实际元素个数
    2021-06-06
  • spring boot中使用@Async实现异步调用任务

    spring boot中使用@Async实现异步调用任务

    本篇文章主要介绍了spring boot中使用@Async实现异步调用任务,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • SpringBoot启动时自动执行代码的几种实现方式

    SpringBoot启动时自动执行代码的几种实现方式

    这篇文章主要给大家介绍了关于SpringBoot启动时自动执行代码的几种实现方式,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-02-02
  • 在navicat中导入mysql数据库详细步骤(即.sql后缀的数据库)

    在navicat中导入mysql数据库详细步骤(即.sql后缀的数据库)

    Navicat是MySQL非常好用的可视化管理工具,功能非常强大,能满足我们日常数据库开发的所有需求,下面这篇文章主要给大家介绍了关于如何在navicat中导入mysql数据库(即.sql后缀的数据库)的相关资料,需要的朋友可以参考下
    2023-04-04
  • Java利用happen-before规则如何实现共享变量的同步操作详解

    Java利用happen-before规则如何实现共享变量的同步操作详解

    这篇文章主要给大家介绍了关于Java利用happen-before规则实现共享变量的同步操作的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-06-06
  • Spring中的Aware接口及应用场景详解

    Spring中的Aware接口及应用场景详解

    这篇文章主要介绍了Spring中的Aware接口及应用场景,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • SpringBoot使用MockMvc测试get和post接口的示例代码

    SpringBoot使用MockMvc测试get和post接口的示例代码

    Spring Boot MockMvc是一个用于单元测试的模块,它是Spring框架的一部分,专注于简化Web应用程序的测试,MockMvc主要用来模拟一个完整的HTTP请求-响应生命周期,本文给大家介绍了SpringBoot使用MockMvc测试get和post接口,需要的朋友可以参考下
    2024-06-06
  • Java实现单例模式之饿汉式、懒汉式、枚举式

    Java实现单例模式之饿汉式、懒汉式、枚举式

    本篇文章主要介绍了Java实现单例的3种普遍的模式,饿汉式、懒汉式、枚举式。具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-10-10
  • Java实现RedisUtils操作五大集合(增删改查)

    Java实现RedisUtils操作五大集合(增删改查)

    本文主要介绍了Java实现RedisUtils操作五大集合,文中通过示例代码介绍的非常详细,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • JVM的7种垃圾回收器(小结)

    JVM的7种垃圾回收器(小结)

    这篇文章主要介绍了JVM的7种垃圾回收器(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10

最新评论