您现在的位置是:亿华云 > 应用开发

SpringMVC核心组件HandlerMapping,你清楚了吗?

亿华云2025-10-03 06:42:25【应用开发】0人已围观

简介概述当一个请求过来后Spring是如何进行处理的?下面简单的罗列下请个的过程中核心组件SpringMVC处理的流程:DispatcherServlet 所有请求的入口 HandlerMa

概述

当一个请求过来后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对象,主要就是心组根据请求的URI     mappedHandler = 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 {        // 根据请求地址查询对应的HandlerMethod       HandlerMethod 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获取容器中的所有Bean         for (String beanName : getCandidateBeanNames()) {        if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {          processCandidateBean(beanName);       }     }     handlerMethodsInitialized(getHandlerMethods());   }   protected void processCandidateBean(String beanName) {      Class<?> beanType = null;     try {        // 根据BeanName获取对应的Class       beanType = obtainApplicationContext().getType(beanName);     }     // ...     // isHandler方法判断当前的类是否符合条件,该方法在RequestMappingHandlerMapping中实现     // isHandler方法用处就是判断当前的Class@Controller或者@RequestMapping注解     // 这样就将所有的@Controller与RequestMappingHandlerMapping关联一起了。     if (beanType != null && isHandler(beanType)) {        // 查找所有的HandlerMethod       detectHandlerMethods(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);       }     }   } } 

很赞哦!(42)