读取配置文件的正确姿势(关于配置文件的路径获取)


0、写在前面的话

最近在做微信的公众号开发,因为调用微信接口失败的话是以各类错误码和错误信息返回的,在Github发现有位老哥整理成了xml(weixin/error.xml),索性也就想借鉴他的方式和这份xml,将内容读取存储到一个Map中,这样在遇到微信返回的错误码时就可以从Map中取出对应的具体错误信息。

在工具类中建立一个静态块,然后试图读取xml然后存入Map,问题来了,之前在Servlet中都是利用的ServletContext上下文对象,使用getRealPath(String path)方法获取文件路径。可是这个工具类并不是Servlet,也就没有ServletContext。

然而,什么都难不倒Google,下面就类似的配置文件的读取问题,进行一下总结。

另外,要说一个前提是,xml、properties等配置文件和Java资源都是放在WEB-INF下面的classes文件夹中(以下则称之为classpath)。我们的目的是如何获取该目录下的文件资源,假如我们现在的文件为应用根目录下" .../WEB-INF/classes/error.xml "。

 

1、在Servlet类中读取

假如要将文件获取为流,有两种读取方式:

(1)直接读取文件为流,getResourceAsStream(path)方法,path默认为应用的根目录
InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/error.xml"); 

(2)先读取文件,再读取为流,获取路径的方式和上面是类似的
String path = this.getServletContext().getRealPath("/WEB-INF/classes/error.xml");
InputStream inputStream = new FileInputStream(path);


2、在非Servlet类中(普通Java类中)的读取

在非Servlet类中,要将文件获取为流,也有两种方式:

(1)用ClassLoader类加载资源文件,这里默认是从classes目录下读取

用ClassLoader加载配置文件时,path,也就是这里的 "error.xml" 不能以"/"开头,在查找时直接在classpath下进行查找:
InputStream in = ClassName.class.getClassLoader().getResourceAsStream("error.xml");

同样的方法,也可以迂回一下,先读取到文件的路径,再用流读出,这里FileInputStream的path就可以使用绝对或者相对路径:
String path = ClassName.class.getClassLoader().getResource("error.xml").getPath();  
InputStream inputStream = new FileInputStream(path); 


(2)用Class类加载资源文件,形参不同,访问路径不同
InputStream inputStream = ClassName.class.getResourceAsStream("/error.xml");
需要注意的是,这种方式的形参有两种方式:
  • 绝对定位,“/”开头,此时即以classpath为根目录
  • 相对定位,不加“/”,则以调用getResourceAsStream类的包路径作为根目录(即该类所在包下获取资源)


最后,也就是用了如上的方法,解决了我读取error.xml的问题:
//读取errorCode错误码到Map中
static {
    InputStream xml = WeChatUtil.class.getResourceAsStream("/error.xml");
    SAXReader saxReader = new SAXReader();
    try {
        Document document = saxReader.read(xml);
        Element root = document.getRootElement();
        List<Element> elements = root.elements();
        for (Element element : elements) {
            String code = element.elementText("code");
            String text = element.elementText("text");
            WeChatUtil.errorCodeMap.put(code, text);
        }
    } catch (DocumentException e) {
        log.debug("error.xml读取失败");
        e.printStackTrace();
    }
}


3、参考链接



题外话:

在使用Spring时通常看到诸如 <param-value>classpath:applicationContext-*.xml</param-value> 的配置,此处的classpath确实是指WEB-INF下的classes目录,但此处毕竟只是配置的字符串,实际上获取资源路径时是框架进行了识别和处理的。我之前也是很愚,一直不理解所谓的classpath,今天才明白了些许,顺便追了下Spring源码。

在Spring的配置中,实际上有classpath和classpath*,区别在于:
  • classpath     只会到你的classes路径中查找找文件
  • classpath*    不仅包含classes路径,还包括jar文件中(class路径)进行查找


posted @ 2017-07-11 22:43  Dulk  阅读(9536)  评论(0编辑  收藏  举报