java web 执行流程
组件说明
- Filter 主要用于对请求进行拦截和处理,可以用于对所有请求进行统一的预处理、过滤和修改操作。
- Interceptor 主要用于对 Controller 执行前、执行后以及渲染前的拦截和处理操作,在 Controller 与视图之间添加拦截器链,可以灵活地增加或删除拦截器。
- @ControllerAdvice 主要用于定义全局异常处理器和全局数据绑定器,它只能捕捉到 Controller 层抛出的异常,无法捕捉到更底层的异常。
- AOP 主要用于在运行时动态地将代码片段插入到现有代码的特定位置,并根据切面定义的规则来执行相应的行为,可用于处理各种通用问题,例如日志记录、事务控制、权限验证等。
- Controller 是处理 HTTP 请求并返回响应结果的核心组件之一,它通过注解的方式来标识控制器组件。在实际开发中,控制器逻辑通常会比较复杂,需要对请求参数进行校验、调用 Service 层进行逻辑处理、将结果封装成视图并返回给客户端等多个步骤。
执行顺序 Filter -> Interceptor -> @ControllerAdvice -> AOP -> Controller
- Filter:HTTP 请求进入 Servlet Container 后,首先由 Filter 进行拦截和处理。因此,Filter 的执行顺序最高。
- Interceptor:在经过 Filter 的处理后,请求会交给 DispatcherServlet 进行处理。DispatcherServlet 会根据请求路径映射到对应的 Controller 中去。在 Controller 执行前、执行后以及渲染前,可能会有多个 Interceptor 对其进行拦截和处理。Interceptor 是链式调用的,而且可以配置多个拦截器,因此,Interceptor 的执行顺序由配置的顺序决定。
- @ControllerAdvice:在 Controller 执行过程中,如果抛出了异常,会被捕获并由全局异常处理器进行处理。除此之外,全局数据绑定器和全局数据预处理器也会在执行过程中被调用。
- AOP:在 Controller 执行过程中,可能会使用 AOP 对其进行增强,例如添加事务控制、日志记录等功能。AOP 可以在请求执行前、执行后以及出现异常时进行拦截和处理。
- Controller:Controller 是最后一个处理请求的组件。在执行过程中,会根据请求参数、请求头、路径变量等信息来获取请求资源,并将处理结果封装成视图返回给客户端。
以上其实有一点不对的就是AOP 我们根据源码 检验一下
请求通过 tomcat filter 将请去转发到springmvc
- /org/apache/catalina/core/ApplicationFilterChain.java:189
- filter.doFilter(request, response, this);
- /org/springframework/web/filter/OncePerRequestFilter.java:117
- doFilterInternal(httpRequest, httpResponse, filterChain);
省略无关代码直接到 springmvc 核心代码 dispatcherServlet
- DispatcherServlet 的核心方法,负责协调整个请求处理过程
- DispatcherServlet 是一个 Servlet
- /org/springframework/web/servlet/DispatcherServlet.java:963
- doDispatch(request, response);
核心的方法解析
- DispatcherServlet:
- 核心组件之一,所有的请求都会经过它进行处理。DispatcherServlet 负责接收 HTTP 请求、调用相应的控制器进行处理,并将处理结果返回给客户端。
- doDispatch() 方法首先会通过 HandlerMapping 获取当前请求对应的 HandlerExecutionChain 对象,该对象包含了请求路径所对应的处理器及其拦截器。
* 如果未找到匹配的处理器,doDispatch() 方法会调用 noHandlerFound() 方法,返回 404 状态码。
- HandlerMapping:
- 是将请求路径映射到相应的处理器(Controller)的组件。在执行 DispatcherServlet 之前,会先执行 HandlerMapping 中的 lookupHandler() 方法,根据请求路径找到对应的处理器。
- DispatcherServlet将要调用的方法及其参数等相关信息封装成一个HandlerExecutionChain对象并封装到ModelAndView对象中返回给DispatcherServlet。
- HandlerAdapter:
- 是调用处理器(Controller)的组件。在找到处理器之后,会使用 HandlerAdapter 将处理器包装成可调用的形式,然后调用其 handle() 方法进行处理。
- HandlerAdapter将处理器对象适配成能够处理请求的处理器执行链(HandlerExecutionChain)。因为不同类型的处理器对象需要使用不同的HandlerAdpater进行适配。
- handle 方法会使用 HandlerAdapter 执行处理器的业务逻辑,并将处理结果封装成 ModelAndView 对象返回。
- HandlerInterceptor:
- 是拦截请求和处理器调用之间的组件。HandlerInterceptor 中定义了多个拦截器方法,可以用于在处理器执行前、执行后以及渲染前进行相关处理。
- 如果找到了匹配的处理器,doDispatch() 方法会执行与处理器相关联的拦截器,在 HandlerInterceptor.preHandle()、postHandle() 方法中可以进行权限验证等操作。
- 如果所有拦截器的 preHandle()、postHandle() 方法均返回 true,则说明请求可以继续处理。
- HandlerExceptionResolver:
- 是中用于处理异常的组件。当出现异常时,会通过 ExceptionResolver 将异常转化为 ModelAndView 对象,并将其交给 DispatcherServlet 进行处理。
- 最后则会调用 processDispatchResult() 方法进行异常处理。
源码
// DispatcherServlet 的 service 方法
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
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);
// 1. 查找 HandlerMapping,获取 HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 2. 使用 HandlerAdapter 将处理器包装成可调用的形式
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 调用拦截器的预处理方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 4. 执行Handler调用
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 5. 调用拦截器的后处理方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 6. 处理异常
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception e) {
triggerAfterCompletion(processedRequest, response, mappedHandler, e);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
// 查找 HandlerMapping 的 getHandler 方法
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 获取所有的 HandlerMapping
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
// 查找 HandlerExecutionChain
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
// 使用 HandlerAdapter 调用处理器的 handle 方法
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// ...
try {
// 1. 对请求参数进行解析和验证
mavContainer.setRequestHandled(false);
// 2. 调用处理器的 handle 方法
Object result = invokeHandlerMethod(request, response, handler);
// 3. 处理处理器的返回值
if (result instanceof ModelAndView) {
mav = (ModelAndView) result;
}
else {
mav = new ModelAndView(getViewName(request));
mav.addObject(DEFAULT_MODEL_NAME, result);
}
} catch (Exception ex) {
if (!mavContainer.isRequestHandled()) {
mav = handleException(request, response, handler, ex);
mavContainer.setRequestHandled(true);
}
else {
logger.debug("Exception cleared after handling of request [" + request.getRequestURI() + "]", ex);
}
}
// ...
return mav;
}
本文来自博客园,作者:vx_guanchaoguo0,转载请注明原文链接:https://www.cnblogs.com/guanchaoguo/p/17315052.html