spring源代码解析四.docx

上传人:b****7 文档编号:8805802 上传时间:2023-02-01 格式:DOCX 页数:45 大小:27.45KB
下载 相关 举报
spring源代码解析四.docx_第1页
第1页 / 共45页
spring源代码解析四.docx_第2页
第2页 / 共45页
spring源代码解析四.docx_第3页
第3页 / 共45页
spring源代码解析四.docx_第4页
第4页 / 共45页
spring源代码解析四.docx_第5页
第5页 / 共45页
点击查看更多>>
下载资源
资源描述

spring源代码解析四.docx

《spring源代码解析四.docx》由会员分享,可在线阅读,更多相关《spring源代码解析四.docx(45页珍藏版)》请在冰豆网上搜索。

spring源代码解析四.docx

spring源代码解析四

Spring源代码解析(四):

SpringMVC

2009-08-11(周二)10:

54SpringSpring⁄被围观一共有792个打酱油的路过+下面我们对SpringMVC框架代码进行分析,对于webApplicationContext的相关分析可以参见以前的文档,我们这里着重分析SpringWebMVC框架的实现.我们从分析DispatcherServlet入手:

如转载请注明,转载自:

关注Java[]

本文链接:

-

-

Java代码

//这里是对DispatcherServlet的初始化方法,根据名字我们很方面的看到对各个SpringMVC主要元素的初始化

protectedvoidinitFrameworkServlet()throwsServletException,BeansException{

initMultipartResolver();

initLocaleResolver();

initThemeResolver();

initHandlerMappings();

initHandlerAdapters();

initHandlerExceptionResolvers();

initRequestToViewNameTranslator();

initViewResolvers();

}

//这里是对DispatcherServlet的初始化方法,根据名字我们很方面的看到对各个SpringMVC主要元素的初始化

protectedvoidinitFrameworkServlet()throwsServletException,BeansException{

initMultipartResolver();

initLocaleResolver();

initThemeResolver();

initHandlerMappings();

initHandlerAdapters();

initHandlerExceptionResolvers();

initRequestToViewNameTranslator();

initViewResolvers();

}

看到注解我们知道,这是DispatcherSerlvet的初始化过程,它是在WebApplicationContext已经存在的情况下进行的,也就意味着在初始化它的时候,IOC容器应该已经工作了,这也是我们在web.xml中配置Spring的时候,需要把DispatcherServlet的load-on-startup的属性配置为2的原因。

对于具体的初始化过程,很容易理解,我们拿initHandlerMappings()来看看:

Java代码

privatevoidinitHandlerMappings()throwsBeansException{

if(this.detectAllHandlerMappings){

//这里找到所有在上下文中定义的HandlerMapping,同时把他们排序

//因为在同一个上下文中可以有不止一个handlerMapping,所以我们把他们都载入到一个链里进行维护和管理

MapmatchingBeans=BeanFactoryUtils.beansOfTypeIncludingAncestors(

getWebApplicationContext(),HandlerMapping.class,true,false);

if(!

matchingBeans.isEmpty()){

this.handlerMappings=newArrayList(matchingBeans.values());

//这里通过order属性来对handlerMapping来在list中排序

Collections.sort(this.handlerMappings,newOrderComparator());

}

}

else{

try{

Objecthm=getWebApplicationContext().getBean(HANDLER_MAPPING_BEAN_NAME,HandlerMapping.class);

this.handlerMappings=Collections.singletonList(hm);

}

catch(NoSuchBeanDefinitionExceptionex){

//Ignore,we'lladdadefaultHandlerMappinglater.

}

}

//如果在上下文中没有定义的话,那么我们使用默认的BeanNameUrlHandlerMapping

if(this.handlerMappings==null){

this.handlerMappings=getDefaultStrategies(HandlerMapping.class);

……..

}

}

privatevoidinitHandlerMappings()throwsBeansException{

if(this.detectAllHandlerMappings){

//这里找到所有在上下文中定义的HandlerMapping,同时把他们排序

//因为在同一个上下文中可以有不止一个handlerMapping,所以我们把他们都载入到一个链里进行维护和管理

MapmatchingBeans=BeanFactoryUtils.beansOfTypeIncludingAncestors(

getWebApplicationContext(),HandlerMapping.class,true,false);

if(!

matchingBeans.isEmpty()){

this.handlerMappings=newArrayList(matchingBeans.values());

//这里通过order属性来对handlerMapping来在list中排序

Collections.sort(this.handlerMappings,newOrderComparator());

}

}

else{

try{

Objecthm=getWebApplicationContext().getBean(HANDLER_MAPPING_BEAN_NAME,HandlerMapping.class);

this.handlerMappings=Collections.singletonList(hm);

}

catch(NoSuchBeanDefinitionExceptionex){

//Ignore,we'lladdadefaultHandlerMappinglater.

}

}

//如果在上下文中没有定义的话,那么我们使用默认的BeanNameUrlHandlerMapping

if(this.handlerMappings==null){

this.handlerMappings=getDefaultStrategies(HandlerMapping.class);

........

}

}

怎样获得上下文环境,可以参见我们前面的对IOC容器在web环境中加载的分析。

DispatcherServlet把定义了的所有HandlerMapping都加载了放在一个List里待以后进行使用,这个链的每一个元素都是一个handlerMapping的配置,而一般每一个handlerMapping可以持有一系列从URL请求到SpringController的映射,比如SimpleUrl

HandlerMaaping中就定义了一个map来持有这一系列的映射关系。

DisptcherServlet通过HandlerMapping使得Web应用程序确定一个执行路径,就像我们在HanderMapping中看到的那样,HandlerMapping只是一个借口:

Java代码

publicinterfaceHandlerMapping{

publicstaticfinalStringPATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE=

Conventions.getQualifiedAttributeName(HandlerMapping.class,"pathWithinHandlerMapping");

//实际上维护一个HandlerExecutionChain,这是典型的Command的模式的使用,这个执行链里面维护handler和拦截器

HandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException;

}

publicinterfaceHandlerMapping{

publicstaticfinalStringPATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE=

Conventions.getQualifiedAttributeName(HandlerMapping.class,"pathWithinHandlerMapping");

//实际上维护一个HandlerExecutionChain,这是典型的Command的模式的使用,这个执行链里面维护handler和拦截器

HandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException;

}

他的具体实现只需要实现一个接口方法,而这个接口方法返回的是一个HandlerExecutionChain,实际上就是一个执行链,就像在Command模式描述的那样,这个类很简单,就是一个持有一个Interceptor链和一个Controller:

Java代码

publicclassHandlerExecutionChain{

privateObjecthandler;

privateHandlerInterceptor[]interceptors;

……..

}

publicclassHandlerExecutionChain{

privateObjecthandler;

privateHandlerInterceptor[]interceptors;

........

}

而这些Handler和Interceptor需要我们定义HandlerMapping的时候配置好,比如对具体的SimpleURLHandlerMapping,他要做的就是根据URL映射的方式注册Handler和Interceptor,自己维护一个放映映射的handlerMap,当需要匹配Http请求的时候需要使用这个表里的信息来得到执行链。

这个注册的过程在IOC容器初始化SimpleUrlHandlerMapping的时候就被完成了,这样以后的解析才可以用到map里的映射信息,这里的信息和bean文件的信息是等价的,下面是具体的注册过程:

Java代码

protectedvoidregisterHandlers(MapurlMap)throwsBeansException{

if(urlMap.isEmpty()){

logger.warn("Neither'urlMap'nor'mappings'setonSimpleUrlHandlerMapping");

}

else{

//这里迭代在SimpleUrlHandlerMapping中定义的所有映射元素

Iteratorit=urlMap.keySet().iterator();

while(it.hasNext()){

//这里取得配置的url

Stringurl=(String)it.next();

//这里根据url在bean定义中取得对应的handler

Objecthandler=urlMap.get(url);

//Prependwithslashifnotalreadypresent.

if(!

url.startsWith("/")){

url="/"+url;

}

//这里调用AbstractHandlerMapping中的注册过程

registerHandler(url,handler);

}

}

}

protectedvoidregisterHandlers(MapurlMap)throwsBeansException{

if(urlMap.isEmpty()){

logger.warn("Neither'urlMap'nor'mappings'setonSimpleUrlHandlerMapping");

}

else{

//这里迭代在SimpleUrlHandlerMapping中定义的所有映射元素

Iteratorit=urlMap.keySet().iterator();

while(it.hasNext()){

//这里取得配置的url

Stringurl=(String)it.next();

//这里根据url在bean定义中取得对应的handler

Objecthandler=urlMap.get(url);

//Prependwithslashifnotalreadypresent.

if(!

url.startsWith("/")){

url="/"+url;

}

//这里调用AbstractHandlerMapping中的注册过程

registerHandler(url,handler);

}

}

}

在AbstractMappingHandler中的注册代码:

Java代码

protectedvoidregisterHandler(StringurlPath,Objecthandler)throwsBeansException,IllegalStateException{

//试图从handlerMap中取handler,看看是否已经存在同样的Url映射关系

ObjectmappedHandler=this.handlerMap.get(urlPath);

if(mappedHandler!

=null){

……..

}

//如果是直接用bean名做映射那就直接从容器中取handler

if(!

this.lazyInitHandlers&&handlerinstanceofString){

StringhandlerName=(String)handler;

if(getApplicationContext().isSingleton(handlerName)){

handler=getApplicationContext().getBean(handlerName);

}

}

//或者使用默认的handler.

if(urlPath.equals("/*")){

setDefaultHandler(handler);

}

else{

//把url和handler的对应关系放到handlerMap中去

this.handlerMap.put(urlPath,handler);

……..

}

}

protectedvoidregisterHandler(StringurlPath,Objecthandler)throwsBeansException,IllegalStateException{

//试图从handlerMap中取handler,看看是否已经存在同样的Url映射关系

ObjectmappedHandler=this.handlerMap.get(urlPath);

if(mappedHandler!

=null){

........

}

//如果是直接用bean名做映射那就直接从容器中取handler

if(!

this.lazyInitHandlers&&handlerinstanceofString){

StringhandlerName=(String)handler;

if(getApplicationContext().isSingleton(handlerName)){

handler=getApplicationContext().getBean(handlerName);

}

}

//或者使用默认的handler.

if(urlPath.equals("/*")){

setDefaultHandler(handler);

}

else{

//把url和handler的对应关系放到handlerMap中去

this.handlerMap.put(urlPath,handler);

........

}

}

handlerMap是持有的一个HashMap,里面就保存了具体的映射信息:

Java代码

privatefinalMaphandlerMap=newHashMap();

privatefinalMaphandlerMap=newHashMap();

而SimpleUrlHandlerMapping对接口HandlerMapping的实现是这样的,这个getHandler根据在初始化的时候就得到的映射表来生成DispatcherServlet需要的执行链

Java代码

publicfinalHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{

//这里根据request中的参数得到其对应的handler,具体处理在AbstractUrlHandlerMapping中

Objecthandler=getHandlerInternal(request);

//如果找不到对应的,就使用缺省的handler

if(handler==null){

handler=this.defaultHandler;

}

//如果缺省的也没有,那就没办法了

if(handler==null){

returnnull;

}

//如果handler不是一个具体的handler,那我们还要到上下文中取

if(handlerinstanceofString){

StringhandlerName=(String)handler;

handler=getApplicationContext().getBean(handlerName);

}

//生成一个HandlerExecutionChain,其中放了我们匹配上的handler和定义好的拦截器,就像我们在HandlerExecutionChain中看到的那样,它持有一个handler和一个拦截器组。

returnnewHandlerExecutionChain(handler,this.adaptedInterceptors);

}

publicfinalHandlerExecutionChaingetHandler(HttpServletRequestrequest)throwsException{

//这里根据request中的参数得到其对应的handler,具体处理在AbstractUrlHandlerMapping中

Objecthandler=getHandlerInternal(request);

//如果找不到对应的,就使用缺省的handler

if(handler==null){

handler=this.defaultHandler;

}

//如果缺省的也没有,那就没办法了

if(handler==null){

returnnull;

}

//如果handler不是一个具体的handler,那我们还要到上下文中取

if(handlerinstanceofString){

StringhandlerName=(String)handler;

handler=getApplicationContext().getBean(handlerName);

}

//生成一个HandlerExecutionChain,其中放了我们匹配上的handler和定义好的拦截器,就像我们在HandlerExecutionChain中看到的那样,它持有一个handler和一个拦截器组。

returnnewHandlerExecutionChain(handler,this.adaptedInterceptors);

}

我们看看具体的handler查找过程:

Java代码

protectedObjectgetHandlerInternal(HttpServletRequestrequest)throwsException{

//这里的HTTPRequest传进来的参数进行分析,得到具体的路径信息。

StringlookupPath=this.urlPathHelper.getLookupPathForRequest(request);

…….//下面是根据请求信息的查找

returnlookupHandler(lookupPath,request);

}

protectedObjectlookupHandler(StringurlPath,HttpServletRequestrequest){

//如果能够直接能在SimpleUrlHandlerMapping的映射表中找到,那最好。

Objecthandler=

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 其它课程

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1