最近一直在编写基于IOC与AOP的web开发框架,有点模仿spring的意思。IOC部分已经差不多了,正在编写persistence部分。目前所在的公司,初来乍到,而且公司软件方面以前没有积累,没有能直接使用的开发框架,可是现在项目情况有变,可能留给我自己编写框架的时间不是太够,为了以防万一,先来套Struts2,spring3,hibernate的整合框架用用,于是开始抽时间搭建。网上查了一些搭建配置的文章,但是都是简单的拼凑在一起就完事了,没有深度的集成。 下面就将我在集成的过程中的一些关键的问题的解决,介绍一下。

Struts2 在集成的时候,配置文件大多是放置在src的根目录下就完了。这样很简单。但是无法按照自己工程的结构,进行设计调整。而且也违反了我个人自己多年的习惯。所以第一步将struts的配置放到webapp(上下文)下面的config目录里。web.xml进行如下配置。

 
  1. <filter> 
  2.         <filter-name>struts2</filter-name> 
  3.         <filter-class>com.xk.commons.config.GeneralConfigFilter</filter-class> 
  4.         <init-param> 
  5.         <param-name>configProviders</param-name> 
  6.         <param-value>com.xk.commons.config.Struts2ConfigurationProvider</param-value> 
  7.        </init-param> 
  8.     </filter> 
  9.     <filter-mapping> 
  10.         <filter-name>struts2</filter-name> 
  11.         <url-pattern>/*</url-pattern> 
  12.     </filter-mapping> 

 Struts2ConfigurationProvider 这个类是继承了StrutsXmlConfigurationProvider,顾名思义,此类是用来提供xml格式的配置用的。查看类的各种方法,个人理解,只要实现了类的getConfigurationUrls方法,返回的是你自己的配置文件的url就能够修改默认配置了。于是实现代码如下:

 
  1. public class Struts2ConfigurationProvider extends StrutsXmlConfigurationProvider  
  2. {  
  3.     private static final String CONFIG_FILE = "struts.xml";  
  4.       
  5.     private static Logger logger = LoggerFactory.getLogger(Struts2ConfigurationProvider.class);  
  6.       
  7.     public Struts2ConfigurationProvider()  
  8.     {  
  9.         this(false);  
  10.     }  
  11.  
  12.     public Struts2ConfigurationProvider(boolean errorIfMissing)  
  13.     {  
  14.         super(CONFIG_FILE, errorIfMissing, null);  
  15.     }  
  16.  
  17.     @Override 
  18.     protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException  
  19.     {  
  20.         logger.info("get struts config file : " + fileName);  
  21.         return PathUtils.getStrutsConfigIterator(fileName);  
  22.     }  

 

 

编写这个类的时候有点问题,在这里提一下,如果不提供默认无参构造器,在启动工程的时候会报错误,

 
其实这个错误发生的原因就是在实例化这个类的时候,找不到无参构造器。同样方式,在工程外测试用例测试不会出这样的问题,仅限于struts2工程内部,不太明白为什么,没找到原因,总之,将无参构造器加上,问题解决。 但是工程启动后,好像无论如何加载不到我自己的配置。于是乎仔细读源码,发现Dispatcher类中的init_CustomConfigurationProviders方法是装载加载自定义配置的地方,其实看上面那个错误信息也大概知道地方了。发现虽然自己的Provider类是被实例化了,但是没有被被加到ConfigurationManager中,再进一步查看,发现ConfigurationManager中的CopyOnWriteArrayList中已经存在要加入的对象了,因为加入的时候会通过实例的equals进行比较。查看相同的对象,发现一个是XmlConfigurationProvider,一个是我自己定义的Struts2ConfigurationProvider,晕了,明明是两个不同的类实例化出的对象,怎么就能equals为true呢? 想了办法,突然茅塞顿开,如果两个不同的类的实例比较结果是一一样的,那么只有一种可能,就是hashcode方法被重写了。因为equals比较的就是两个实例的hashcode,没错,查看XmlConfigurationProvider的方法,其中果然有hashcode方法,而方法实现又极其简单。
 
  1. @Override 
  2.    public int hashCode() {  
  3.        return ((configFileName != null) ? configFileName.hashCode() : 0);  
  4.    } 

看吧,只要你通过参数传递的配置文件名与struts2中默认的名字是一样的,那么hashcode就是一样的。,虽然不知道struts的开发者这样设计的目的,但是肯定是有原因的,也罢,将我自己定义的provider中的struts配置文件名字改了一下,既然自定义吗,那配置文件名称也要自定义哦。 一些都ok了, 在配置里写个简单的Action,测试通过。