在研究MyBatis的parsing包时,想测试一下利用Xpath查找xml中的元素,遇到了一个如何获取项目类路径的问题,于是,就顺便总结一下获取类路径的方式。如下文:

一、非web项目下如何获取类路径?

  1. 利用Class(支持相对路径和绝对路径)的getResourceAsStream和getResouce方法
/**
     * 如何读取类路径下的文件? 一、利用Class(支持相对路径和绝对路径)  二、利用ClassLoader(仅支持绝对路径,从classpath的根路径下查找,但路径开头不加斜杠)
     * 方式一:
     * 利用Class(支持相对路径和绝对路径)获取类路径或读取类路径下的文件
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        String resource = "info.xml";

        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

        //a)   利用Class的getResource获取类路径的资源文件的绝对路径
        //注意: TestXpath.class.getResource("/")取的是 classes目录的绝对路径
        System.out.println(TestXpath.class.getResource("/").getPath());
        //      TestXpath.class.getResource("")取的是  当前TestXpath.class文件所在包的绝对路径
        System.out.println(TestXpath.class.getResource("").getPath());


        //b)   利用Class的getResourceAsStream将资源文件读取为输入流
        //注意: TestXpath.class.getResourceAsStream("aaa.xml")取的是 TestXpath.class文件的相对路径,即TestXpath.class文件同级目录下的aaa.xml文件
        //      TestXpath.class.getResourceAsStream("/aaa.xml")取的是 类路径(classes目录)下的aaa.xml文件
        Document document = documentBuilder.parse(TestXpath.class.getResourceAsStream("/"+resource));

        XPathFactory xPathFactory = XPathFactory.newInstance();
        XPath xPath = xPathFactory.newXPath();

        XPathExpression xPathExpression = xPath.compile("/members/user[id=1]");
        System.out.println(xPathExpression.evaluate(document));

    }
  1. 利用ClassLoader(仅支持绝对路径,从classpath的根路径下查找,但路径开头不加斜杠)的getResourceAsStream和getResouce方法
/**
     * 如何读取类路径下的文件? 一、利用Class(支持相对路径和绝对路径)  二、利用ClassLoader(仅支持绝对路径,从classpath的根路径下查找,但路径开头不加斜杠)
     * 方式二:
     * 利用ClassLoader(仅支持绝对路径,从classpath的根路径下查找,但路径开头不加斜杠)获取类路径或读取类路径下的文件
     * 【注意】:【建议使用Thread.currentThread().getContextClassLoader(),其他方式获取类加载器可能会导致和当前线程所运行的类加载器不一致】
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        String resource = "info.xml";

        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

        //a)   利用ClassLoader的getResource获取类路径的资源文件的绝对路径
        System.out.println(TestXpath2.class.getClassLoader().getResource(resource).getPath());
        System.out.println(ClassLoader.getSystemClassLoader().getResource(resource).getPath());
        System.out.println(Thread.currentThread().getContextClassLoader().getResource(resource).getPath());

        //b)  利用ClassLoader的getResourceAsStream将资源文件读取为输入流
        //Document document = documentBuilder.parse(TestXpath.class.getClassLoader().getResourceAsStream(resource));
        //Document document = documentBuilder.parse(ClassLoader.getSystemClassLoader().getResourceAsStream(resource));
        Document document = documentBuilder.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream(resource));


        XPathFactory xPathFactory = XPathFactory.newInstance();
        XPath xPath = xPathFactory.newXPath();

        XPathExpression xPathExpression = xPath.compile("/members/user[id=1]");
        System.out.println(xPathExpression.evaluate(document));

    }

【注意】:【建议使用Thread.currentThread().getContextClassLoader(),其他方式获取类加载器可能会导致和当前线程所运行的类加载器不一致】

二、web项目下如何获取类路径?

  1. 通过HttpServletRequest获取
request.getServletContext().getRealPath("/")
  1. 通过HttpSession获取
request.getSession().getServletContext().getRealPath(""); //参数可具体到包名

三、如何加载类路径下的Properties文件?

  • 方法一:通过调用Properties的load方法加载
  • 方法二:通过ResourceBundle的getBundle方法
    获取使用指定的基本名称,默认的语言环境和调用者的类加载器获取资源包
public class TestPropertiesLoad {

    public static void main(String[] args) {

        //方法一:通过调用Properties的load方法加载
        //loadByInputstream();

        //方法二:通过ResourceBundle的getBundle方法 方法获取使用指定的基本名称,默认的语言环境和调用者的类加载器获取资源包
        ResourceBundle resource = ResourceBundle.getBundle("cardInfo");
        String bankcardNo = resource.getString("bankCardNo");
        System.out.println("bankCardNo: " + bankcardNo);
    }


    /**
     * 使用java.util.Properties类的load()方法加载properties文件
     */
    private static void loadByInputstream() {
        try {
            // 获取文件流
            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("cardInfo.properties");
            //加载格式化后的流
            Properties prop = new Properties();
            prop.load(new InputStreamReader(inputStream, "UTF-8"));

            String bankcardNo = prop.getProperty("bankCardNo");

            System.out.println("bankCardNo: " + bankcardNo);

        } catch (FileNotFoundException e) {
            System.out.println("properties文件路径有误!");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

四、如何让maven的test目录下读取到main中的resource目录配置呢?

通过在pom.xml build中添加testResource标签.如下:

<!--单元测试时引用src/main/resources下的资源文件 如何test下面有同类型的文件,则以test的为准-->
        <testResources>
            <testResource>
                <directory>src/test/resources</directory>
            </testResource>
            <testResource>
                <directory>src/main/resources</directory>
            </testResource>
        </testResources>