DispatcherServlet调用点方法
// 上层的调用方法为AbstractApplicationContext#refresh()---》onRefresh();
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* 初始化解析器、映射器,适配器等等,根据/org/springframework/web/servlet/DispatcherServlet.properties 配置文件初始化
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
最主要的处理方法
doDispatch(HttpServletRequest request, HttpServletResponse response)
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 {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 1.为当前的请求匹配对应的处理Handler,其实也就是根据url去匹配要执行Controller哪个方法.详见 解释1
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
//2.确定当前请求的适配器
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;
}
}
// 3 前置通知器 HandlerInterceptor
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 4.实际执行
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//5. 后置过滤拦截
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);
}
//6.视图渲染、返回值处理
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);
}
}
}
}
- 解释1
getHandler()-->AbstractHandlerMethodMapping#getHandlerInternal(HttpServletRequest request)。把HandlerMapping封装成HandlerExecutionChain
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
** url 映射method在容器初始化的时候已经准备好**
// 入口 开始声明的initStrategies() -->initHandlerMappings(context);会山路十八弯的调到
AbstractHandlerMethodMapping#initHandlerMethods() {
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
-- isHandler(beanType)判断是否有@Controller || @RequestMapping注解
//detectHandlerMethods 方法内
Map methods = MethodIntrospector.selectMethods(userType,
new MethodIntrospector.MetadataLookup() {
@Override
public T inspect(Method method) {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
}
});
// 执行完上述方法之后methods ,Controller内带有RequestMapping的method为key, @RequestMapping封装成RequestMappingInfo为value
Map methods =
{
public java.lang.String ren.xuedao.moudle.sys.controller.LoginController.login(java.lang.String,java.lang.String,org.springframework.ui.Model)={[/login],methods=[POST]}
, public java.lang.String ren.xuedao.moudle.sys.controller.LoginController.home(org.springframework.ui.Model)={[/home],methods=[GET]},
public java.lang.String ren.xuedao.moudle.sys.controller.LoginController.logOut()={[/logout]},
public java.lang.String ren.xuedao.moudle.sys.controller.LoginController.layui()={[/layui]}
}
// 循环methods Map 构造另一种形式的map
for (Map.Entry entry : methods.entrySet()) {
Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType);
T mapping = entry.getValue();
registerHandlerMethod(handler, invocableMethod, mapping);
}
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
this.mappingLookup.put(mapping, handlerMethod);
List directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
// 添加到registry
this.registry.put(mapping, new MappingRegistration(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
// 最终模样
Map> registry =
{
{[/login],methods=[POST]}=org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistration@81e87eb
, {[/home],methods=[GET]}=org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistration@6bb30dc5
}
AbstractHandlerMethodMapping$MappingRegistration {
directUrls = [/login],
handlerMethod = public java.lang.String ren.xuedao.moudle.sys.controller.LoginController.login(java.lang.String,java.lang.String,org.springframework.ui.Model),
mapping = {[/login],methods=[POST]},
mappingName = LC#login
}
-
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());用到了策略模式去匹配对应的
HandlerAdapter一共有三种,即下图所示。作用就是去使用哪一种类型去处理请求。下面4中所示。
前置过滤器拦截
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
- 实际执行
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
ServletInvocableHandlerMethod#invokeAndHandle
4.1 调用 InvocableHandlerMethod#invokeForRequest
4.1.1Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);InvocableHandlerMethod.getMethodArgumentValues(request, mavContainer, providedArgs);策略模式获取hand中方法的入参数组
4.1.2 Object returnValue = doInvoke(args); 反射调用hand中的method
4.2 调用this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);对method的返回参数进行处理,也是策略模式。 - 后置过滤拦截器 mappedHandler.applyPostHandle(processedRequest, response, mv);
- processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);视图渲染、返回值处理
6.1 render(mv, request, response);
6.2 mappedHandler.triggerAfterCompletion(request, response, null);后置过滤器,释放资源,关闭连接
---未完待续 ,后续把图补上。