Struts2配置文件全路径搜索的实现
2013-08-02 17:48
357 查看
我们在使用Struts2的时候,相关Action的配置文件(一般以struts.xml作为配置文件),Struts2的StrutsPrepareAndExecuteFilter过滤器会到工程类路径(WEB-INF/classes目录下)找此配置文件。
这样,在类路径下有很多的xml配置文件,不便于维护,我们一般会将自定义的struts.xml放到特别的目录下,比如放到WEB-INF/conf目录下。此时,我们在web.xml里的struts过滤器会这样配置:
之后,如果要加更多的struts配置,可以以这样的方式配置config对应的配置文件值,也可以在struts.xml中,以include标签配置额外的配置文件:
可以看出来,这样配置起来,要么struts.xml里,充斥大量的Action配置,要么就充斥很多include标签。而且还需要关注各种路径问题(尤其是,如果我们需要按照Action类的包路径关系,在config目录下也按照包路径创建文件夹,将相应的struts配置文件放到对应包下时,路径问题会令人头晕)。
对此,我们可以考虑能否从过滤器初始化配置文件的处理机制上,进行改进,来实现无需额外配置,让过滤器自动“搜索”struts配置文件。
我们先来说明一种配置文件的放置方式。在每一个Action类的包下,创建一个conf目录,专门放struts.xml配置文件。这样,我们的action类与配置文件在一起管理,十分灵活方便。接下来就是如何实现全路径搜索struts配置文件的问题了。
首先要分析下,StrutsPrepareAndExecuteFilter过滤器如何实现配置文件查找的。经分析,在org/apache/struts2/dispatcher/ng/InitOperations.java类createDispatcher方法中,做了路径查找工作。这里可以看下createDispatcher方法的实现,具体调用关系请参阅相关源码:
这里会将struts的配置文件以“,”分隔放到一个字符串中,封装到params这个Map中。
在这里,我们考虑在return操作之前,再做个全路径搜索,将其他struts.xml配置文件的全路径拼装到配置文件字符串中。直接修改InitOperations.java类的方式不利于lib库的管理,因此考虑使用继承的手段,重写StrutsPrepareAndExecuteFilter过滤器init方法,和InitOperations.java类的createDispatcher方法。
继承InitOperations的类(不妨命名为MyInitOperations),覆盖private Dispatcher createDispatcher( HostConfig filterConfig )方法,参考实现如下:
StrutsPrepareAndExecuteFilter类init方法源码如下:
继承类(假设为MyStrutsPrepareAndExecuteFilter)重写此方法,InitOperations init = new InitOperations();操作改为MyInitOperations init = new MyInitOperations();即可。
这里有几点使用说明:
1. web.xml的struts核心过滤器需配置为MyStrutsPrepareAndExecuteFilter这个继承类;
2. struts配置文件必须以"struts.xml"结尾,用以区分其它配置文件;
3. 只要绝对路径不同,配置文件使用相同的文件名(如,都以"struts.xml"作为配置文件名)没有影响;
4. 配置文件在类加载路径即其子路径下,都可以解析得到;
5. 若需要解析非类加载路径目录,需要参考此方式,根据相对路径思想,得到新的目录file,再次调用getStrutsPath(File file, StringBuilder pathBuilder)方法即可。
使用继承和全路径遍历的思想来实现,看起来还是比较简单易懂的。这样,我们的类加载路径下,全路径搜索struts配置文件就实现了。
这样,在类路径下有很多的xml配置文件,不便于维护,我们一般会将自定义的struts.xml放到特别的目录下,比如放到WEB-INF/conf目录下。此时,我们在web.xml里的struts过滤器会这样配置:
<!-- 定义Struts2的核心Filter --> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> <init-param> <param-name>config</param-name> <param-value>struts-default.xml,struts-plugin.xml,../conf/struts.xml</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
之后,如果要加更多的struts配置,可以以这样的方式配置config对应的配置文件值,也可以在struts.xml中,以include标签配置额外的配置文件:
<struts> <include file="../conf/other-struts.xml"/><!--注意:这里也是相对类路径配置--> ... </struts>
可以看出来,这样配置起来,要么struts.xml里,充斥大量的Action配置,要么就充斥很多include标签。而且还需要关注各种路径问题(尤其是,如果我们需要按照Action类的包路径关系,在config目录下也按照包路径创建文件夹,将相应的struts配置文件放到对应包下时,路径问题会令人头晕)。
对此,我们可以考虑能否从过滤器初始化配置文件的处理机制上,进行改进,来实现无需额外配置,让过滤器自动“搜索”struts配置文件。
我们先来说明一种配置文件的放置方式。在每一个Action类的包下,创建一个conf目录,专门放struts.xml配置文件。这样,我们的action类与配置文件在一起管理,十分灵活方便。接下来就是如何实现全路径搜索struts配置文件的问题了。
首先要分析下,StrutsPrepareAndExecuteFilter过滤器如何实现配置文件查找的。经分析,在org/apache/struts2/dispatcher/ng/InitOperations.java类createDispatcher方法中,做了路径查找工作。这里可以看下createDispatcher方法的实现,具体调用关系请参阅相关源码:
/** * Create a {@link Dispatcher} */ private Dispatcher createDispatcher( HostConfig filterConfig ) { Map<String, String> params = new HashMap<String, String>(); for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) { String name = (String) e.next(); String value = filterConfig.getInitParameter(name); params.put(name, value); } return new Dispatcher(filterConfig.getServletContext(), params); }
这里会将struts的配置文件以“,”分隔放到一个字符串中,封装到params这个Map中。
在这里,我们考虑在return操作之前,再做个全路径搜索,将其他struts.xml配置文件的全路径拼装到配置文件字符串中。直接修改InitOperations.java类的方式不利于lib库的管理,因此考虑使用继承的手段,重写StrutsPrepareAndExecuteFilter过滤器init方法,和InitOperations.java类的createDispatcher方法。
继承InitOperations的类(不妨命名为MyInitOperations),覆盖private Dispatcher createDispatcher( HostConfig filterConfig )方法,参考实现如下:
/** * 覆盖原方法 */ private Dispatcher createDispatcher(HostConfig hostConfig) { Map<String, String> params = new HashMap<String, String>(); String name; String value; //原逻辑保留 for (Iterator< ? > e = hostConfig.getInitParameterNames(); e.hasNext(); params.put(name, value)) { name = (String) e.next(); value = hostConfig.getInitParameter(name); } parseStrutsConfig(hostConfig, params); return new Dispatcher(hostConfig.getServletContext(), params); } /** * 获取所有配置文件的路径 */ private void parseStrutsConfig(HostConfig hostConfig, Map<String, String> m) { String home = hostConfig.getServletContext().getRealPath("/"); home.replace("//", "/"); if (home.startsWith("/")) { home = home + "/"; } //初始化 StringBuilder strutsPath = new StringBuilder("struts-default.xml,struts-plugin.xml"); getStrutsPath(new File(home), strutsPath); m.put("config", strutsPath.toString()); } /** * 获取工程下所有的struts配置文件 */ private void getStrutsPath(File file, StringBuilder pathBuilder) { //file为空,则不操作 if (null == file) { return; } File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { File f = files[i]; //如果为目录文件,递归调用本方法 if (f.isDirectory()) { getStrutsPath(f, pathBuilder); continue; } //解析文件名:以struts.xml结尾,则拼接到路径字符串中 String fName = files[i].getName(); if (fName.endsWith("struts.xml")) { pathBuilder.append(","); //绝对路径 pathBuilder.append(files[i].getAbsolutePath()); } } }
StrutsPrepareAndExecuteFilter类init方法源码如下:
public void init(FilterConfig filterConfig) throws ServletException { InitOperations init = new InitOperations(); Dispatcher dispatcher = null; try { FilterHostConfig config = new FilterHostConfig(filterConfig); init.initLogging(config); dispatcher = init.initDispatcher(config); init.initStaticContentLoader(config, dispatcher); prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher); execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher); this.excludedPatterns = init.buildExcludedPatternsList(dispatcher); postInit(dispatcher, filterConfig); } finally { if (dispatcher != null) { dispatcher.cleanUpAfterInit(); } init.cleanup(); } }
继承类(假设为MyStrutsPrepareAndExecuteFilter)重写此方法,InitOperations init = new InitOperations();操作改为MyInitOperations init = new MyInitOperations();即可。
这里有几点使用说明:
1. web.xml的struts核心过滤器需配置为MyStrutsPrepareAndExecuteFilter这个继承类;
2. struts配置文件必须以"struts.xml"结尾,用以区分其它配置文件;
3. 只要绝对路径不同,配置文件使用相同的文件名(如,都以"struts.xml"作为配置文件名)没有影响;
4. 配置文件在类加载路径即其子路径下,都可以解析得到;
5. 若需要解析非类加载路径目录,需要参考此方式,根据相对路径思想,得到新的目录file,再次调用getStrutsPath(File file, StringBuilder pathBuilder)方法即可。
使用继承和全路径遍历的思想来实现,看起来还是比较简单易懂的。这样,我们的类加载路径下,全路径搜索struts配置文件就实现了。
相关文章推荐
- struts2--为Action配置Method属性,实现同一文件,多个Action
- struts2改变配置文件路径的一系列问题
- struts2配置文件实现文本校验
- struts2路径,常量,等一些xml配置文件
- 修改Struts2的struts.xml配置文件位置和名称-重点是init-param参数用来切换加载的路径
- python实现,按文件名搜索制定路径下的文件
- thinkphp配置文件路径的实现方法
- android输入设备配置文件搜索路径
- 批处理(bat)实现全盘搜索指定文件获取其完整路径方法大全
- as通过gradle实现多渠道打包+使用配置文件进行版本管理+指定apk输出路径和apk文件名
- C实现在某个目录下搜索某个文件并返回那个文件的绝对路径
- 批处理集锦——(6)【转】批处理实现全盘搜索指定文件获取其完整路径方法大全
- struts2实现文件上传(配置拦截器)
- 【struts2】配置log4j,设置日志文件保存路径
- Struts2实现文件上传(相对路径)
- Struts2上传文件通过配置文件实现文件过滤
- Struts2上传文件获取param配置的文件路径时的错误
- struts2——为Action配置Method属性,实现同一文件,多个Action
- 批处理(bat)实现全盘搜索指定文件获取其完整路径方法大全
- struts2通过配置文件实现动态调用action