当前位置: 首页 > 科技观察

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

时间:2023-03-16 14:28:05 科技观察

Spring如何处理请求的概述?下面简单列出核心组件SpringMVC在以下流程中的处理流程:DispatcherServlet所有请求的入口HandlerMapping将请求地址与handler关联HandlerAdapter真正的处理程序,比如执行上一步对应的handlerHandlerMethodArgumentResolver解析参数,这里面还涉及很多其他的东西HanlderMethodReturnValueHandler输出返回值ViewResolver当上一步返回的结果是ModelAndView时,会应用视图解析器对一个请求的处理ProcessGetHandlerMapping这一步获取所有的HandlerMapping容器中的对象。publicclassDispatcherServletextendsFrameworkServlet{privateListhandlerMappings;privatevoidinitHandlerMappings(ApplicationContextcontext){//查找ApplicationContext中的所有HandlerMapping,包括祖先上下文。Mapma??tchingBeans=BeanFactoryUtils.beansOfTypeIncludingAncestors(context,HandlerMapping.class,true,false);if(!matchingBeans.isEmpty()){this.handlerMappings=newArrayList<>(matchingBeans.values());AnnotationAwareOrderComparator。sort(this.handlerMappings);}}}查找HandlerMapping这一步从获取的HandlerMappings中寻找适合当前请求的HandlerMapping。publicclassDispatcherServletextendsFrameworkServlet{privateListhandlerMappings;protectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{HandlerExecutionChainmappedHandler=null;//查找能够处理当前请求HandlerMapping对象,主要就是根据请求的URImappedHandler=getHandler(processedRequest);}protectedHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{if(this.handlerMappings!=null){//HandlerMapping实现了Ordered接口,是有顺序的,所以这里,谁先匹配到就处理for(HandlerMappingmapping:this.handlerMappings){//在这个过程中,会把查找传递给HandlerMapping对象,然后获取相应的处理程序(可以是Bean对象或HandlerMethod对象等)HandlerExecutionChainhandler=mapping.getHandler(request);if(handler!=null){returnhandler;}}}returnnull;}}system默认有以下五个HandlerMappingRequestMappingHandlerMappingBeanNameUrlHandlerMappingRouterFunctionMappingSimpleUrlHandlerMappingWelcomePageHandlerMapping一般默认为RequestMappingHandlerMapping匹配接下来我们看看如何调用父类AbstractHandlerMapping#getHandler方法,父类中的这个方法定义了具体的逻辑,对于每一个不同的HandlerMapping实现,都需要具体的子类来实现AbstractHandlerMapping#getHandlerInternal方法//...HandlerExecutionChainexecutionChain=getHandlerExecutionChain(handler,request);//...returnexecutionChain;}}publicabstractclassAbstractHandlerMethodMapping{protectedHandlerMethodgetHandlerInternal(HttpServletRequestrequest)throwsException{//GetrequestaddressaccordingtoStringinlookupPath{Address(Lookup/LookupPath)查询对应的HandlerMethodHandlerMethodhandlerMethod=lookupHandlerMethod(lookupPath,request);返回(handlerMethod!=null?handlerMethod.createWithResolvedBean():null);}//...}protectedHandlerMethodlookupHandlerMethod(StringlookupPath,HttpServletRequestrequest)throwsException{Listmatches=newArrayList<>();//根据请求的url在注册的Mapping中查找//This.pathLookup.get(urlPath);ListddirectPathMatches=this.mappingRegistry.getMappingsByDirectPath(lookupPath);if(!matches.isEmpty()){MatchbestMatch=matches.get(0);//...handleMatch(bestMatch.mapping,lookupPath,request);returnbestMatch.getHandlerMethod();}//...}}这里是找到处理请求的HandlerMethod对象接下来看系统如何初始化所有HandlerMethod初始化HandlerMethodpublicclassRequestMappingHandlerMapping{publicvoidafterPropertiesSet(){//...super.afterPropertiesSet();}}publicabstractclassAbstractHandlerMethodMapping{publicvoidafterPropertiesSet(){initHandlerMethods();}ProtectedvoidinitHand获取容器中的所有beanfor(StringbeanName:getCandidateBeanNames()){if(!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)){processCandidateBean(beanName);}}handlerMethodsInitialized(getHandlerMethods());}protectedvoidprocessCandidateBean(StringbeanName){Class=null;try{//Get相应的ClassbeanType根据BeanName=obtainApplicationContext().getType(beanName);}//...//isHandler方法判断当前类是否满足条件,该方法实现在RequestMappingHandlerMapping//isHandler方法的目的就是判断当前Class是@Controller还是@RequestMapping注解//这样会把所有的@Controller和RequestMap关联起来ping处理程序映射。if(beanType!=null&&isHandler(beanType)){//查找所有HandlerMethoddetectHandlerMethods(beanName);}}protectedvoiddetectHandlerMethods(Objecthandler){ClasshandlerType=(handlerinstanceofString?obtainApplicationContext().getType((String)handler):handler.getClass());if(handlerType!=null){ClassuserType=ClassUtils.getUserClass(handlerType);//查找Class中的所有方法Mapmethods=MethodIntrospector.selectMethods(userType,(MethodIntrospector.MetadataLookup)method->{try{//封装每个符合条件的方法(在方法上使用@RequestMapping注解)//到RequestMappingInfo对象中returnMappingForMethod(method,userType);}//...});methods。forEach((method,mapping)->{MethodinvocableMethod=AopUtils.selectInvocableMethod(method,userType);//注册所有找到的方法并添加到Map中registerHandlerMethod(handler,invocableMethod,mapping);});}}protectedvoidregisterHandlerMethod(Objecthandler,Methodmethod,Tmapping){this.mappingRegistry.register(映射,处理程序,方法);}classMappingRegistry{//T:RequestMappingInfo,handler:string(usersController)Bean名称,method:请求方法对象publicvoidregister(Tmapping,Objecthandler,Methodmethod){//创建HandlerMethod对象HandlerMethodhandlerMethod=createHandlerMethod(handler,method);//...for(Stringpath:directPaths){//缓存上,当请求到来时,会从这个pathLookup集合中查找this.pathLookup.add(path,mapping);}}}}

最新推荐
猜你喜欢