SpringMVC原理分析
1.目标
- 理解原生servlet与servlet容器
- 理解SpringMVC的请求处理流程
2.原生servlet
2.1 回顾
首先我们回忆一下在使用诸如Structs2、SpringMVC框架之前我们是如何处理来着B端或是C端的请求的。下面我们用一张图来进行说明。
从Brower来的http请求会有Tomcat、Jetty这样的Servlet容器来接受。比如Tomcat默认监听8080端口,在传输层对请求进行处理是剥离掉TCP头解析出对应端就会把请求端口是8080的请求交给Tomcat进行处理。
ps:Tomcat这里就有Servlet的一些相关概念,比如Servlet是什么、Servlet的初始化、请求方式不同的不同处理、Servlet的销毁、Servlet是单例的吗等问题。这不属于本文的讨论重点,请看官自行复习。
言归正传,Tomcat这个Servlet容器只管接受请求,具体的处理是依赖我们实现的Servlet的。对于不同的请求我们要定义不同的Servlet进行处理。比如以下这个例子。我们Tomcat的webapp下可能会有多个应用(生产上一般一个Tomcat也就放一个),然后我们通过 http://ip:port/appname/path
的url去访问服务,例子中的port为80端口、appname配置的为/
,通过一个名为dispatchServlet的容器处理该app下的所有请求,后面动手实现SpringMVC的时候我们还会用到这个例子。
到目前为止我们已经回顾了原生的servlet请求的处理,只要上面的DispatchServlet实现了HttpServlet就可以处理从前端来的请求了。
2.2 原生Servlet的问题
原生的Servlet解决了规范与实现的问题,但是对于开发者来说工作量还是挺大的,每一个url我们都要去web.xml里面做映射,然后实现HttpServlet完成业务处理。这样的一个请求一次重复处理,用起来是不是很繁琐呢。其次每个url都需要Servlet容器创建对于的Servlet来完成请求处理,这么多Servlet的维护也是需要资源的。
那么有没有什么好办法来解决它呢?
3 SpringMVC的实现分析
因为小编没有玩过Structs2,这里就不分析它了我们直接上SpringMVC对 实现。
需求很简单:
1. `web.xml`中别来那么多mapping,写的恶心人。少来点,最好只有一个
2. 给Servlet容器减减压,让它也少创建点Servlet
3. `url`的映射简单点,得给我个写的地方,处理方法上写就最好了
SpringMVC给出了以下答卷
上面已经给出了SpringMVC对于一个请求处理涉及的重要接口,虽然现在前后端分离导致ViewResolver和View用的少了,但是其他的部分还是值得我们好好理解的。
以下是我从源码中摘录的一部分解释以及按理解画的一个请求处理核心流程图,上图理解的不清楚可以再看看。
1.DispatcherServlet
也称为前段处理器、处理器控制器
它是HTTP请求处理程序/控制器的中央调度程序,用来接受http请求然后分发到不同的handler进行处理,最后将请求响应返回
Central dispatcher for HTTP request handlers/controllers, e.g. for web UI controllers or HTTP-based remote service exporters. Dispatches to registered handlers for processing a web request, providing convenient mapping and exception handling facilities.
2.HandlerMapping
处理器映射器
它是一个接口,提供通过request找到对应handler的能力
Interface to be implemented by objects that define a mapping between requests and handler objects.
3.HandlerAdapter
处理器适配器
它也是一个接口,提供了处理器是否支持请求处理以及处理请求的方法。它是spring MVC框架的SPI。
ps: SPI 全称为 Service Provider Interface,是一种服务发现机制
MVC framework SPI, allowing parameterization of the core MVC workflow
4.handler
处理器
用来处理请求
注意:它没有统一的顶层接口,这也是为什么需要一个HandlerAdapter的原因
Handle sent objects and complete request processing.
5.ViewResolver
视图解析器
通过View的名称找到对应View对象
Interface to be implemented by objects that can resolve views by name.
6.View
视图
展示model数据产生最终视图响应结果, 呈现指定model的视图。
MVC View for a web interaction. Implementations are responsible for rendering content, and exposing the model. A single view exposes multiple model attributes.
最后给出一个我在做实现的时候用的抽象类算是对后面手写SpringMVC开个头。它实现了HttpServlet
的doGet方法,doPost的实现很类似就没有做实现不影响理解。后面的DispatchServlet实现这个抽象类就好了,重写doDispatch方法就行了。
/**
* Created by wxy on 2020/6/11 22:36.
* 接受所有请求调用dispatch方法
*/
public abstract class AbstractSevlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
doDispatch(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
// 模板方法,子类实现
public abstract void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
读到这里看官是否有自己的实现思路了呢?