文章目录
- 1,Spring MVC核心组件DispatcherServlet
- 1.1 DispatcherServlet的继承关系
- 1.2 DispatcherServlet的doDispatch方法
- 2,核心组件HandlerMapping(处理器映射器)
- 3,核心组件HandlerAdapter(处理器适配器)
- 4,HandlerInterceptor拦截器
- 5,核心组件Handler(处理器)
- 6,ModelAndView(模型和视图)
- 7,核心组件HandlerExceptionResolver(异常处理器解析器)
1,Spring MVC核心组件DispatcherServlet
所有源码都来自springboot3.0.2,spring-webmvc-6.0.4
1.1 DispatcherServlet的继承关系
HttpServlet是抽象类,用于处理基于HTTP协议的请求和响应。
package jakarta.servlet.http;
public abstract class HttpServlet extends GenericServlet
HttpServletBean是Spring Framework中提供的一个抽象基类,用于简化开发自定义的Servlet类在 Spring环境中的配置和使用。
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware
FrameworkServlet是Spring MVC框架中的一个重要组件,它是 DispatcherServlet的抽象基类之一。作为一个抽象类,FrameworkServlet提供了一些基本的功能,比如Servlet生命周期管理等
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware
DispatcherServlet是Spring MVC 框架中的核心组件,实现整个请求处理的流程,接下来会做详细分析
public class DispatcherServlet extends FrameworkServlet
1.2 DispatcherServlet的doDispatch方法
当HTTP请求打到服务器后,会先经过HttpServlet的service方法,然后执行到FrameworkServlet重写的service方法
// HttpServlet.class
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(lStrings.getString("http.non_http"));
}
// FrameworkServlet重写了这个方法
service(request, response);
}
FrameworkServlet的service方法,如果是"DELETE", “HEAD”, “GET”, “OPTIONS”, “POST”, “PUT”, "TRACE"方法的请求会交给父类也就是HttpServlet的另一个(参数是HttpServletRequest,HttpServletResponse重载的)service方法,该service方法会根据请求类型,将任务再分发给doGet(),doPost()等方法,而这写方法都被FrameworkServlet重写了
// FrameworkServlet.class
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (HTTP_SERVLET_METHODS.contains(request.getMethod())) {
super.service(request, response);
}
else {
processRequest(request, response);
}
}
FrameworkServlet重写的doGet,doPost等方法都是调用了processRequest方法
// FrameworkServlet.class
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
FrameworkServlet的核心方法processRequest,作用于处理客户端请求的整个流程,包括初始化上下文、调用doService方法处理请求、记录请求处理的结果和时间、无论结果如何发布请求处理完毕事件等。其中处理请求的核心方法doService由子类DispatcherServlet重写实现
// FrameworkServlet.class
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 省略...
try {
// DispatcherServlet重写了这个方法
doService(request, response);
}
// 省略...
}
DispatcherServlet的doService方法的核心环节doDispatch方法
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 省略...
try {
doDispatch(request, response);
}
// 省略...
}
DispatcherServlet的doDispatch方法
// DispatcherServlet.class
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 根据当前请求的特征来寻找并返回与之匹配的处理器执行链
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 确定当前请求的处理器适配器
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 实际调用处理程序
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new ServletException("Handler dispatch failed: " + err, err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new ServletException("Handler processing failed: " + err, err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
2,核心组件HandlerMapping(处理器映射器)
HandlerMapping是处理器映射器,其作用是根据请求的URL路径,通过注解或者XML配置,寻找匹配的处理器(Handler)信息。
HandlerExecutionChain mappedHandler = null;
// 省略...
mappedHandler = getHandler(processedRequest);
在doDispatcher方法中,通过执行getHandler方法,获取到HandlerExecutionChain处理器执行链,并且准备好了针对当前请求最佳的处理器(比如自定义Controller组件中请求映射符合当前请求URL路径的某个方法),以及拦截器集合
// DispatcherServlet.class
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
HandlerExecutionChain的主要属性
// 处理器执行链
public class HandlerExecutionChain {
// 处理器
private final Object handler;
// 拦截器集合
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
// 拦截器索引
private int interceptorIndex = -1;
// 省略...
}
3,核心组件HandlerAdapter(处理器适配器)
HandlerAdapter 是处理器适配器,其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
在doDispatcher方法中,通过执行getHandlerAdapter方法,遍历所有处理器适配器,返回支持当前处理器的HandlerAdapter处理器适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
HandlerAdapter接口的两个方法
public interface HandlerAdapter {
// 配置当前处理器适配器是否支持传入的处理器
boolean supports(Object handler);
// 执行处理
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
4,HandlerInterceptor拦截器
HandlerInterceptor的三个方法:
preHandle方法在处理程序执行之前被调用。它可以拦截请求,并在处理程序执行之前进行一些预处理操作。方法返回一个布尔值,如果是true,则继续执行处理程序;如果是false,则终止请求的处理。
postHandle 方法在处理程序执行之后、视图渲染之前被调用。它允许拦截并修改处理程序的结果模型和视图。您可以在此方法中添加一些公共的模型数据、修改视图或进行一些资源清理操作。
afterCompletion 方法是在整个请求处理完成后被调用,包括视图渲染完毕。此时拦截器可以进行一些资源清理工作,或者进行一些日志记录等。它接收一个 Exception 参数,用于捕获并处理请求处理过程中的异常。
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
DispatcherServlet的doServlet方法中拦截器的处理时机
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 省略...
try {
// 省略...
try {
// 省略...
// 执行HandlerInterceptor的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 执行处理程序
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 执行HandlerInterceptor的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
// 省略...
// 在processDispatchResult方法最后调用了mappedHandler.triggerAfterCompletion(request, response, null)执行HandlerInterceptor的afterCompletion方法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
// 省略
}
5,核心组件Handler(处理器)
Handler是处理器,和Java Servlet扮演的角色一致。HandlerAdapter接口的handle方法通过Handler执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至ModelAndView对象中。
ModelAndView mv = null;
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
举例当HandlerAdapter的实现类RequestMappingHandlerAdapter调用handle方法时,因为自身没有实现handle方法,所以会执行父类AbstractHandlerMethodAdapter的handle方法,这个handle的类型是HandlerMethod。
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
RequestMappingHandlerAdapter实现了handleInternal方法,走后面的处理逻辑最终处理并返回ModelAndView
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
6,ModelAndView(模型和视图)
handle处理程序返回的模型和视图,该模型和视图将由 DispatcherServlet 解析。视图可以是String 类型的视图名称,该名称需要由ViewResolver对象解析也可以直接指定View对象。该模型是一个 Map用于存储传输数据。
public class ModelAndView {
/** View instance or view name String. */
@Nullable
private Object view;
/** Model Map. */
@Nullable
private ModelMap model;
/** Optional HTTP status for the response. */
@Nullable
private HttpStatusCode status;
}
7,核心组件HandlerExceptionResolver(异常处理器解析器)
异常处理器解析器是用于处理全局异常的组件,它可以捕获和处理控制器抛出的异常,然后决定如何对异常进行处理,例如返回错误页面、返回 JSON 错误信息等。
HandlerExceptionResolver接口就一个resolveException方法,通过这个方法来进行异常处理。
public interface HandlerExceptionResolver {
@Nullable
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
}
在DispatcherServlet的doDispatch执行到processDispatchResult方法的时候,会在前面处理请求过程中捕获的可能出现的异常作为参数传递进去
// DispatcherServlet.class
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 省略...
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new ServletException("Handler dispatch failed: " + err, err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
// 省略...
}
如果传递的异常参数不为null,且不属于ModelAndViewDefiningException,则走processHandlerException方法的异常处理逻辑,并通过异常处理结果获得新的ModelAndView
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
// 异常处理
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No view rendering, null ModelAndView returned.");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
// Exception (if any) is already handled..
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
在processHandlerException方法中将遍历HandlerExceptionResolver并执行resolveException方法进行实际异常逻辑的处理,整个方法执行完则返回一个新的ModelAndView
@Nullable
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) throws Exception {
// Success and error responses may use different content types
request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
if (this.handlerExceptionResolvers != null) {
for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
// 核心环节,遍历并执行HandlerExceptionResolver的resolveException方法
exMv = resolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
}
if (exMv != null) {
if (exMv.isEmpty()) {
request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
return null;
}
// We might still need view name translation for a plain error model...
if (!exMv.hasView()) {
String defaultViewName = getDefaultViewName(request);
if (defaultViewName != null) {
exMv.setViewName(defaultViewName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using resolved error view: " + exMv, ex);
}
else if (logger.isDebugEnabled()) {
logger.debug("Using resolved error view: " + exMv);
}
WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
return exMv;
}
throw ex;
}