DispatchServlet的service()
一个请求是从一个客户端发出,经过容器然后将请求交与合适的servlet,servlet调用service()方法来处理这个请求。
如下是 DispatchServlet 继承关系图。
我们主要关心上图中各类的 service() 方法。看看 DispatchServlet 中的 service() 方法来自哪里。
- Servlet: Servlet为接口,只是声明了 service()方法。
- GenericServlet: 抽象类,service() 方法交由子类实现。
- HttpServlet: 抽象类,实现了 service() 方法,根据请求方式的不同,判断调用什么方法来处理请求。如果我们不用框架的话,那么只需要继承自 HttpServlet,然后重写 doGet()或者 doPost() 方法即可,重写的代码就是处理请求的过程所要执行的代码。
- HttpServletBean: 继承HttpServlet 的service() 方法。
- FramworkServlet: 重写 HttpServlet 的 service() 方法,目的是为了能够处理 PATCH 请求。什么是PATCH请求
- DispatchServlet: 继承 FramworkServlet 的 service() 方法.
总结,DispatchServlet的 service() 方法来自父类 FramworkServlet,该方法既可以处理已知的请求(如GET,POST),又可以处理 PATCH 请求,然后根据请求方式的不同执行不同的处理过程。
DispatchServlet的doGet()等方法
我们知道一个servlet要想处理请求,必须重写doGet() doPost()等方法,DispatchServlet当然也不例外,那么DispatchServlet的 doGet(),doPost() 方法重写在哪里呢?答案是在其父类 FramworkServlet 中。DispatchServlet 直接继承即可。我们来看一下 FramworkServlet 部分源码。
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
//增加对 PATCH 请求的处理
if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
processRequest(request, response);
}
else {
super.service(request, response);
}
}
//重写doGet()方法
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
//重写doPost()方法
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
好,通过以上代码,我们了解了无论什么样的请求方法,DispatchServlet 全部都委托给了一个 processRequest() 方法进行处理。如下是 processRequest() 方法源代码。
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
initContextHolders(request, localeContext, requestAttributes);
try {
//doService() FramworkServlet没有实现,只是简单定义,交由 DispatchServlet实现
doService(request, response);
}
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
}
else {
if (asyncManager.isConcurrentHandlingStarted()) {
logger.debug("Leaving response open for concurrent processing");
}
else {
this.logger.debug("Successfully completed request");
}
}
}
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
深入了解 doService() 方法:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
//设置上下文及其他属性,方便其他方法需要时从request获取
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
//深入了解
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
继续深入了解 doDispatch() 方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
//HandlerExecutionChain,执行链,后面会详细说明
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
//逻辑视图对象
ModelAndView mv = null;
Exception dispatchException = null;
try {
//检查请求是否为文件上传请求,如果是使文件上传解析器可用
processedRequest = checkMultipart(request);
//如果是文件上传请求multipartRequestParsed值为true
multipartRequestParsed = (processedRequest != request);
//获取处理该请求的handler
//深入了解
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == 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 = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
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 NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", 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);
}
}
}
}
HandlerExecutionChain:
包含一个处理请求的处理器(Handler),同时包含若干个对该请求实施拦截的拦截器(HandlerInterceptor),当HandlerMapping 返回 HandlerExecutionChain 后, DispatchServlet 将请求交给定义在 HandlerExecutionChain 中的拦截器和处理器一并处理。
拦截器可以在三个地方对请求进行处理,分别是:
- boolean preHandler(request,response,handler): 请求到达 adapter 之前。返回 true 继续传递请求,false 不传递请求,将请求驳回。
- void postHandler(request,response,handler): adapter 处理完之后。
- void afterCompletion(request,response,handler,exception): 响应已经被渲染之后。
-
深入了解 DispatchServlet.getHandler() 方法。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //循环遍历默认的处理器映射,如果找到handler,直接返回 for (HandlerMapping hm : this.handlerMappings) { ... HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }
HandlerMapping 本身是一个接口,只有一个方法 getHandler(),本例中的 this.handlerMappings 中包含3个 HandlerMapping 的实现,他们将按照先后顺序查找该请求的处理器映射,找到即返回。
如下是本例中包含的3个处理器映射实现类:
- RequestMappingHandlerMapping
- BeanNameUrlHandlerMapping
- SimpleUrlHandlerMapping
如下是 HandlerMapping 继承关系图
每个实现类都继承了HandlerMapping接口,故每个处理器映射都有一个用来查找handler的getHandler()方法,我们以本例的 RequestMappingHandlerMapping 类为例子来了解该类的 getHandler() 方法。
我们由上面的继承关系图可得知:
RequestMappingHandlerMapping 是 AbstractHandlerMapping 和 AbstractHandlerMethodMapping 的子类。
以下是 AbstractHandlerMapping 的部分源码.public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //主要调用了 getHandlerInternal() 方法 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } //根据请求的路径将handler和对应的拦截器包装成一个handlerExecutionChain对象 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
通过查看源代码可知主要调用了 getHandlerInternal() 方法,该方法由子类 AbstractHandlerMethodMapping 实现。如下是子类 AbstractHandlerMethodMapping 的部分源码。
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { //获取请求的URL路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); //获取读锁 this.mappingRegistry.acquireReadLock(); try { //根据请求路径找到对应的handler方法 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); //返回HandlerMethod对象 return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { //释放获取到的读锁 this.mappingRegistry.releaseReadLock(); } }
该方法执行完毕之后,继续执行 AbstractHandlerMapping.getHandler()方法中的其余部分。其余部分所做的主要工作就是根据请求的URL路径找到拦截该路径的拦截器,然后将handler和这些拦截器封装成为一个 HandlerExecutionChain 对象返回。
至此,DispatchServlet.doDispatch() 方法的 mappedHandler 对象初始化完毕。
深入了解 DispatchServlet.getHandlerAdapter() 方法
如下是 DispatchServlet.getHandlerAdapter() 方法部分源码。
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (ha.supports(handler)) {
return ha;
}
}
}
HandlerAdapter 为一个接口,该接口内部定义了如下三个方法:
- supports(): 给出一个 handler,查看该 HandlerAdapter 是否支持该 handler。
- handle(): 使用本 HandlerAdapter 代理执行这个 handler 中的方法。
- getLastModified(): 查看该请求的 lastModified 值
this.handlerAdapters 为 实现 HandlerAdapter 接口的实现类集合,默认的实现类有如下三个:
- RequestMappingHandlerAdapter
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
继承关系如下图所示:
未完待更...