概述
当一个请求过来后Spring是如何进行处理的?下面简单的罗列下请个的过程中核心组件
SpringMVC处理的流程:
DispatcherServlet 所有请求的入口
HandlerMapping 将请求地址与处理程序关联
HandlerAdapter 真正的处理程序,如执行上一步中对应的处理程序
HandlerMethodArgumentResolver 对参数进行解析,这里面还涉及到很多其它东西
HanlderMethodReturnValueHandler 对返回值进行输出处理
ViewResolver 当上一步返回结果为ModelAndView时会应用视图解析器
一个请求的处理过程
获取HandlerMapping
该步从容器中获取所有的HandlerMapping对象。
public class DispatcherServlet extends FrameworkServlet {private List<HandlerMapping> handlerMappings;private void initHandlerMappings(ApplicationContext context) {// 在ApplicationContext中查找所有HandlerMappings,包括祖先上下文。Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerMappings = new ArrayList<>(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerMappings);}}}
查找HandlerMapping
该步从获取的HandlerMapping中查找适合当前请求的HandlerMapping。
public class DispatcherServlet extends FrameworkServlet {private List<HandlerMapping> handlerMappings;protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HandlerExecutionChain mappedHandler = null;// 查找能够处理当前请求HandlerMapping对象,主要就是根据请求的URImappedHandler = getHandler(processedRequest);}protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {// HandlerMapping 实现了Ordered接口,是由顺序的,那在这里,谁先匹配谁就处理for (HandlerMapping mapping : this.handlerMappings) {// 在这个过程中会通过查找到的HandlerMapping对象,然后获取合适的处理程序(可能是个Bean对象或是HandlerMethod对象等)HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}}
系统默认有如下5个HandlerMapping
RequestMappingHandlerMapping
BeanNameUrlHandlerMapping
RouterFunctionMapping
SimpleUrlHandlerMapping
WelcomePageHandlerMapping
一般默认都是RequestMappingHandlerMapping匹配
接下来看看是如何进行匹配的
调用父类AbstractHandlerMapping#getHandler方法,父类中的这个方法中定义了特定的逻辑,而针对每种不同的HandlerMapping实现是需要具体的子类来实现AbstractHandlerMapping#getHandlerInternal方法
public abstract class AbstractHandlerMapping {public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {Object handler = getHandlerInternal(request);// ...HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);// ...return executionChain;}}public abstract class AbstractHandlerMethodMapping {protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 获取请求地址String lookupPath = initLookupPath(request);try {// 根据请求地址查询对应的HandlerMethodHandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);}// ...}protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {List<Match> matches = new ArrayList<>();// 在已注册的Mapping中根据请求的url进行查找// 这样查找的this.pathLookup.get(urlPath);List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);if (!matches.isEmpty()) {Match bestMatch = matches.get(0);// ...handleMatch(bestMatch.mapping, lookupPath, request);return bestMatch.getHandlerMethod();}// ...}}
到这里就是查找处理请求的HandlerMethod对象。接下来看看系统是如何进行初始化所有的HandlerMethod
初始化HandlerMethod
public class RequestMappingHandlerMapping {public void afterPropertiesSet() {// ...super.afterPropertiesSet();}}public abstract class AbstractHandlerMethodMapping {public void afterPropertiesSet() {initHandlerMethods();}protected void initHandlerMethods() {// getCandidateBeanNames获取容器中的所有Beanfor (String beanName : getCandidateBeanNames()) {if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {processCandidateBean(beanName);}}handlerMethodsInitialized(getHandlerMethods());}protected void processCandidateBean(String beanName) {Class<?> beanType = null;try {// 根据BeanName获取对应的ClassbeanType = obtainApplicationContext().getType(beanName);}// ...// isHandler方法判断当前的类是否符合条件,该方法在RequestMappingHandlerMapping中实现// isHandler方法用处就是判断当前的Class@Controller或者@RequestMapping注解// 这样就将所有的@Controller与RequestMappingHandlerMapping关联一起了。if (beanType != null && isHandler(beanType)) {// 查找所有的HandlerMethoddetectHandlerMethods(beanName);}}protected void detectHandlerMethods(Object handler) {Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());if (handlerType != null) {Class<?> userType = ClassUtils.getUserClass(handlerType);// 查找Class中的所有方法Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> {try {// 将每一个符合条件的方法(方法上有@RequestMapping注解的)// 封装到RequestMappingInfo对象中return getMappingForMethod(method, userType);}// ...});methods.forEach((method, mapping) -> {Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);// 将找到的所有Method进行注册添加到Map中registerHandlerMethod(handler, invocableMethod, mapping);});}}protected void registerHandlerMethod(Object handler, Method method, T mapping) {this.mappingRegistry.register(mapping, handler, method);}class MappingRegistry {// T : RequestMappingInfo, handler: 字符串(usersController)Bean名称,method:请求方法对象public void register(T mapping, Object handler, Method method) {// 创建HandlerMethod对象HandlerMethod handlerMethod = createHandlerMethod(handler, method);// ...for (String path : directPaths) {// 缓存上,在请求到来的时候 会从这个pathLookup集合中查找this.pathLookup.add(path, mapping);}}}}
完毕!!!
求个关注+转发






