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



    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路径)进行查找


  • 相关阅读:
    验证码缓存问题完美解决方案
    最近项目是跟框架有关的两个问题
    未与信任 SQL Server 连接相关联
    Get请求
    Post请求
    jQuery操作元素
    Dom对象和jQuery包装集
    XMLHttpRequest对象
    jQuery事件与事件对象
    处理数据集
  • 原文地址:https://www.cnblogs.com/deng-cc/p/7152988.html
Copyright © 2020-2023  润新知