Convention Plugin 学习(三)

[size=small]1.Convention插件的主要实现浅析

1.1 PackageBasedActionConfigBuilder 这个类最重要,是整个程序的入口。
1.1.1 buildActionConfigs方法进行初始化配置,其中findActions扫描类路径,我没有深入研究这个方法具体是怎么找到所有类的。只是找到全部类后,和我们的配置文件中限定的范围匹配、过滤,存入一个set中。然后buildConfiguration(set)循环分析这些类。

1.1.2 buildConfiguration方法,首先创建一个map类型的packageConfigs。键为包(struts2)名,值为PackageConfig.Builder对象,这个对象可以创建PackageConfig对象。
然后循环找到的类,分析包名(java),determineActionNamespace方法分析命名空间,得到一个list对象。
再循环所有命名空间,determineActionName方法分析类名称、类的默认方法(这个是写死在程序中的,就是execute方法)。
getPackageConfig方法分析得到PackageConfig.Builder对象。
getActionAnnotations方法分析得到action类方法的annotation配置。
循环每个方法的配置,调用createActionConfig方法分析,把results,interceptors,exceptionMappings等配置放入ActionConfig.Builder对象,再把ActionConfig对象(由ActionConfig.Builder生成)放入PackageConfig.Builder中。
buildIndexActions创建默认索引action。这个好像用处不大。
最后把PackageConfig对象放入Configuration对象中,这是最顶级的配置。我们在任何时间和地点都可以得到Configuration对象,并对其进行分析。

1.1.3 determineActionNamespace方法是确定一个action类在web应用中的命名空间,先找这个类的Namespace注解,找到后放入一个存储命名空间的list。再找Namespaces注解,一个action可以有多个命名空间。如果有注解则按照注解来确定一个action的命名空间,如果没有,则分析这个action所在包(java)的路径,按照struts2.xml中配置的规则来确定。这个规则就是截取到定义的locator,在这个locator之后的包(java)全部作为命名空间,类名作为action名称。

1.1.4 determineActionName方法是确定一个action类在web应用中的名称。由ActionNameBuilder(接口)的方法来实现,这个接口的具体实现类,插件默认为SEOActionNameBuilder。被称为搜索引擎友好的名称。会把action类的name按单词分解,然后用连接符连起来。默认连接符是"-",我们可以设置为"_"。

1.1.5 getPackageConfig方法是确定一个action类在web应用中的继承的包(struts2)。先找这个类的ParentPackage注解,如果有注解则按照注解来确定一个action的父包(struts2),如果没有,按照struts.xml中配置的规则来确定。这个规则就是defaultParentPackage。得到父包(struts2)后要拼成: actionPackage + "#" + parentPkg.getName() + "#" + actionNamespace 的形式,这是xwork里的规定。

1.1.6 getActionAnnotations方法是确定一个action类的方法上的annotation配置。先找方法的Actions注解,一个方法可以有多个action映射。再找Action注解,放入一个map中,键是方法名,值是存储一组acton映射的list对象。

1.1.7 createActionConfig方法构造ActionConfig.Builder对象,逐一判断interceptors,results,exceptionMappings,都是从类一级开始判断是否有此注解,再从方法的action注解中寻找。InterceptorMapBuilder,ResultMapBuilder是两个接口,提供通过注解构造Interceptor和Result的方法,插件分别提供了默认的实现DefaultInterceptorMapBuilder和DefaultResultMapBuilder。而buildExceptionMappings只是本类中的一个方法。

1.2 DefaultInterceptorMapBuilder
先找action类是否存在InterceptorRefs注解,再看是否存在InterceptorRef注解,再看action注解中是否定义了InterceptorRefs。
还用到了StringTools的createParameterMap方法把注解中的params(形式为{key1,value1,key2,value2,......})转化成一个map。
buildInterceptorList方法利用了xwork中的InterceptorBuilder的一个静态方法constructInterceptorReference把拦截器注入到配置中。
而一个action所继承的父包中的拦截器,或是默认拦截器,并不在这个类中构造。而是由xwork根据包(struts2)的继承关系加载(actionPackage + "#" + parentPkg.getName() + "#" + actionNamespace 这是xwork里规定的形式,已经由PackageBasedActionConfigBuilder 配置)。

1.3 DefaultResultMapBuilder
1.3.1 build方法,确定defaultResultPath,构造包含ResultConfig的map对象,再通过扩展名获得一个包含ResultTypeConfig的map对象。createFromResources方法获得默认返回结果页面,然后查找action注解中的results配置,再找类级别的Results注解,再找类级别的Result注解,相同的肯定会覆盖。createFromAnnotations。

1.3.2 createFromResources方法中使用servletContext.getResourcePaths方法寻找页面。如果struts.xml中配置flatLayout为true则直接找到以命名空间为名称的文件夹,在此文件夹中寻找页面,如果flatLayout为false,则会找到以命名空间为名称的文件夹,再找到此文件夹中的以action名称命名的子文件夹,在这个文件夹中寻找页面。

1.3.3 makeResults方法找默认的返回页面,如果没有路径没有包含resultcode(定义的字符串)的页面,则按默认顺序寻找success,input,error。比如hello_world.jsp文件(flatLayout为true,连接符为"_"),如果没有hello_world_success.jsp,hello_world_input.jsp,hello_world_error.jsp文件,同时"success","input","error",又没有显式的配置,只是作为结果字符串返回,则程序默认会用hello_world.jsp来匹配三种结果。如果结果字符串resultcode是"edit",同时又没有显式的配置,则必会找hello_world_edit.jsp。

1.3.4 createFromAnnotations这个方法就是把注解转换成ResultConfig配置。

1.4 ConventionsServiceImpl
是result配置的辅助类。determineResultPath方法先判断struts.xml文件中的配置,再判断action类的注解中是否有ResultPath,如果有将覆盖struts.xml中配置。
getResultTypesByExtension方法提供一个map对象,默认的result结果返回。

其实通过看这些方法,我们也基本了解了struts2的整个配置过程,非常繁琐,很多的判断确实很耗费资源,使用xml配置也一样。我们也知道所有配置信息都是应用启动时加载,存入map中常驻内存。所以我们应该尽可能减少配置,多使用动态方法调用。

1.5 ConventionUnknownHandler 是UnknownHandler接口的一个实现,用来处理找不到相应配置的情况。在struts2.1的dtd中新增了一个<unknown-handler-stack>元素,可以配置一组handler。
handleUnknownAction方法处理找不到action的情况。这个我感觉用处不大。
handleUnknownResult方法处理找不到result的情况。这个方法可以有很多扩展。比如我想定义一种返回值形式:redirect->xxx.do?ad=12或chain->xxx.do。用这种形式比写注解要方便的多。
handleUnknownActionMethod方法处理找不到action中方法的情况。这个默认没有实现。
[/size]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值