1.前端控制器的架构?DispatcherServlet
分析得到处理流程
请求一来,先到达HttpServlet的service方法,service决定调用具体的doGet,doPost等方法,然后由于我们DispatcherServlet的父抽下类FrameworkServlet重写了HttpServlet的doGet等方法,于是就会调用FrameworkServlet的doGet等方法,然后在doGet等方法中都会调用本类的processRequest(request, response)这个方法,方法内的关键代码就是调用doService(request, response)由于doService在FrameworkServlet中为抽象方法,所以调用的DispatcherServlet重写的doService方法,在doService方法中调用了最为关键的doDispatch方法,所以我们主要来研究
DispatcherServlet的doDispatch方法
DispatcherServlet的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 {
//检查当前请求是否为文件上传请求 若是,就包装request
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//决定我们当前请求用哪一个处理器(controller)
mappedHandler = getHandler(processedRequest);
//如果没找到能处理当前请求的处理器 这执行以下代码(抛异常或者404)
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//决定当前请求要用哪一个处理器的适配器(拿到controller的适配器,适配器来反射执行方法)
//适配器名:AnnotationMethodHandlerAdapter
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;
}
//真正的执行目标方法(处理器controller的方法被调用,用适配器ha执行的)
//返回一个ModelAndView实例 将目标方法返回值作为试图名,保存到其内View中
//目标方法不论怎么写,最终适配器执行后都会将执行后的信息封装成ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//异步处理器判断是否异步方法,如果是,直接请求借书结束
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//如果方法执行完返回了一个void,没有视图名,则用默认视图名
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);
}
//转发到目标页面(渲染)
//根据方法最终执行完后封装的ModelAndView,转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
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);
}
}
}
}
怎么根据当前请求就能找到哪个类能来处理?:getHandler()细节
getHandler()会返回目标处理器类的执行链——HandlerExecutionChain的一个实例
//其内DefaultAnnotationHandlerMapping中的hanlderMap保存了所有的请求——控制器映射信息
private List<HandlerMapping> handlerMappings;
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//handlerMappings保存了每一个处理器能处理哪些请求的映射信息
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
hanlderMap:ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的hanlderMap属性中
如何找到目标处理器类的适配器?:getHandlerAdapter()细节
三种适配器
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
- RequstMappingHandlerAdapter(spingmvc低版本是AnnotationMethodHandlerAdapter)
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
//遍历所有的适配器(三种)
//最终拿到AnnotationMethodHandlerAdapter(能解析注解方法)的适配器
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");
}
HttpRequestHandlerAdapter的supports()方法——以HttpRequestHandlerAdapter为例:
public boolean supports(Object handler) { return (handler instanceof HttpRequestHandler);}
就是判断你当前的handler是不是某类型的,这里我们是注解的Controller,是RequstMappingHandlerAdapter类型
RequstMappingHandlerAdapter的supports()方法
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
适配器怎么执行的方法?:handler()细节
调用的是RequstMappingHandlerAdapter的父抽象类的handler()方法,然后调用了子类的handleInternal()实现方法
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
//如果需要,在synchronized块中执行invokeHandlerMethod.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
//执行目标方法(没有HttpSession可用)
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
//执行目标方法(不需要同步会话)
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
//返回ModelAndView
return mav;
}
怎么来到目标页面的?: processDispatchResult方法
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);
}
}
render(mv, request, response);方法执行解析完毕,来到页面
视图解析具体的流程在后续文章会分析