1. SpringMVC重要组件
1. DispatcherServlet
SpringMVC的中央Servlet,所有请求的入口,重写了doService()方法。核心方法:doService()、doDispatch()。
2. HandlerMapping
处理器映射,负责根据HttpServletRequest找到对应的Handler,这里返回Handler的辅助类HandlerExecutionChain。
public interface HandlerMapping {
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
3. HandlerExecutionChain
Handler execution chain, consisting of handler object and any handler interceptors.
处理器执行链,Handler辅助类,由Handler对象和一些HandlerInterceptor组成,主要功能为执行拦截器,核心属性和方法:
private final Object handler;
private HandlerInterceptor[] interceptors;
// 一般情况下返回的是一个HandlerMethod对象
Object getHandler()
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response)
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)
4. HandlerMethod
Encapsulates information about a handler method consisting of a method and a bean. Provides convenient access to method parameters, the method return value, method annotations, etc.
保存了Controller Bean对象和对应的Method对象。
// 对应的Controller实例
private final Object bean;
// 处理请求的方法
private final Method method;
// 方法的参数
private final MethodParameter[] parameters;
5. HandlerInterceptor
拦截器,自定义拦截器实现此接口。preHandle()和postHandle()方法分别在实际的请求处理之前和之后执行。
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
6. HandlerAdapter
处理器适配器。handle()方法负责执行实际的请求处理并返回一个ModelAndView对象。
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}
2. SpringMVC请求处理流程
- DispatcherServlet作为入口且重写了doService()方法,所以请求会首先到doService()方法。下面步骤1、2、3在doService()方法完成,接着doService()方法调用doDispatch()方法,doDispatch()方法完成剩下的所有步骤。
- WebApplicationContext对象绑定到Request,key为DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE。
- locale resolver绑定到Request。
- theme resolver绑定到Request。
- 如果是multipart request,包装成MultipartHttpServletRequest。
- 调用HandlerMapping的getHandler()方法获取对应的Handler,这里是HandlerExecutionChain对象。
- 调用HandlerExecutionChain的getHandler()方法,这里返回HandlerMethod对象,根据Handler获取HandlerAdapter。
- 如果是GET或者HEAD方法执行HandlerAdapter的getLastModified()方法。
- 调用HandlerExecutionChain的applyPreHandle()方法执行HandlerInterceptor的preHandle()方法。
- 调用HandlerAdapter的handle()方法执行实际的请求处理,实际执行HandlerMethod的对应方法,返回ModelAndView对象,
- 根据ModelAndView视图解析器找到对应的View。
- 渲染视图返回用户。
3. HandlerMethod收集
请求处理流程中的第5步中提到了HandlerMapping,这个核心第实现是RequestMappingHandlerMapping类,当使用SpringMVC时此类就会被注入到spring容器中,此类实现了InitializingBean接口,所以在实例化过程中会执行afterPropertiesSet()方法,此方法调用initHandlerMethods(),这个方法负责收集HandlerMethod,其相关源码如下:
/**
* Detects handler methods at initialization.
* @see #initHandlerMethods
*/
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
/**
* Scan beans in the ApplicationContext, detect and register handler methods.
* @see #getCandidateBeanNames()
* @see #processCandidateBean
* @see #handlerMethodsInitialized
*/
protected void initHandlerMethods() {
// 1. 遍历所有beanName
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
/**
* 2. 判断beanName对应的Class是否为Controller
*/
protected void processCandidateBean(String beanName) {
Class> beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
// 3. 判断逻辑为是否有@Controller或@RequestMapping注解
if (beanType != null && isHandler(beanType)) {
// 检测Controller类中的HandlerMethod
detectHandlerMethods(beanName);
}
}
@Override
protected boolean isHandler(Class> beanType) {
// 判断逻辑为是否有@Controller或@RequestMapping注解
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
protected void detectHandlerMethods(Object handler) {
Class> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
Class> userType = ClassUtils.getUserClass(handlerType);
// 4. 检测到所有Method
Map methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup) method -> {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace("Mapped " + methods.size() + " handler method(s) for " + userType + ": " + methods);
}
// 5. 对检测到到Method进行注册缓存。
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 这里把解析出到HanderMethod对象进行组册
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
// 6. 这里组册到MappingRegistry的对应的集合中缓存起来
this.mappingRegistry.register(mapping, handler, method);
}