• Java--SpringMVC概述,运行流程


    一、SpringMVC概述

    MVC 设计模式一般指 MVC 框架,M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。使用 MVC 的目的是将 M 和 V 的实现代码分离,使同一个程序可以有不同的表现形式。其中,View 的定义比较清晰,就是用户界面

    开发Servlet 及 JSP时,JavaBean 相当于 Model,Servlet 相当于 Controller,JSP 相当于 View。

    视图层(View):负责格式化数据并把它们呈现给用户,包括数据展示、用户交互、数据验证、界面设计等功能。

    控制层(Controller):负责接收并转发请求,对请求进行处理后,指定视图并将响应结果发送给客户端。

    数据模型层(Model):模型对象拥有最多的处理任务,是应用程序的主体部分,它负责数据逻辑(业务规则)的处理和实现数据操作(即在数据库中存取数据)

    SpringMVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 Servlet

    SpringMVC 也叫 Spring web mvc。是 Spring 框架的一部分,是在 Spring3.0 后发布的。

    由于 Spring MVC 本身就是 Spring 框架的一部分,可以说和 Spring 框架是无缝集成,能够使用Spring的IoC和Aop。方便整合MyBatis,Strtus,Hiberate,JPA 等其他框架

    Spring MVC主要由DispatcherServlet(中央调度器)、处理器映射、处理器(控制器)、视图解析器、视图组成

    SpringMVC工作流程

     1、Http请求:客户端请求提交到DispatcherServlet(中央调度器)

    2、寻找处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller

    3、调用处理器:DispatcherServlet将请求提交到Controller

    4、调用业务处理和返回结果:Controller调用业务逻辑处理后,返回ModelAndView

    5、处理视图映射并返回模型: DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图

    6、Http响应:视图负责将结果显示到客户端

    SpringMVC组件

    1、DispatcherServlet:中央调度器(前端控制器)。用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性,系统扩展性提高。由框架实现

    2、HandlerMapping:处理器映射器。HandlerMapping负责根据用户请求的url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,根据一定的规则去查找,例如:xml配置方式,实现接口方式,注解方式等。由框架实现

    3、Handler:处理器。Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。

    4、HandlAdapter:处理器适配器。通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。由框架实现。

    5、ModelAndView:springmvc的封装对象,将model和view封装在一起。

    6、ViewResolver:视图解析器。ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。

    7、View:springmvc的封装对象,是一个接口, springmvc框架提供了很多的View视图类型,包括:jspview,pdfview,jstlView、freemarkerView、pdfView等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。

    二、SpringMVC项目开发步骤

    1、新建一个maven的web项目,选择

    maven-archetype-webapp

    2、pom.xml文件加入依赖

    spring-webmvc依赖,间接把spring的依赖都加入到项目;jsp,servlet依赖

    1. <properties>
    2. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    3. <maven.compiler.source>1.8maven.compiler.source>
    4. <maven.compiler.target>1.8maven.compiler.target>
    5. properties>
    6. <dependencies>
    7. <dependency>
    8. <groupId>junitgroupId>
    9. <artifactId>junitartifactId>
    10. <version>4.11version>
    11. <scope>testscope>
    12. dependency>
    13. <dependency>
    14. <groupId>org.springframeworkgroupId>
    15. <artifactId>spring-webmvcartifactId>
    16. <version>5.2.5.RELEASEversion>
    17. dependency>
    18. <dependency>
    19. <groupId>javax.servletgroupId>
    20. <artifactId>javax.servlet-apiartifactId>
    21. <version>3.1.0version>
    22. <scope>providedscope>
    23. dependency>
    24. dependencies>
    25. <build>
    26. <resources>
    27. <resource>
    28. <directory>src/main/javadirectory>
    29. <includes>
    30. <include>**/*.propertiesinclude>
    31. <include>**/*.xmlinclude>
    32. includes>
    33. <filtering>falsefiltering>
    34. resource>
    35. resources>
    36. build>

    3、新建web.xml文件,并在该配置文件中注册SpringMVC框架的核心对象DispatcherServlet

    1. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    4. version="4.0">
    5. <servlet>
    6. <servlet-name>mywebservlet-name>
    7. <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    8. <init-param>
    9. <param-name>contextConfigLocationparam-name>
    10. <param-value>classpath:springmvc.xmlparam-value>
    11. init-param>
    12. <load-on-startup>1load-on-startup>
    13. servlet>
    14. <servlet-mapping>
    15. <servlet-name>mywebservlet-name>
    16. <url-pattern>*.dourl-pattern>
    17. servlet-mapping>
    18. web-app>

    (1)中央调度器DispatcherServlet

    中央调度器的全限定性类名在 导入的 Jar 文件 spring-webmvc-5.2.5.RELEASE.jar 的第一个包 org.springframework.web.servlet 下

    1. <servlet-name>mywebservlet-name>
    2. <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>

    (2)

    启动Tomcat报错,无法读取这个文件 /WEB-INF/myweb-servlet.xml    

    Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/myweb-servlet.xml]

    SpringMVC创建容器对象时,默认读取的配置文件路径是 /WEB-INF/-servlet.xml   

    指的是注册中央调度器标签 中指定的 Servlet 的 name 值
    一般情况下,配置文件是放在类路径下,即 resources 目录下‘’因此需要自定义SpringMVC读取配
    置文件的位置    

    :在servlet类中通过getInitParamenter(String name)方法访问初始化参数    

    param-name:参数名;

    param-value:参数值,支持多个参数    

    在这个方法中通过 getInitParamter("key"); key 就是 param-name的值,来获取对应的参数值

    1. <init-param>
    2. <param-name>contextConfigLocationparam-name>
    3. <param-value>classpath:springmvc.xmlparam-value>
    4. init-param>

    打开 DispatcherServlet 的源码,DispatcherServlet 继承自 FrameworkServlet,该类中有一个属性 contextConfigLocation,用于设置 SpringMVC 配置文件的路径及文件名。因此初始化参数的属性就来自于此 

    (3)

    的作用是,标记是否在Web服务器(这里是Tomcat)启动时会创建这个 Servlet 实例,即是否在 Web 服务器启动时调用执行该 Servlet 的 init()方法,而不是在真正访问时才创建

    load-on-startup:表示Tomcat启动后创建对象的顺序;

    它的值是整数,数值越小,Tomcat创建对象的时间越早,大于等于0的整数

    <load-on-startup>1load-on-startup>

    (4)

    url-pattern  拦截匹配规则的 url 请求,进入springmvc 框架处理, springmvc 就会去找能够处理这个url 的 handler去执行业务逻辑

    (1)使用扩展名方式,语法  *.xx , xx是自定义的扩展名

    常用的方式 *.do, *.action, *.mvc等等,不能使用 *.jsp        

    http://localhost:8080/myweb/some.do        

    http://localhost:8080/myweb/other.do    

    (2)使用斜杠 "/"

    <url-pattern>*.dourl-pattern>

    项目自带web.xml文件如下;使用的是最低版本2.3,因此需要更改版本

    (1)File ----> Project Structure...

    (2)删掉项目自带的web.xml文件

    (3)新增web.xml文件,并且选择版本

    注:这里需要重新命名web.xml文件,如web1111.xml,如果还是使用web.xml名称,新建之后还是最低版本,因此需要重新命名!!!

    (4)更改新增之后的web.xml文件名称,将其改为“web.xml”

    4、创建一个发起请求的页面 index.jsp

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Titletitle>
    5. head>
    6. <body>
    7. <p>第一个SpringMVC项目p>
    8. <p> <a href="some.do">发起some.do的请求a> p>
    9. <p> <a href="first.do">发起first.do的请求a> p>
    10. <p> <a href="other.do">发起other.do的请求a> p>
    11. <p> <a href="second.do">发起second.do的请求a> p>
    12. body>
    13. html>

    5、创建控制器(处理器)类

    (1)在类上面加入@Controller注解,创建对象,并放入到SpringMVC容器中

    @Controller:表示当前类为处理器

    (2)在类的方法上加入@RequestMapping注解

    @RequestMapping :表示当前方法为处理器方法。该方法要对 value 属性所指定的 URI
    进行处理与响应
    ModelAndView 类中的 addObject()方法用于向其 Model 中添加数据。 Model 的底层为一个HashMap
    Model 中的数据存储在 request 作用域中,SringMVC 默认采用转发的方式跳转到视图,本次请求结束,模型中的数据被销毁
    1. import org.springframework.stereotype.Controller;
    2. import org.springframework.web.bind.annotation.RequestMapping;
    3. import org.springframework.web.servlet.ModelAndView;
    4. /**
    5. * @Controller :创建处理器对象,对象放在SpringMVC容器中
    6. * 位置:在类的上面
    7. *
    8. * 能处理请求的都是控制器(处理器),也叫做后端控制器(back Controller)
    9. */
    10. @Controller
    11. public class MyController {
    12. /**
    13. * SpringMVC中使用方法来处理用户提交的请求;方法可以自定义,也可以有多种返回值,多种参数,方法名称自定义
    14. *
    15. * @RequestMapping : 请求映射;作用是把一个请求地址和一个方法绑定在一起
    16. * 一个请求指定一个方法处理
    17. *
    18. * 属性:value;是一个String,表示请求的URI地址(some.do)
    19. * value的值必须是唯一的,不能重复;使用时,推荐地址以 "/"开始
    20. *
    21. * 位置:1、在方法上面,常用;2、在类上面
    22. *
    23. * 注:使用@RequestMapping修饰的方法叫做处理器方法或者控制器方法
    24. * 使用@RequestMapping修饰的方法可以处理请求,类似Servlet中的doGet,doPost
    25. *
    26. * 返回值:ModelAndView,表示本次请求的处理结果
    27. * Model:数据,请求处理完成后,要显示给用户的数据、
    28. * View:视图,如jsp等
    29. */
    30. @RequestMapping(value = {"/some.do","first.do"})
    31. public ModelAndView doSome(){ // doGet()----service请求处理
    32. //处理 some.do请求,相当于service调用处理完成
    33. ModelAndView mdv = new ModelAndView();
    34. /**
    35. * 添加数据,框架在请求的最后把数据放入到request作用域
    36. * request.setAttribute("msg","欢迎使用springmvc做web开发");
    37. */
    38. mdv.addObject("msg","欢迎使用SpringMVC做web开发");
    39. mdv.addObject("fun","执行的是doSome方法");
    40. /**
    41. * 指定视图,指定视图的完整路径
    42. * 框架对视图进行forward转发操作,request.getRequestDispather("/show.jsp).forward(...)
    43. */
    44. /**
    45. * jsp页面放在 /webapp 目录下,
    46. * 用户可以通过输入对应地址 http://localhost:8081/springmvc-1-war/show.jsp 直接访问
    47. */
    48. //mdv.setViewName("/show.jsp");
    49. /**
    50. * jsp页面放在 /webapp/WEB-INF/view 目录下,
    51. * 输入对应地址 http://localhost:8081/springmvc-1-war/WEB-INF/view/show11.jsp 无法访问,访问报错,更加安全
    52. * WEB-INF目录下的jsp页面就必须要通过请求才能访问,是要求隐藏性的,只让客户通过请求访问而不是直接访问jsp页面
    53. */
    54. //mdv.setViewName("/WEB-INF/view/show11.jsp");
    55. /**
    56. * 配置视图解析器。可以使用逻辑名称(文件名),指定视图
    57. * SpringMVC会使用视图解析器的前缀 + 逻辑名称 + 后缀 拼接成完整路径(字符串连接操作)
    58. * "/WEB-INF/view/" + "show11" + ".jsp"
    59. */
    60. mdv.setViewName("show11");
    61. return mdv;
    62. }
    63. @RequestMapping(value = {"/other.do","/second.do"})
    64. public ModelAndView doOther(){
    65. ModelAndView mv = new ModelAndView();
    66. mv.addObject("msg","====欢迎使用SpringMVC做web开发====");
    67. mv.addObject("fun","执行的是doOther方法");
    68. mv.setViewName("other");
    69. return mv;
    70. }
    71. }

    6、创建一个结果的 show.jsp,显示处理结果

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Titletitle>
    5. head>
    6. <body>
    7. <h3>/webapp/show.jsp从request作用域获取数据h3>
    8. <h3>msg数据:${msg}h3><br/>
    9. <h3>fun数据:${fun}h3>
    10. body>
    11. html>

    这里需要注意 show.jsp目录位置

    1. /**
    2. * 指定视图,指定视图的完整路径
    3. * 框架对视图进行forward转发操作,request.getRequestDispather("/show.jsp).forward(...)
    4. */
    5. /**
    6. * jsp页面放在 /webapp 目录下,
    7. * 用户可以通过输入对应地址 http://localhost:8081/springmvc-1-war/show.jsp 直接访问
    8. */
    9. mdv.setViewName("/show.jsp");
    10. /**
    11. * jsp页面放在 /webapp/WEB-INF/view 目录下,
    12. * 输入对应地址 http://localhost:8081/springmvc-1-war/WEB-INF/view/show11.jsp 无法访问,访问报错,更加安全
    13. * WEB-INF目录下的jsp页面就必须要通过请求才能访问,是要求隐藏性的,只让客户通过请求访问而不是直接访问jsp页面
    14. */
    15. mdv.setViewName("/WEB-INF/view/show11.jsp");

    (1)jsp页面放在 /webapp 目录下

    用户可以通过输入对应地http://localhost:8081/springmvc-1-war/show.jsp 直接访问

    (2)jsp页面放在 /webapp/WEB-INF/view 目录下

     输入对应地址 http://localhost:8081/springmvc-1-war/WEB-INF/view/show11.jsp 无法访问,访问报错,更加安全

    WEB-INF目录下的jsp页面就必须要通过请求才能访问,是要求隐藏性的,只让客户通过请求访问而不是直接访问jsp页面

    7、创建SpringMVC的配置文件(和spring的配置文件一样)

    工程的类路径即 src 目录下创建 SpringMVC 的配置文件 springmvc.xml

    (1)声明组件扫描器,指定@Controller注解所在的包名

    (2)声明视图解析器,处理视图

    1. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    2. <property name="prefix" value="/WEB-INF/view/" />
    3. <property name="suffix" value=".jsp" />
    4. bean>
    1. /**
    2. * 配置视图解析器。可以使用逻辑名称(文件名),指定视图
    3. * SpringMVC会使用视图解析器的前缀 + 逻辑名称 + 后缀 拼接成完整路径(字符串连接操作)
    4. * "/WEB-INF/view/" + "show11" + ".jsp"
    5. */
    6. mdv.setViewName("show11");
    1. <beans xmlns="http://www.springframework.org/schema/beans"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xmlns:context="http://www.springframework.org/schema/context"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. http://www.springframework.org/schema/beans/spring-beans.xsd
    6. http://www.springframework.org/schema/context
    7. https://www.springframework.org/schema/context/spring-context.xsd">
    8. <context:component-scan base-package="com.mycompany.controller" />
    9. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    10. <property name="prefix" value="/WEB-INF/view/" />
    11. <property name="suffix" value=".jsp" />
    12. bean>
    13. beans>

    8、启动Tomcat,或者未修改Java代码,只修改 jsp 代码,重启资源即可配置如下

    IDEA下更改jsp界面后(或者静态资源界面),一般要手动update或者reploy,这里可以设置tomcat来解决

     选择Edit Configurations...

    默认是Tomcat的【Server】选项, On Frame Deactivation选项这里如果 只有 Do nothing,看如下配置

    On Upate Action 与 On Frame Deactivation  这两个选项的设置,依赖于 项目的部署方式 是war包 还是 exploded 

     选择【Deployment】,添加一个启动项目,这里必须选择 exploded 为后缀的war包!!!

    在选择【Server】查看,On Frame Deactivation  选项的设置就会出现【Update resources】选项,选择即可

    这时重启Tomcat,就会多了选项【Update resources】和【Update classes and resources】

    (1)如果重启Tomcat,选择【Restart server】

    (2)如果只修改 jsp 或者 html 页面,选择【Update resources】

    整个项目结构如下

    启动Tomcat之后,在浏览器中输入访问地址即可

    http://localhost:8081/springmvc-1-war/

    三、DispatcherServlet创建容器,请求过程源码解析

    DispatherServlet 负责接收用户的所有请求,用户把请求给了DispatherServlet, 之后DispatherServlet把请求转发给我们的Controller对象,Controller对象处理请求

    index.jsp-----> DispatherServlet(Servlet) ---- > 转发,分配给 ---> Controller对象(@Controller注解创建的对象)

    SpringMVC请求的处理流程

    (1)index.jsp 发起 some.do 请求

    (2)tomcat(web.xml--url-pattern知道 *.do的请求给DispatcherServlet)

    (3)DispatcherServlet(根据springmvc.xml配置知道 some.do---doSome())

    (4)DispatcherServlet把some.do转发个MyController.doSome()方法

    (5)框架执行doSome() 把得到ModelAndView进行处理, 转发到show.jsp

    简化的方式:some.do----> DispatcherServlet ----> MyController

    1、DispatcherServlet创建容器

    DispatcherServlet在创建过程中,会同时创建SpringMVC容器对象,读取SpringMVC配置文件,把这个配置文件中的对象都创建好, 用户发起请求时就可以直接适用对象

    DispatcherServlet初始化会执行 init() 方法;

    DispatcherServlet在 init() 方法中

    (1)创建容器,读取配置文件

    WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");

    (2)将容器对象放入到ServletContext中

    getServletContext().setAttribute(key, ctx);

    1. public class DispatcherServlet extends FrameworkServlet
    2. public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware
    3. public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
    4. public final void init() throws ServletException {
    5. this.initServletBean();
    6. }
    7. }
    8. public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    9. protected final void initServletBean() throws ServletException {
    10. try {
    11. this.webApplicationContext = this.initWebApplicationContext();
    12. this.initFrameworkServlet();
    13. }
    14. }
    15. protected WebApplicationContext initWebApplicationContext() {
    16. WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
    17. WebApplicationContext wac = null;
    18. if (this.webApplicationContext != null) {
    19. wac = this.webApplicationContext;
    20. if (wac instanceof ConfigurableWebApplicationContext) {
    21. ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
    22. if (!cwac.isActive()) {
    23. if (cwac.getParent() == null) {
    24. cwac.setParent(rootContext);
    25. }
    26. this.configureAndRefreshWebApplicationContext(cwac);
    27. }
    28. }
    29. }
    30. if (wac == null) {
    31. wac = this.findWebApplicationContext();
    32. }
    33. if (wac == null) {
    34. wac = this.createWebApplicationContext(rootContext);
    35. }
    36. if (!this.refreshEventReceived) {
    37. synchronized(this.onRefreshMonitor) {
    38. this.onRefresh(wac);
    39. }
    40. }
    41. if (this.publishContext) {
    42. String attrName = this.getServletContextAttributeName();
    43. this.getServletContext().setAttribute(attrName, wac);
    44. }
    45. return wac;
    46. }
    47. }

    2、DispatcherServlet请求过程

    1. public class DispatcherServlet extends FrameworkServlet
    2. public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware
    3. public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware
    4. public abstract class HttpServlet extends GenericServlet {
    5. }
    6. public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    7. protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    8. HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    9. if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
    10. super.service(request, response);
    11. } else {
    12. this.processRequest(request, response);
    13. }
    14. }
    15. protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    16. this.doService(request, response);
    17. }
    18. }
    19. public class DispatcherServlet extends FrameworkServlet {
    20. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    21. this.doDispatch(request, response);
    22. }
    23. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    24. HttpServletRequest processedRequest = request;
    25. HandlerExecutionChain mappedHandler = null;
    26. boolean multipartRequestParsed = false;
    27. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    28. try {
    29. try {
    30. ModelAndView mv = null;
    31. Object dispatchException = null;
    32. try {
    33. processedRequest = this.checkMultipart(request);
    34. multipartRequestParsed = processedRequest != request;
    35. mappedHandler = this.getHandler(processedRequest);
    36. if (mappedHandler == null) {
    37. this.noHandlerFound(processedRequest, response);
    38. return;
    39. }
    40. HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
    41. String method = request.getMethod();
    42. boolean isGet = "GET".equals(method);
    43. if (isGet || "HEAD".equals(method)) {
    44. long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
    45. if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
    46. return;
    47. }
    48. }
    49. if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    50. return;
    51. }
    52. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    53. if (asyncManager.isConcurrentHandlingStarted()) {
    54. return;
    55. }
    56. this.applyDefaultViewName(processedRequest, mv);
    57. mappedHandler.applyPostHandle(processedRequest, response, mv);
    58. } catch (Exception var20) {
    59. dispatchException = var20;
    60. } catch (Throwable var21) {
    61. dispatchException = new NestedServletException("Handler dispatch failed", var21);
    62. }
    63. this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
    64. } catch (Exception var22) {
    65. this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
    66. } catch (Throwable var23) {
    67. this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
    68. }
    69. } finally {
    70. if (asyncManager.isConcurrentHandlingStarted()) {
    71. if (mappedHandler != null) {
    72. mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
    73. }
    74. } else if (multipartRequestParsed) {
    75. this.cleanupMultipart(processedRequest);
    76. }
    77. }
    78. }
    79. }

  • 相关阅读:
    BottomNavigation 底部导航模版
    C++基础系列(一) 对象指针
    PCL点云处理之特征计算、特征点对匹配、配准矩阵计算,结果保存的全流程 (二百二十)
    装备制造业为何需要重视工业软件?
    设计模式在参数校验中的使用
    UVM同步通信 - sv event, uvm_event, uvm_barrier详解
    Apache Solr 身份认证绕过导致任意文件读取漏洞复现(CVE-2024-45216)
    大端与小端:显示、存储和读取
    autoware.ai感知随笔--地面滤波
    java 基础(核心知识搭配代码)
  • 原文地址:https://blog.csdn.net/MinggeQingchun/article/details/123537386