DispatherServlet 源码解析
DispatherServlet 源码解析
DispatherServlet 初始化做了什么?
在 DispatherServlet 的 OnRefresh()方法打上断点,可以看到是 Servlet 生命周期 init() 方法一直调用到了 OnRefresh() 方法, OnRefresh() 又调用了 initStrategies() 方法
在 DispatherServlet 的 initStrategies() 方法中,有9个方法完成了DispatherServlet 的初始化过程
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
initMultipartResolver
Multipart:是文件上传的一种格式,这个方法是初始化文件上传时用到的解析器
initLocaleResolver
spring对于国际化的支持,只要是关于一些本地化解析器的初始化,解决语言问题
-
AcceptHeaderLocaleResolver:从请求头中获取本地信息
-
CookieLocaleResolver:从 Cookie 中获取本地信息
initHandlerMappings
建立一个请求路径与控制器方法的映射
- 所有的请求都会来到 DispatherServlet ,当时所有的请求都会由某个控制器方法来执行
- HandlerMapaping:路径映射器,其中有一个实现就是用来解析 RequestMapping:RequestMappingHandlerMapping
/**
* Initialize the HandlerMappings used by this class.
* <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
* we default to BeanNameUrlHandlerMapping.
* 初始化 HandlerMappings,如果 BeanFactory中没有,则使用默认的 BeanNameUrlHandlerMapping
*/
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
// detectAllHandlerMappings 探测所有的 HandlerMapping,SpringMVC中父子容器,当前容器没有,则会去父容器探测
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
// 如果没有发现其他的映射,通过注册一个默认的 HandlerMapping 来确保我们至少有一个 HandlerMapping
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
}
for (HandlerMapping mapping : this.handlerMappings) {
if (mapping.usesPathPatterns()) {
this.parseRequestPath = true;
break;
}
}
}
getDefaultStrategies 就是去类路径下读取 DispatcherServlet.properties 这个文件
在 DispatcherServlet.properties 中定义了三个 HandlerMappiing
将这三个 HandlerMapping 的实现类加入到 DispatcherServlet 的成员变量 handlerMappings 中
这里为了测试方便,直接将 RequestMappingHandlerMapping 注入到 IOC 容器中
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping(){
return new RequestMappingHandlerMapping();
}
从容器中获取 RequestMappingHandlerMapping 对象,获得路径与控制器方法的映射关系
// 作用 解析 @RequestMapping 以及派生注解,生成路径与控制器方法的映射关系,在初始化时就生成
RequestMappingHandlerMapping requestMappingHandlerMapping = ac.getBean(RequestMappingHandlerMapping.class);
/*
RequestMappingInfo:请求参数,请求路径,请求方式 封装在该对象中
HandlerMethod:哪个控制器的哪个方法
*/
Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
handlerMethods.forEach((k, v) -> {
logger.debug("K:{}==V:{}",k,v);
});
结果:

也就是解析了我们自己写的 Controller1 这个控制器
/*
请求来了,获取控制器方法
HandlerExecutionChain:处理器执行链,封装了 handlerMethods 以及一些拦截器
*/
HandlerExecutionChain chain = requestMappingHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/test1"));
logger.debug("{}",chain);
执行结果:

找到一个执行链,Controller1中 test1方法,并且没有拦截器
getHandlerMethods:是去 RequestMappingHandlerMapping 对象的成员变量 mappingRegistry 中获取并进一步封装,这个 mappingRegistry 是什么时候初始化的呢?
可以看到 RequestMappingHandlerMapping 是继承了 RequestMappingHandlerMapping ,在 RequestMappingHandlerMapping 中有一个方法:afterPropertiesSet() ,afterPropertiesSet() 是在Spring Bean生命周期过程中自动调用的,mappingRegistry 初始化就是在这个方法中完成的
执行链:
afterPropertiesSet -> initHandlerMethods() -> processCandidateBean(beanName) -> detectHandlerMethods(beanName) -> registerHandlerMethod(handler, invocableMethod, mapping)
initHandlerAdapters
- 适配不同形式的控制器方法,然后去调用他们,简单来说就是去调用控制器方法的,它也有多种实现
/*
请求来了,获取控制器方法
HandlerExecutionChain:处理器执行链,封装了 handlerMethods 以及一些拦截器
*/
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test2");
request.addParameter("name","jalivv");
MockHttpServletResponse response = new MockHttpServletResponse();
HandlerExecutionChain chain = requestMappingHandlerMapping.getHandler(request);
logger.debug("{}",chain);
MyRequestMappingHandlerAdapter handlerAdapter = ac.getBean(MyRequestMappingHandlerAdapter.class);
handlerAdapter.invokeHandlerMethod(request, response, ((HandlerMethod) chain.getHandler()));
// RequestMappingHandlerAdapter 源码中 invokeMethod 访问修饰符为 protected ,这里新建一个类,继承
RequestMappingHandlerAdapter,将其访问修饰符改为 public,方便测试
@Component
public class MyRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {
@Override
public ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
return super.invokeHandlerMethod(request, response, handlerMethod);
}
}
运行结果:

成功执行了 Controller1 中的 test2() 方法
参数解析器:
logger.debug("------------------所有的参数解析器------------------");
for (HandlerMethodArgumentResolver argumentResolver : handlerAdapter.getArgumentResolvers()) {
logger.debug("{}", argumentResolver);
}
运行结果:

返回值解析器:
logger.debug("------------------所有的返回值解析器------------------");
for (HandlerMethodReturnValueHandler returnValueHandler : handlerAdapter.getReturnValueHandlers()) {
logger.debug("{}",returnValueHandler);
}
运行结果:

-
自定义参数解析器
新建一个 TokenHandlerMethodArgumentResolver 实现 HandlerMethodArgumentResolver 接口
@Component public class TokenHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { // 支持哪些参数解析 @Override public boolean supportsParameter(MethodParameter parameter) { // 由 token 注解,才解析 return parameter.getParameterAnnotation(Token.class) != null; } // 参数的值 @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { return webRequest.getHeader("token"); } }通过 set 注入 给 RequestMappingHandlerAdapter 赋值
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter(TokenHandlerMethodArgumentResolver tokenResolver) { MyRequestMappingHandlerAdapter handlerAdapter = new MyRequestMappingHandlerAdapter(); handlerAdapter.setCustomArgumentResolvers(Arrays.asList(tokenResolver)); return handlerAdapter; }模拟请求,查看方法执行结果
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/test3"); request.addParameter("name","jalivv"); request.addHeader("token","jalivvToken666"); MockHttpServletResponse response = new MockHttpServletResponse(); HandlerExecutionChain chain = requestMappingHandlerMapping.getHandler(request); // handlerAdapter 作用:调用控制器方法 MyRequestMappingHandlerAdapter handlerAdapter = (MyRequestMappingHandlerAdapter) ac.getBean("requestMappingHandlerAdapter"); handlerAdapter.invokeHandlerMethod(request, response, ((HandlerMethod) chain.getHandler()));结果:

-
自定义返回值解析器
新建一个类 YmlReturnValueHandler 实现 HandlerMethodReturnValueHandler 接口
@Component public class YmlReturnValueHandler implements HandlerMethodReturnValueHandler { // 什么样的返回值采用该解析器 @Override public boolean supportsReturnType(MethodParameter returnType) { return returnType.getMethodAnnotation(Yml.class) != null; } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 1. 转换返回结果为 yaml 字符串 String str = new Yaml().dump(returnValue); // 2. 将 yaml 字符串写入相应 HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); response.setContentType("text/plain;charset=utf-8"); response.getWriter().println(str); // 3. 设置请求已经处理完毕(防止视图解析器篡改相应结果) mavContainer.setRequestHandled(true); } }set 注入给 RequestMappingHandlerAdapter 赋值
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter(TokenHandlerMethodArgumentResolver tokenResolver, YmlReturnValueHandler returnValueHandler) { MyRequestMappingHandlerAdapter handlerAdapter = new MyRequestMappingHandlerAdapter(); handlerAdapter.setCustomArgumentResolvers(Arrays.asList(tokenResolver)); handlerAdapter.setCustomReturnValueHandlers(Arrays.asList(returnValueHandler)); return handlerAdapter; }测试代码:
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test4"); MockHttpServletResponse response = new MockHttpServletResponse(); HandlerExecutionChain chain = requestMappingHandlerMapping.getHandler(request); // handlerAdapter 作用:调用控制器方法 MyRequestMappingHandlerAdapter handlerAdapter = (MyRequestMappingHandlerAdapter) ac.getBean("requestMappingHandlerAdapter"); handlerAdapter.invokeHandlerMethod(request, response, ((HandlerMethod) chain.getHandler())); byte[] bytes = response.getContentAsByteArray(); String s = new String(bytes, StandardCharsets.UTF_8); logger.debug("{}",s);执行结果:

-
参数解析器
在 handlerAdapter 调用控制器方法之前,它需要准备好每一个参数,给参数赋值就需要用到参数解析器
------------------所有的参数解析器------------------
-
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
-
org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
-
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
-
org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver
-
org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver
-
org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver
-
org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.RequestAttributeMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor
-
org.springframework.web.servlet.mvc.method.annotation.RedirectAttributesMethodArgumentResolver
-
org.springframework.web.method.annotation.ModelMethodProcessor
-
org.springframework.web.method.annotation.MapMethodProcessor
-
org.springframework.web.method.annotation.ErrorsMethodArgumentResolver
-
org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.UriComponentsBuilderMethodArgumentResolve
-
com.jalivv.spring.a20.TokenHandlerMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.PrincipalMethodArgumentResolver
-
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
-
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
-
initHandlerExceptionResolvers
- 控制器方法有可能出现异常,解析异常
- 出现异常之后,该怎么解析

浙公网安备 33010602011771号