客户端发送get或者post等请求,会调用Servelt项相对应的方法,比如get请求,就会执行Servlet的doGet方法。
进过查看,DispatcherServelt类中并没有覆盖这几种方法,根据java多态的特性,如果子类没有此方法,那么就去直接父类找。然后在FrameworkServlet类中找到了处理这些请求的方法:
然后我们看处理这几种请求的方法体:
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* 处理Get请求
*/
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* 处理Post请求
*/
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* 处理Put请求
*/
@Override
protected final void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* 处理Delete请求
*/
@Override
protected final void doDelete(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
所有的请求,方法里面都没有进行处理,而是统一委托给processRequest方法进行处理。FrameworkServlet的processRequest方法处理了所有请求,那么我们来看一下他的如何工作的:
此方法的注释上面说的是,这个方法处理请求,不管请求成功与否,都会发布事件,实际事件处理由Service方法执行。
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取系统当前时间戳
long startTime = System.currentTimeMillis();
// 申明一个异常顶层对象Throwable
Throwable failureCause = null;
// 本地化、国际化处理。
// 获取上一个LocaleContext,这里叫上一个,是因为此方法是从ThreadLocal中获取的,获取当前线程的LocaleContext。
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
// 构建一个本地国际化上下文,SimpleLocaleContext
LocaleContext localeContext = buildLocaleContext(request);
// 获取当前绑定到线程的RequestAttributes
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 构建ServletRequestAttributes
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 将localeContext和requestAttributes放入当前线程中
initContextHolders(request, localeContext, requestAttributes);
try {
// 然后进入doService方法。这个方法才是大菜,上面那些都是一些准备工作,后面finally里面的都是一些收尾工作
doService(request, response);
}
catch (ServletException | 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();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
我们来看看这个doService方法,这个方法FreameworkServlet没有实现,是DispatcherServlet进行实现的。
从这里可以看出,FrameworkServelt主要做的是一些准备工作,比如系统初始化的时候,也基本上是FrameworkServelt在做,这里准备一些工作也是他在做,分工还是很明确的。
我们来看 DispatcherServlet的doService方法:
方法上面的注释大概意思是:将请求交给doDispatch来处理。。。怪我道行不高,搞不懂其原因。
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// 保留请求属性的快照,以防出现include,
// 能够在include之后恢复原始属性。
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));
}
}
}
// 使框架对象对处理程序和视图对象可用。
// 将web应用上下文对象放置在request域中
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
// 下面都是针对于视图的一些属性,放置在request域中
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
// 看flashMap是否为null,不为空的话做如下操作。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()) {
// 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 mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 检查当前请求是不是一个MultipartHttpServletRequest请求,(文件上传请求)
processedRequest = checkMultipart(request);
// 将是不是文件请求赋值给multipartRequestParsed
multipartRequestParsed = (processedRequest != request);
// 确定当前请求程序,也就是根据请求类型,返回不同的handler。
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 如果当前请求没有handler进行处理,那么就抛出异常
noHandlerFound(processedRequest, response);
return;
}
// 获取当前处理器的适配器,这里使用到了适配器模式,
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 如果最后一个处理程序支持头修改,则返回最后一个处理程序。
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 实际调用处理程序。讲request,response传递过去,
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 如果说视图不为null,并且没有视图名称,并且有默认的视图名称,那么将视图的名称设置为默认的视图名称
applyDefaultViewName(processedRequest, mv);
// 执行所有的handler,就是执行我们所有的HandlerInterceptor实现类的方法。包括我们自定义的。
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);
}
}
}
}