struts2中struts.xml 放置路径的问题

     在搭建struts2项目时如果在web.xml中不指定struts.xml文件的路径,struts2会默认到/WEB-INF/classes中寻找加载其配置文件的,但我就是想把struts的配置文件放到我指定的位置下,这时该如何处理呢?我做了以下实验:

先看一下项目的文件结构:

我把struts的配置文件放到了/WEB-INF/deploy/pms/app-config/struts-config/下,并且在web.xml中的配置如下:

 1 <filter>
 2         <filter-name>struts2</filter-name>
 3         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 4          <init-param>        
 5                <param-name>config</param-name>         
 6                <param-value>
 7                      struts-default.xml,struts-plugin.xml,/WEB-INF/deploy/pms/app-config/struts-config/struts.xml
 8                    </param-value>        
 9          </init-param> 
10     </filter>
11 
12     <filter-mapping>
13         <filter-name>struts2</filter-name>
14         <url-pattern>/*</url-pattern>
15     </filter-mapping>

满怀信心的部署项目,并潇洒的启动tomcat,擦,不想看到的问题还是来了,打印信息如下:

为什么不能加载配置文件呢(保证配置文件是无误的),难道不能解析这个路径,那把配置文件放到src的指定文件夹下试试(因为它不是默认从src发布的文件夹下找嘛),

并且修改了web.xml

 1 <filter>
 2         <filter-name>struts2</filter-name>
 3         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 4          <init-param>        
 5                <param-name>config</param-name>         
 6                <param-value>
 7                      struts-default.xml,struts-plugin.xml,config/struts.xml
 8                    </param-value>        
 9          </init-param> 
10     </filter>
11 
12     <filter-mapping>
13         <filter-name>struts2</filter-name>
14         <url-pattern>/*</url-pattern>
15     </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)方法中打印的,方法实现如下:

  1  private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {
  2         List<Document> docs = new ArrayList<Document>();
  3         List<Document> finalDocs = new ArrayList<Document>();
  4         if (!includedFileNames.contains(fileName)) {
  5             if (LOG.isDebugEnabled()) {
  6                 LOG.debug("Loading action configurations from: " + fileName);
  7             }
  8 
  9             includedFileNames.add(fileName);
 10 
 11             Iterator<URL> urls = null;
 12             InputStream is = null;
 13 
 14             IOException ioException = null;
 15             try {
 16                 urls = getConfigurationUrls(fileName);
 17             } catch (IOException ex) {
 18                 ioException = ex;
 19             }
 20 
 21             if (urls == null || !urls.hasNext()) {
 22                 if (errorIfMissing) {
 23                     throw new ConfigurationException("Could not open files of the name " + fileName, ioException);
 24                 } else {
 25                     if (LOG.isInfoEnabled()) {
 26                     LOG.info("Unable to locate configuration files of the name "
 27                             + fileName + ", skipping");
 28                     }
 29                     return docs;
 30                 }
 31             }
 32 
 33             URL url = null;
 34             while (urls.hasNext()) {
 35                 try {
 36                     url = urls.next();
 37                     is = fileManager.loadFile(url);
 38 
 39                     InputSource in = new InputSource(is);
 40 
 41                     in.setSystemId(url.toString());
 42 
 43                     docs.add(DomHelper.parse(in, dtdMappings));
 44                 } catch (XWorkException e) {
 45                     if (includeElement != null) {
 46                         throw new ConfigurationException("Unable to load " + url, e, includeElement);
 47                     } else {
 48                         throw new ConfigurationException("Unable to load " + url, e);
 49                     }
 50                 } catch (Exception e) {
 51                     throw new ConfigurationException("Caught exception while loading file " + fileName, e, includeElement);
 52                 } finally {
 53                     if (is != null) {
 54                         try {
 55                             is.close();
 56                         } catch (IOException e) {
 57                             LOG.error("Unable to close input stream", e);
 58                         }
 59                     }
 60                 }
 61             }
 62 
 63             //sort the documents, according to the "order" attribute
 64             Collections.sort(docs, new Comparator<Document>() {
 65                 public int compare(Document doc1, Document doc2) {
 66                     return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));
 67                 }
 68             });
 69 
 70             for (Document doc : docs) {
 71                 Element rootElement = doc.getDocumentElement();
 72                 NodeList children = rootElement.getChildNodes();
 73                 int childSize = children.getLength();
 74 
 75                 for (int i = 0; i < childSize; i++) {
 76                     Node childNode = children.item(i);
 77 
 78                     if (childNode instanceof Element) {
 79                         Element child = (Element) childNode;
 80 
 81                         final String nodeName = child.getNodeName();
 82 
 83                         if ("include".equals(nodeName)) {
 84                             String includeFileName = child.getAttribute("file");
 85                             if (includeFileName.indexOf('*') != -1) {
 86                                 // handleWildCardIncludes(includeFileName, docs, child);
 87                                 ClassPathFinder wildcardFinder = new ClassPathFinder();
 88                                 wildcardFinder.setPattern(includeFileName);
 89                                 Vector<String> wildcardMatches = wildcardFinder.findMatches();
 90                                 for (String match : wildcardMatches) {
 91                                     finalDocs.addAll(loadConfigurationFiles(match, child));
 92                                 }
 93                             } else {
 94                                 finalDocs.addAll(loadConfigurationFiles(includeFileName, child));
 95                             }
 96                         }
 97                     }
 98                 }
 99                 finalDocs.add(doc);
100                 loadedFileUrls.add(url.toString());
101             }
102 
103             if (LOG.isDebugEnabled()) {
104                 LOG.debug("Loaded action configuration from: " + fileName);
105             }
106         }
107         return finalDocs;
108     }

在方法的16行,该方法又调用了getConfigurationUrls(filename)方法:

1  protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException {
2         return ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false);
3     }

水还真是深,在getConfigurationUrls(filename)方法中又调用了其他类的方法,ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false)方法如下:

 1  public static Iterator<URL> getResources(String resourceName, Class callingClass, boolean aggregate) throws IOException {
 2 
 3          AggregateIterator<URL> iterator = new AggregateIterator<URL>();
 4 
 5          iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
 6 
 7          if (!iterator.hasNext() || aggregate) {
 8              iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
 9          }
10 
11          if (!iterator.hasNext() || aggregate) {
12              ClassLoader cl = callingClass.getClassLoader();
13 
14              if (cl != null) {
15                  iterator.addEnumeration(cl.getResources(resourceName));
16              }
17          }
18 
19          if (!iterator.hasNext() && (resourceName != null) && ((resourceName.length() == 0) || (resourceName.charAt(0) != '/'))) { 
20              return getResources('/' + resourceName, callingClass, aggregate);
21          }
22 
23          return iterator;
24      }

也该到尽头了吧!!从代码中可以看出,struts加载的配置文件都是从类加载器加载.class文件的路径中去寻找的,把配置文件放到WEB-INF下,它当然加载不到了,除非你写成http://xxx/工程名+配置文件路径,否则只能把配置文件写到src下了,这点struts2设计的还真是让人有点郁闷!

原文地址:https://www.cnblogs.com/angryprogrammer/p/3228104.html