struts2中struts.xml 放置路径的问题
在搭建struts2项目时如果在web.xml中不指定struts.xml文件的路径,struts2会默认到/WEB-INF/classes中寻找加载其配置文件的,但我就是想把struts的配置文件放到我指定的位置下,这时该如何处理呢?我做了以下实验:
先看一下项目的文件结构:
我把struts的配置文件放到了/WEB-INF/deploy/pms/app-config/struts-config/下,并且在web.xml中的配置如下:
<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,/WEB-INF/deploy/pms/app-config/struts-config/struts.xml
</param-value>
</init-param>
</filter> <filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
满怀信心的部署项目,并潇洒的启动tomcat,擦,不想看到的问题还是来了,打印信息如下:
为什么不能加载配置文件呢(保证配置文件是无误的),难道不能解析这个路径,那把配置文件放到src的指定文件夹下试试(因为它不是默认从src发布的文件夹下找嘛),
并且修改了web.xml
<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,config/struts.xml
</param-value>
</init-param>
</filter> <filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
再次部署启动,居然没错了。郁闷。。。,难道我非得把配置文件放到src下吗,有点不甘心,看看你struts2的源码怎么读取文件的吧,从tomcat的打印信息中可以看到,加载配置文件的类是XmlConfigurationProvider
16:10:36,403 INFO ContextLoader:301 - Root WebApplicationContext: initialization completed in 2546 ms
16:10:36,622 INFO XmlConfigurationProvider:42 - Parsing configuration file [struts-default.xml]
16:10:36,763 INFO XmlConfigurationProvider:42 - Parsing configuration file [struts-plugin.xml]
16:10:36,809 INFO XmlConfigurationProvider:42 - Parsing configuration file [config/struts.xml]
16:10:37,059 INFO StrutsSpringObjectFactory:42 - Initializing Struts-Spring integration...
那就在struts2源码中直接找这个类,在这个类中搜了一下打印的日志信息“Unable to locate configuration files of the name”,找到这个信息是在XmlConfigurationProvider类的private List<Document> loadConfigurationFiles(String fileName, Element includeElement)方法中打印的,方法实现如下:
private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {
List<Document> docs = new ArrayList<Document>();
List<Document> finalDocs = new ArrayList<Document>();
if (!includedFileNames.contains(fileName)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Loading action configurations from: " + fileName);
}
includedFileNames.add(fileName);
Iterator<URL> urls = null;
InputStream is = null;
IOException ioException = null;
try {
urls = getConfigurationUrls(fileName);
} catch (IOException ex) {
ioException = ex;
}
if (urls == null || !urls.hasNext()) {
if (errorIfMissing) {
throw new ConfigurationException("Could not open files of the name " + fileName, ioException);
} else {
if (LOG.isInfoEnabled()) {
LOG.info("Unable to locate configuration files of the name "
+ fileName + ", skipping");
}
return docs;
}
}
URL url = null;
while (urls.hasNext()) {
try {
url = urls.next();
is = fileManager.loadFile(url);
InputSource in = new InputSource(is);
in.setSystemId(url.toString());
docs.add(DomHelper.parse(in, dtdMappings));
} catch (XWorkException e) {
if (includeElement != null) {
throw new ConfigurationException("Unable to load " + url, e, includeElement);
} else {
throw new ConfigurationException("Unable to load " + url, e);
}
} catch (Exception e) {
throw new ConfigurationException("Caught exception while loading file " + fileName, e, includeElement);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
LOG.error("Unable to close input stream", e);
}
}
}
}
//sort the documents, according to the "order" attribute
Collections.sort(docs, new Comparator<Document>() {
public int compare(Document doc1, Document doc2) {
return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));
}
});
for (Document doc : docs) {
Element rootElement = doc.getDocumentElement();
NodeList children = rootElement.getChildNodes();
int childSize = children.getLength();
for (int i = 0; i < childSize; i++) {
Node childNode = children.item(i);
if (childNode instanceof Element) {
Element child = (Element) childNode;
final String nodeName = child.getNodeName();
if ("include".equals(nodeName)) {
String includeFileName = child.getAttribute("file");
if (includeFileName.indexOf('*') != -1) {
// handleWildCardIncludes(includeFileName, docs, child);
ClassPathFinder wildcardFinder = new ClassPathFinder();
wildcardFinder.setPattern(includeFileName);
Vector<String> wildcardMatches = wildcardFinder.findMatches();
for (String match : wildcardMatches) {
finalDocs.addAll(loadConfigurationFiles(match, child));
}
} else {
finalDocs.addAll(loadConfigurationFiles(includeFileName, child));
}
}
}
}
finalDocs.add(doc);
loadedFileUrls.add(url.toString());
}
if (LOG.isDebugEnabled()) {
LOG.debug("Loaded action configuration from: " + fileName);
}
}
return finalDocs;
}
在方法的16行,该方法又调用了getConfigurationUrls(filename)方法:
protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException {
return ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false);
}
水还真是深,在getConfigurationUrls(filename)方法中又调用了其他类的方法,ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false)方法如下:
public static Iterator<URL> getResources(String resourceName, Class callingClass, boolean aggregate) throws IOException {
AggregateIterator<URL> iterator = new AggregateIterator<URL>();
iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
if (!iterator.hasNext() || aggregate) {
iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
}
if (!iterator.hasNext() || aggregate) {
ClassLoader cl = callingClass.getClassLoader();
if (cl != null) {
iterator.addEnumeration(cl.getResources(resourceName));
}
}
if (!iterator.hasNext() && (resourceName != null) && ((resourceName.length() == 0) || (resourceName.charAt(0) != '/'))) {
return getResources('/' + resourceName, callingClass, aggregate);
}
return iterator;
}
也该到尽头了吧!!从代码中可以看出,struts加载的配置文件都是从类加载器加载.class文件的路径中去寻找的,把配置文件放到WEB-INF下,它当然加载不到了,除非你写成http://xxx/工程名+配置文件路径,否则只能把配置文件写到src下了,这点struts2设计的还真是让人有点郁闷!
struts2中struts.xml 放置路径的问题的更多相关文章
- struts2中struts.xml配置文件详解【未整理】
1. 深入Struts2的配置文件 本部分主要介绍struts.xml的常用配置. 1.1. 包配置: Struts2框架中核心组件就是Action.拦截器等,Struts2框架使用包来管 ...
- struts2中struts.xml配置文件详解
struts.xml的常用配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts ...
- struts2中struts.xml和web.xml文件解析及工作原理
web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp ...
- Struts2中.properties文件放置路径(classpath)
一.web应用的classpath简介 classpath路径,即WEB-INF下面的classes目录,所有src目录下面的java.xml.properties等文件编译后都会在此. Stru ...
- Struts2中Struts.xml的作用
struts.xml 为Struts 2的核心配置文件.struts.xml文件主要负责管理应用中的Action映射,以及该Action包含的Result定义等.struts.xml中主要配置Stru ...
- Struts2 中Struts.xml结果页面配置
结果页面的配置: 红色的比较常用
- struts2中改变struts.xml默认路径
struts2.X配置文件默认存放路径在/WEB-INF/classes目录下,即将struts.xml放在src的目录下. 但是为了方便管理,开发人员把struts.xml放到其他位置,处理方法如下 ...
- Struts2笔记——struts.xml配置详解
访问HelloWorld应用的路径的设置 * 在struts1中,通过<action path=“/primer/helloWorldAction.action”>节点的path属性指定访 ...
- struts2——配置struts.xml文件
在struts2框架中struts.xml是应当放到src的根目录,程序编译后会将struts.xml放到WEB-INF/classes目录下. Struts2在web.xml中的一般配置如下: &l ...
随机推荐
- multiSelect 下拉多选插件
multiSelect是一款很好用的下拉多选插件,可以在下拉框中实现多选框,全选及取消全选等方法.使用方法:1.引用 multiSelect.css及 multiSelect.js.下载地址 http ...
- Web API框架学习——消息管道(二)
HttpServer的GlobalConfiguration中创建: GlobalConfiguration中确定了第一个HttpMessageHandler消息管道: 首:DefaultServer ...
- 详解< meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" />
< meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" /> 这是个是 ...
- 浅谈EL
一.了解EL 1.EL是从 JavaScript 脚本语言得到启发的一种表达式语言,它借鉴了 JavaScript 多类型转换无关性的特点.在使用 EL 从 scope 中得到参数时可以自动转换类型, ...
- NIO(三、Channel)
目录 NIO(一.概述) NIO(二.Buffer) NIO(三.Channel) Channel 上文说了描述了Buffer的实现机制,那么这个章节就主要描述数据是如何进入缓冲区的,并且又是如何从缓 ...
- RabbitMQ-从基础到实战(4)— 消息的交换(下)
0.目录 RabbitMQ-从基础到实战(1)- Hello RabbitMQ RabbitMQ-从基础到实战(2)- 防止消息丢失 RabbitMQ-从基础到实战(3)- 消息的交换(上) 1.简介 ...
- JQ鼠标右键点击功能 兼容IE8
//阻止浏览器当前DIV默认右键事件 $("div").unbind("mousedown").bind("contextmenu", fu ...
- iOS开发之NSTimer
1.NSTimer叫做“定时器”,它的作用如下 Ø 在指定的时间执行指定的任务 Ø 每隔一段时间执行指定的任务 2.调用NSTimer下面的方法就会开启一个定时任务 + (NSTimer *)sche ...
- pyqt样式表语法笔记(中)--原创
pyqt样式表语法笔记(中) pyqt QSS python 样式表 一.弹窗 在日常的各种桌面软件的使用中,我们都会碰到弹窗.例如注册,登录的时候,会有相应的信息弹窗,这里就以信息收集弹窗为例进行弹 ...
- PHP和js实时倒计时
<?php //这是t.php页面 header('content-type:text/html;charset=utf-8'); date_default_timezone_set('PRC' ...