首页>>后端>>SpringBoot->SpringBoot中的Controller详解

SpringBoot中的Controller详解

时间:2023-11-30 本站 点击:0

SpringBoot中的Controller注册

本篇将会以Servlet为切入点,通过源码来看web容器中的Controller是如何注册到HandlerMapping中。请求来了之后,web容器是如何根据请求路径找到对应的Controller方法并执行的。

先讲下本文的大概思路和流程图:

我们经常使用的RequestMapping这个注解对应的方法最终会被RequestMappingHandlerMapping处理,并封装成一个HandlerMethod注入到自己内部的mappingRegistry 容器中。这一步是Controller的注册,被执行的触发点是因为RequestMappingHandlerMapping这个类实现了InitializingBean接口,由Spring容器触发。

tomcat容器被启动的时候,最后会调用Servlet的init方法,这里会把所有的HandlerMapping注册到自己内部的handlerMappings属性中。这样Servlet和RequestMapping注解的Controller就建立起了间接关系。

当请求到来的时候,tomcat拿到并封装好请求体后会调用Servlet的service方法。这个方法最终会走到 DispatcherServletdoDispatch方法,这个方法中会找到最适合的HandlerMapping并取出对应的HadlerMethod,然后给对应的HandlerAdapter执行.

controller注册流程图

controller发现和使用流程图 正文开始

处理请求的DispatcherServlet

Servlet接口的源码

publicinterfaceServlet{//初始化publicvoidinit(ServletConfigconfig)throwsServletException;//响应请求publicvoidservice(ServletRequestreq,ServletResponseres)throwsServletException,IOException;//获取servlet信息publicStringgetServletInfo();//服务停止时回调publicvoiddestroy();}

springboot内置了tomcat容器,而tomcat容器是遵循了servlet规范的。servlet规范中定义了初始化、响应、获取配置信息和销毁时回调钩子。从servlet的规范中可以看出,tomcat启动时会调用servlet的init方法,处理请求时会调用service方法,容器销毁时会调用destroy方法。servlet中最核心的实现就是我们所熟知的DispatchServlet,看下DispatchServlet的继承体系

从DispatchServlet的继承体系中,看下Servlet的初始化做了什么。

Servlet的初始化 init

HttpServletBean中的init方法源码

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}

从HttpServletBean中的init方法可以看到,这里核心的就是设置了Servlet的一些 bean properties,继续到子类 FrameworkServlet中看initServletBean方法

@OverrideprotectedfinalvoidinitServletBean()throwsServletException{getServletContext().log("InitializingSpring"+getClass().getSimpleName()+"'"+getServletName()+"'");if(logger.isInfoEnabled()){logger.info("InitializingServlet'"+getServletName()+"'");}longstartTime=System.currentTimeMillis();try{//这里初始化了web的上下文,这里会初始化Servlet的九大策略this.webApplicationContext=initWebApplicationContext();//这个方法也是空实现initFrameworkServlet();}catch(ServletException|RuntimeExceptionex){logger.error("Contextinitializationfailed",ex);throwex;}if(logger.isDebugEnabled()){Stringvalue=this.enableLoggingRequestDetails?"shownwhichmayleadtounsafeloggingofpotentiallysensitivedata":"maskedtopreventunsafeloggingofpotentiallysensitivedata";logger.debug("enableLoggingRequestDetails='"+this.enableLoggingRequestDetails+"':requestparametersandheaderswillbe"+value);}if(logger.isInfoEnabled()){logger.info("Completedinitializationin"+(System.currentTimeMillis()-startTime)+"ms");}}//初始化上下文protectedWebApplicationContextinitWebApplicationContext(){WebApplicationContextrootContext=WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContextwac=null;if(this.webApplicationContext!=null){wac=this.webApplicationContext;if(wacinstanceofConfigurableWebApplicationContext){ConfigurableWebApplicationContextcwac=(ConfigurableWebApplicationContext)wac;if(!cwac.isActive()){if(cwac.getParent()==null){cwac.setParent(rootContext);}configureAndRefreshWebApplicationContext(cwac);}}}if(wac==null){wac=findWebApplicationContext();}if(wac==null){wac=createWebApplicationContext(rootContext);}if(!this.refreshEventReceived){synchronized(this.onRefreshMonitor){//springboot只会进入这个方法,这个方法是空实现,具体实现在子类DispatchServletonRefresh(wac);}}if(this.publishContext){StringattrName=getServletContextAttributeName();getServletContext().setAttribute(attrName,wac);}returnwac;}

接着跟进DispatchServlet的onRefresh方法,这个方法中会初始化DispatchServlet的九大策略,这里我们只关心initHandlerMappings方法

@OverrideprotectedvoidonRefresh(ApplicationContextcontext){initStrategies(context);}//初始化策略protectedvoidinitStrategies(ApplicationContextcontext){initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);//这个是我们关注的核心,Controller注册就在这里实现initHandlerMappings(context);//这个是处理Controller方法调用的,逻辑跟上面的initHandlerMappings差不多initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);}

核心看下initHandlerMappings方法

privatevoidinitHandlerMappings(ApplicationContextcontext){this.handlerMappings=null;//默认为trueif(this.detectAllHandlerMappings){//默认的HandlerMapping有8个,这里我们只关心RequestMappingHandlerMapping这个类Map<String,HandlerMapping>matchingBeans=BeanFactoryUtils.beansOfTypeIncludingAncestors(context,HandlerMapping.class,true,false);if(!matchingBeans.isEmpty()){this.handlerMappings=newArrayList<>(matchingBeans.values());//排序AnnotationAwareOrderComparator.sort(this.handlerMappings);}}else{try{HandlerMappinghm=context.getBean(HANDLER_MAPPING_BEAN_NAME,HandlerMapping.class);//这里就让Serlvet和Controller建立起了间接关系了,这个方法主要是为了给handlerMappings属性赋值this.handlerMappings=Collections.singletonList(hm);}catch(NoSuchBeanDefinitionExceptionex){}}//这里如果没有HanlderMapping的话,会给一个默认的处理if(this.handlerMappings==null){this.handlerMappings=getDefaultStrategies(context,HandlerMapping.class);if(logger.isTraceEnabled()){logger.trace("NoHandlerMappingsdeclaredforservlet'"+getServletName()+"':usingdefaultstrategiesfromDispatcherServlet.properties");}}}

看下默认的 HandlerMapping 有哪些

这里我们只关心RequestMappingHandlerMapping这个类,这个类就是处理我们Controller上的RequestMapping注解的类。

注意这里的handlerMappings,后面处理请求的时候,会从handlerMappings中选择一个最合适的HandlerMapping来处理请求

Servlet的请求处理 service

HttpServlet中的service方法源码

/***这个方法只是将ServletRequest强转为HttpServletRequest*ServletResponse强转为HttpServletResponse*/@Overridepublicvoidservice(ServletRequestreq,ServletResponseres)throwsServletException,IOException{HttpServletRequestrequest;HttpServletResponseresponse;try{request=(HttpServletRequest)req;response=(HttpServletResponse)res;}catch(ClassCastExceptione){thrownewServletException(lStrings.getString("http.non_http"));}//接着看这个service(request,response);}protectedvoidservice(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{//获取方法类型Stringmethod=req.getMethod();//根据不同的方法类型调用不同的方法,从doGet进去,看子类FrameworkServlet的doGet方法if(method.equals(METHOD_GET)){longlastModified=getLastModified(req);if(lastModified==-1){doGet(req,resp);}else{longifModifiedSince;try{ifModifiedSince=req.getDateHeader(HEADER_IFMODSINCE);}catch(IllegalArgumentExceptioniae){ifModifiedSince=-1;}if(ifModifiedSince<(lastModified/1000*1000)){maybeSetLastModified(resp,lastModified);doGet(req,resp);}else{resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);}}}elseif(method.equals(METHOD_HEAD)){longlastModified=getLastModified(req);maybeSetLastModified(resp,lastModified);doHead(req,resp);}elseif(method.equals(METHOD_POST)){doPost(req,resp);}elseif(method.equals(METHOD_PUT)){doPut(req,resp);}elseif(method.equals(METHOD_DELETE)){doDelete(req,resp);}elseif(method.equals(METHOD_OPTIONS)){doOptions(req,resp);}elseif(method.equals(METHOD_TRACE)){doTrace(req,resp);}else{StringerrMsg=lStrings.getString("http.method_not_implemented");Object[]errArgs=newObject[1];errArgs[0]=method;errMsg=MessageFormat.format(errMsg,errArgs);resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED,errMsg);}}//FrameworkServlet的doGet方法@OverrideprotectedfinalvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{//继续跟processRequest(request,response);}rotectedfinalvoidprocessRequest(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{longstartTime=System.currentTimeMillis();ThrowablefailureCause=null;LocaleContextpreviousLocaleContext=LocaleContextHolder.getLocaleContext();LocaleContextlocaleContext=buildLocaleContext(request);RequestAttributespreviousAttributes=RequestContextHolder.getRequestAttributes();ServletRequestAttributesrequestAttributes=buildRequestAttributes(request,response,previousAttributes);WebAsyncManagerasyncManager=WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(),newRequestBindingInterceptor());initContextHolders(request,localeContext,requestAttributes);try{//这里处理请求,继续跟,看子类DispatchServlet的doService方法doService(request,response);}catch(ServletException|IOExceptionex){failureCause=ex;throwex;}catch(Throwableex){failureCause=ex;thrownewNestedServletException("Requestprocessingfailed",ex);}finally{resetContextHolders(request,previousLocaleContext,previousAttributes);if(requestAttributes!=null){requestAttributes.requestCompleted();}logResult(request,response,failureCause,asyncManager);publishRequestHandledEvent(request,response,startTime,failureCause);}}

DispatchServlet的doService方法

@OverrideprotectedvoiddoService(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{//打印日志logRequest(request);//保存快照Map<String,Object>attributesSnapshot=null;if(WebUtils.isIncludeRequest(request)){attributesSnapshot=newHashMap<>();Enumeration<?>attrNames=request.getAttributeNames();while(attrNames.hasMoreElements()){StringattrName=(String)attrNames.nextElement();if(this.cleanupAfterInclude||attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)){attributesSnapshot.put(attrName,request.getAttribute(attrName));}}}//设置属性request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE,this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE,this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE,getThemeSource());if(this.flashMapManager!=null){FlashMapinputFlashMap=this.flashMapManager.retrieveAndUpdate(request,response);if(inputFlashMap!=null){request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE,Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE,newFlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE,this.flashMapManager);}try{//处理请求核心方法doDispatch(request,response);}finally{if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()){if(attributesSnapshot!=null){restoreAttributesAfterInclude(request,attributesSnapshot);}}}}

DispatchServlet的doDispatch方法

protectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{HttpServletRequestprocessedRequest=request;HandlerExecutionChainmappedHandler=null;booleanmultipartRequestParsed=false;WebAsyncManagerasyncManager=WebAsyncUtils.getAsyncManager(request);try{ModelAndViewmv=null;ExceptiondispatchException=null;try{processedRequest=checkMultipart(request);multipartRequestParsed=(processedRequest!=request);//获取当前请求的handlermappedHandler=getHandler(processedRequest);if(mappedHandler==null){//404noHandlerFound(processedRequest,response);return;}//获取处理当前请求的handlerAdapterHandlerAdapterha=getHandlerAdapter(mappedHandler.getHandler());Stringmethod=request.getMethod();booleanisGet="GET".equals(method);if(isGet||"HEAD".equals(method)){longlastModified=ha.getLastModified(request,mappedHandler.getHandler());if(newServletWebRequest(request,response).checkNotModified(lastModified)&&isGet){return;}}//调用前置拦截器if(!mappedHandler.applyPreHandle(processedRequest,response)){return;}//请求对应的方法在这里被执行mv=ha.handle(processedRequest,response,mappedHandler.getHandler());if(asyncManager.isConcurrentHandlingStarted()){return;}applyDefaultViewName(processedRequest,mv);//调用后置拦截器mappedHandler.applyPostHandle(processedRequest,response,mv);}catch(Exceptionex){dispatchException=ex;}catch(Throwableerr){//Asof4.3,we'reprocessingErrorsthrownfromhandlermethodsaswell,//makingthemavailablefor@ExceptionHandlermethodsandotherscenarios.dispatchException=newNestedServletException("Handlerdispatchfailed",err);}processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException);}catch(Exceptionex){triggerAfterCompletion(processedRequest,response,mappedHandler,ex);}catch(Throwableerr){triggerAfterCompletion(processedRequest,response,mappedHandler,newNestedServletException("Handlerprocessingfailed",err));}finally{if(asyncManager.isConcurrentHandlingStarted()){//InsteadofpostHandleandafterCompletionif(mappedHandler!=null){mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest,response);}}else{//Cleanupanyresourcesusedbyamultipartrequest.if(multipartRequestParsed){cleanupMultipart(processedRequest);}}}}@NullableprotectedHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{if(this.handlerMappings!=null){for(HandlerMappingmapping:this.handlerMappings){//这里的mapping就是接下来要讲到的RequestMappingHandlerMappingHandlerExecutionChainhandler=mapping.getHandler(request);if(handler!=null){returnhandler;}}}returnnull;}

这里可以记录Servlet处理请求的调用链 service -> doGet -> processRequest -> doService -> doDispatch

RequestMappingHandlerMapping 做了啥

从上面的继承图可以看出RequestMappingHandlerMapping实现了InitializingBean接口,所以初始化的时候会调用afterPropertiesSet方法。

@Override@SuppressWarnings("deprecation")publicvoidafterPropertiesSet(){//配置this.config=newRequestMappingInfo.BuilderConfiguration();this.config.setUrlPathHelper(getUrlPathHelper());this.config.setPathMatcher(getPathMatcher());this.config.setSuffixPatternMatch(useSuffixPatternMatch());this.config.setTrailingSlashMatch(useTrailingSlashMatch());this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());this.config.setContentNegotiationManager(getContentNegotiationManager());//这里是核心,会把所有controller注册进去super.afterPropertiesSet();}

接着看父类AbstractHandlerMethodMapping的afterPropertiesSet方法

@OverridepublicvoidafterPropertiesSet(){initHandlerMethods();}protectedvoidinitHandlerMethods(){for(StringbeanName:getCandidateBeanNames()){if(!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)){//这里会注册controllerprocessCandidateBean(beanName);}}handlerMethodsInitialized(getHandlerMethods());}protectedvoidprocessCandidateBean(StringbeanName){Class<?>beanType=null;try{beanType=obtainApplicationContext().getType(beanName);}catch(Throwableex){if(logger.isTraceEnabled()){logger.trace("Couldnotresolvetypeforbean'"+beanName+"'",ex);}}//这里的isHandler会判断是否有Controller或RequestMapping注解if(beanType!=null&&isHandler(beanType)){//这里会注册controller,接着跟detectHandlerMethods(beanName);}}protectedvoiddetectHandlerMethods(Objecthandler){//获取类型Class<?>handlerType=(handlerinstanceofString?obtainApplicationContext().getType((String)handler):handler.getClass());if(handlerType!=null){Class<?>userType=ClassUtils.getUserClass(handlerType);Map<Method,T>methods=MethodIntrospector.selectMethods(userType,(MethodIntrospector.MetadataLookup<T>)method->{try{//这里会把RequestMapping转换为RequestMappingInforeturngetMappingForMethod(method,userType);}catch(Throwableex){thrownewIllegalStateException("Invalidmappingonhandlerclass["+userType.getName()+"]:"+method,ex);}});if(logger.isTraceEnabled()){logger.trace(formatMappings(userType,methods));}methods.forEach((method,mapping)->{MethodinvocableMethod=AopUtils.selectInvocableMethod(method,userType);//注册到mappingRegistry中,后面会根据request获取对应的HandlerMethodregisterHandlerMethod(handler,invocableMethod,mapping);});}}

RequestMapping转换为RequestMappingInfo

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}0

这个方法会把方法上的RequestMapping转换为RequestMappingInfo,把类上的RequestMapping转换为RequestMappingInfo,然后再把两个RequestMappingInfo合并成一个(url的合并)。

HandlerMethod的注册

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}1

这里需要注意的是,注册的Controller是直接注册的HandlerMethod,这个HandlerMethod就是对应的Controller类中具体请求对应的方法,这个对象封装了所有信息,后面获取出HandlerMethod后会通过反射调用具体的方法

进入RequestMappingHandlerMapping的getHandler方法看下,这个方法在父类AbstractHandlerMapping中实现,这里用到了设计模式中的模版方法。

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}2

这里核心关注两个方法,一个是获取处理器的getHandlerInternal方法,一个是获取对应拦截器链的getHandlerExecutionChain方法

AbstractHandlerMethodMapping的getHandlerInternal方法

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}3

从上面的方法中可以看出,最后是从mappingRegistry属性中取出的HandlerMethod,mappingRegistry在上面的RequestMappingHandlerMapping中有详细讲解

AbstractHandlerMapping的getHandlerExecutionChain方法

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}4

到这就已经拿到了对应的拦截器链和响应请求对应的方法了。接下来就是调用方法了,这里就轮到HandlerAdapter出场了,如何获取RequestMappingHandlerAdapter的方法getHandlerAdapter这里就跳过了

再回到DispatchServlet的doDispatch方法中的

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}5

RequestMappingHandlerAdapter类的handleInternal方法

@Overridepublicfinalvoidinit()throwsServletException{//设置servlet的属性PropertyValuespvs=newServletConfigPropertyValues(getServletConfig(),this.requiredProperties);if(!pvs.isEmpty()){try{BeanWrapperbw=PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoaderresourceLoader=newServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class,newResourceEditor(resourceLoader,getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs,true);}catch(BeansExceptionex){if(logger.isErrorEnabled()){logger.error("Failedtosetbeanpropertiesonservlet'"+getServletName()+"'",ex);}throwex;}}//具体的初始化方法交给子类实现initServletBean();}//空实现,具体的由子类实现protectedvoidinitServletBean()throwsServletException{}6

到这里,整个调用的过程就已经到此为止了。其中的HandlerAdapter的注册、获取、处理请求反射调用HandlerMethod等以后的章节再分析。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/SpringBoot/4400.html