欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

请求从Servlet到SpringMVC的处理过程

程序员文章站 2022-07-15 12:01:05
...

看这个之前请先看这个脑袋有个大局观:从Servlet到SpringMVC详解(ServletContext 和WebApplicationContext, ApplicationContext之间的关系)

最简单的看图说话:

请求从Servlet到SpringMVC的处理过程

请求从Servlet到SpringMVC的处理过程

 

所有人都知道DispatcherServlet是分发器的作用:但是为什么不叫Dispatcher,还要加上Servlet呢?当然排除命名的问题,还有另外一个问题,那就是这个DispatcherServlet是一个Servlet,他继承了HttpServlet。

 在我们使用SpringMVC框架之前我们是怎么使用原声的Servlet进行web开发的呢?

我们之前写的Servlet是这样的:

package com.iquantex.eurekaserver.localserver;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

然后会在我们的web项目中的web.xml文件中进行配置:


<servlet>  
    <servlet-name>myServlet</servlet-name>  
    <servlet-class>org.springframework.web.servlet.MyServlet</servlet-class>  
    <init-param>  
      <param-name>publishContext</param-name>  
      <param-value>false</param-value>  
    </init-param>  
    <load-on-startup>1</load-on-startup>  
</servlet>

<servlet-mapping>  
    <servlet-name>myServlet</servlet-name>  
    <url-pattern>/</url-pattern>  
</servlet-mapping>

url的匹配是在web.xml文件中配置的,如果你的请求匹配了某个<url-mapping>标签的话,系统会根据对应的<servlet-name>标签找到对应的servlet的全类名 org.springframework.web.servlet.MyServlet,然后处理你的请求。

每写一个servlet需要在web.xml里面配置一个servlet。

那我们能不能换一种思想来做这个事情,我们用一个map来存储我们的uri和对应的servlet,然后通过一个统一的Servlet来接受所有请求,然后我们在我们的业务逻辑里面来自己区分应该用哪个servlet来处理对应的请求,

如:

        Map<String, HttpServlet> uriMap = new HashMap<>();
        uriMap.put("/a", aServlet);
        uriMap.put("/b", bServlet);

如果我们的请求是http://localhost:8080/a, 然后我们的请求分发器  比如叫做DispatcherServlet 进行转发,然后在我们的uri里面进行匹配这样的话我们是不是可以定位到用aServlet进行处理,如果我们还需要对请求参数进行转化或者预处理什么的我们可以定义一套自己的handler,

在SpringMVC中DispatcherServlet进行请求转发的时候,会先实例化ApplicationContext,里面装载了无论是我们通过注解形式也好,也好还是配置文件xml形式配置的bean,还是javaconfig形式注入的bean也好,都会被装载进在ApplicationContext,

然后我们的DispatcherServlet进行请求转发,然后从ApplicationContext中获得HandlerMapping.class类型的 handlermapping实例和HandlerAdapter.class类型的handleradapter实例,此时的handlermapping的内容时类似于:

        Map<String, HttpServlet> uriMap = new HashMap<>();
        uriMap.put("/a", aServlet);
        uriMap.put("/b", bServlet);
  1.  就是通过handlermapping实例获得handler实例被封装成HandlerExecutionChain实例,这里面包含了一个类型是HandlerIntercepetor类型的拦截器list,和一个handler,这个handler是根据请求的url匹配兄handlermapping中获得的,
  2. 然后通过这个handler的类型(这个handler实现的接口)从handlerAdapter中筛选出类型符合的handleradapter,
  3. 然后会先执行拦截器list里面的所有的拦截器的所有PreHandle方法,
  4. 然后在通过handleradapter执行对应的handler的方法返回的就是ModelAndView实例,
  5. 然后在执行拦截器list里面的所有的PostHandle方法。

一个大概且粗旷的流程大概是这样子的,有什么问题可以留言

参考:

https://zhuanlan.zhihu.com/p/65658315

https://muyinchen.github.io/2017/08/05/Spring5%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90-Spring%E4%B8%AD%E7%9A%84%E5%A4%84%E7%90%86%E5%99%A8handlers/