概述
DispatcherServlet的真正请求处理,也就是Servlet的service()方法逻辑
// org.springframework.web.servlet.FrameworkServlet#processRequest
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 备份当前线程的国际化Context,再为当前请求重新创建一个
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
// 备份当前线程的RequestAttributes,再为当前请求创建一个
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
// 异步请求管理 TODO
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 将新创建的LocaleContext 和RequestAttributes 绑定到线程变量
initContextHolders(request, localeContext, requestAttributes);
try {
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
// 恢复doService前的上下文对象,发布ServletRequestHandledEvent事件
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
LocaleContextHolder用于做本地化、国际化的上下文容器
RequestContextHolder持有当前request上下文的容器
两个Holder内部都是使用ThreadLocal变量存放与当前请求相关的属性、对象等,例如我们在业务处理程序中可以如下获取当前的HttpServletRequest对象,而不用一层一层传参数进来
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
doService
设置请求request属性,调用doDispatch
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// 如果是include的请求(RequestDispatcher.include),备份attributes
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// 对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
if (this.flashMapManager != null) {
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()) {
// 如果是include请求,进行还原
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
doDispatch
1、解析文件请求
2、获取请求对应的handler
3、获取handler对应的适配器adapter
4、执行handler拦截器preHandle
5、适配器调用handler方法执行逻辑处理,返回mav
6、执行handler拦截器postHandle
7、处理完成渲染View、执行拦截器afterCompletion;如果是异常结束那就是调用异常解析器处理异常
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 {
// 判断是否是文件请求,如果是解析请求返回MultipartHttpServletRequest
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 从所有handlerMappings中获取请求对应的处理器handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 获取handler类型对应的处理器适配器
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)) {
// LastModified缓存机制,适配器调用handler.getLastModified()的获取资源的最后更新时间
// 如果时间与客户端请求头的缓存时间一致,则直接返回HTTP状态码304,表示使用缓存资源
// 继承Controller的handler方式实现LastModified接口即可以支持这种缓存机制
// 而@RequestMapping注解形式的需要自己去调用webRequest.checkNotModified
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 执行handler的拦截器的PreHandle方法,拦截器顺序从前到后
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 适配器调用handler方法,返回mav
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 返回的mav中不带view,给一个默认的view
applyDefaultViewName(processedRequest, mv);
// 执行handler拦截器的PostHandle方法,拦截器顺序从后到前
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 调用结束,异常解析器解析异常、渲染视图、执行拦截器AfterCompletion方法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 执行handler拦截器的AfterCompletion方法,顺序从后到前
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 {
// 如果是文件请求,清理资源
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
最后
以上就是彩色玫瑰为你收集整理的SpringMVC源码笔记(三) DispatcherServlet.service的全部内容,希望文章能够帮你解决SpringMVC源码笔记(三) DispatcherServlet.service所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复