添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
* 获取相对路径 【推荐】 * 使用Java提供的Path类和Paths类来获取相对路径。 * 例如,假设有两个路径a和b,我们可以使用Path类的relativize()方法来获取相对路径,该方法返回一个相对路径的Path对象。 @Test public void getRelativePathTest1(){ Path pathA = Paths.get("/user/myproject/dir1");//不需要保证文件实际存在 Path pathB = Paths.get("/user/myproject/dir2/subdir/file.txt");//不需要保证文件实际存在 Path relativePathB = pathA.relativize(pathB);//[√] log.info("relativePathB : {}", relativePathB);// "relativePathB : ..\dir2\subdir\file.txt" Path relativePathA = pathB.relativize(pathA); log.info("relativePathA : {}", relativePathA);// "relativePathA : ..\..\..\dir1" * 获取相对路径 【推荐】 @Test public void getRelativePathTest2() throws IOException { File fileA = new File("/user/myproject/dir1");//不需要保证文件实际存在 File fileB = new File("/user/myproject/dir2/subdir/file.txt");//不需要保证文件实际存在 String absolutePathA = fileA.getCanonicalPath();//E:\\user\\myproject\\dir1 String absolutePathB = fileB.getCanonicalPath();//E:\\user\\myproject\\dir2\\subdir\\file.txt String relativePath = absolutePathB.substring(absolutePathA.length()); // 输出:/dir2/subdir/file.txt log.info("absolutePathA : {}, absolutePathB : {}", absolutePathA, absolutePathB);//absolutePathA : E:\\user\\myproject\\dir1, absolutePathB : E:\\user\\myproject\\dir2\\subdir\\file.txt log.info("relativePath : {}", relativePath);//relativePath : \\subdir\\file.txt * 获取相对路径 * 如果是在Web应用中获取相对路径,可以使用ServletContext的getRealPath()方法来获取文件的绝对路径,然后使用字符串的截取来获取相对路径。 // @Test // public void getRelativePathTest3(){ // ServletContext servletContext = null; // String absolutePathA = servletContext.getRealPath("/dir1"); // String absolutePathB = servletContext.getRealPath("/dir2/subdir/file.txt"); // String relativePath = absolutePathB.substring(absolutePathA.length()); // 输出:/dir2/subdir/file.txt // }

2 获得绝对路径

基于相对路径获得绝对路径

@Test
public void getAbsolutePathByRelativePathTest(){
	// 相对路径
	String relativePath = "example.txt";
	// 获取绝对路径
	String absolutePath = null;
	//方式1
	//absolutePath = ( new File(relativePath) ).getAbsolutePath( );//E:\source_code\ADP\poc-bigdata\poc-common-demo\example.txt
	//方式2
	//absolutePath = ( (Path) Paths.get(relativePath)).toAbsolutePath().toString();//E:\source_code\ADP\poc-bigdata\poc-common-demo\example.txt
	 * 方式3 【推荐】
	 * ClassLoader 提供的 getResource()方法可以获取资源文件的URL。通过 URL 对象的 getPath 方法可以获取文件的绝对路径
	//absolutePath = getAbsolutePath(ClassLoader.getSystemClassLoader(), relativePath);
	//方式4 【推荐】 基于基础参考路径、相对路径,拼接出文件的绝对路径
	String classpath = ClassLoader.getSystemResource("").getPath();//如: /E:/source_code/xxx/xxx-bigdata/xxx-common-demo/target/classes/
	absolutePath = getAbsolutePath( classpath, relativePath );
	//方式5 通过 javax.servlet.ServletContext#getRealPath(relativePath) 方法
	//ServletContext servletContext = null;//获取 servletContext 对象,此处省略获取过程
	//absolutePath = servletContext.getRealPath(relativePath);
	// 输出绝对路径
	System.out.println("absolutePath: " + absolutePath);
 * 通过 classloader 、相对路径,获得绝对路径  
 * @param relativePath  
 * @param classLoader  
 *   [1] 获取ClassLoader的方式  
 *   ClassLoader classLoader = ClassLoader.getSystemClassLoader();  
 *   ClassLoader classLoader = Thread.currentThread().getContextClassLoader() *   ClassLoader classLoader = XXClass.class.getClassLoader(); 
 * @return
  public String getAbsolutePath(ClassLoader classLoader, String relativePath){  
    String absolutePath = null;  
    URL resource = classLoader.getResource(relativePath);// ClassLoader.getSystemResource(relativePath);  
    if(resource != null){  
        absolutePath = resource.getPath();  
    } else{  
        log.warn("the relative path's resource not for classpath!relativePath:{}", relativePath);  
    return absolutePath;  
 * 通过 基础参考路径 、相对路径,获得绝对路径  
 * @param relativePath 注:路径的首个字符不得含有文件夹符号  
 * @param basePath 注: 路径的最后必须含文件夹符号 [ "/"(Linux) , "\"(Windows) ]  
 * @return
public String getAbsolutePath(String basePath, String relativePath) {  
    //File.separator  
    return basePath + relativePath;  

基于正则表达式关键字路径 + 绝对路径,提取出目标绝对路径

import java.util.regex.Matcher;
import java.util.regex.Pattern;
     * java 实现在
     *  绝对路径A(如: /D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/com/xxx/sdk/java/yyy/)中
     *  按照关键词路径P(如"/target/*classes/")正则匹配搜索出绝对路径A2(如:"/D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/")
    @Test
    public void test(){
        String absolutePath = "/D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/com/xxx/sdk/java/yyy/";
        String patternStr = "/target/*classes/";
        String regex = patternStr.replace("*", ".*");
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(absolutePath);
        if (matcher.find()) {
            String matchedPath = absolutePath.substring(0, matcher.end());
            System.out.println("匹配到的路径 A2: " + matchedPath);
        } else {
            System.out.println( "未找到匹配的路径");
 * 获取项目的根路径
 * @note 仅适用于源码工程中
 * @param anyProjectClassAbsolutePath 项目内任一 class/java 文件的路径
 * @return
public static String getProjectRootPath(String anyProjectClassAbsolutePath) {
	//String anyProjectClassAbsolutePath = "/D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/com/xxx/sdk/java/yyy/";
	String patternStr = "/target/*classes/";
	String regex = patternStr.replace("*", ".*");
	Pattern pattern = Pattern.compile(regex);
	Matcher matcher = pattern.matcher(anyProjectClassAbsolutePath);
	if (matcher.find()) {
		String matchedPath = anyProjectClassAbsolutePath.substring(0, matcher.end());
		log.info("matchedPath: {},anyProjectClassAbsolutePath: {}", matchedPath, anyProjectClassAbsolutePath);
		return matchedPath;
	} else {
	   throw new RuntimeException("Not matched target path!anyProjectClassAbsolutePath:" + anyProjectClassAbsolutePath);

demo code:

// demo code :	
//String classpath = ClassLoader.getSystemResource("").getPath();// /E:/source_code/XXX/XXX-sdk/xxx-common-demo/target/classes/
// XxxxTest.class.getResource("").toString()  = "file:/D:/Workspace/CodeRepositories/XXX-platform/XXX-sdk/XXX-sdk-java/target/test-classes/com/XXX/sdk/java/can/"
// XxxxTest.class.getResource("").getPath() = "/D:/Workspace/CodeRepositories/XXX-platform/XXX-sdk/XXX-sdk-java/target/test-classes/com/XXX/sdk/java/can/"
// classpath | eg: "/D:/Workspace/CodeRepositories/XXX-platform/XXX-sdk/XXX-sdk-java/target/test-classes/"
String classpath = getProjectRootPath( XxxxTest.class.getResource("").getPath() );

3 获取 classpath 路径

classpath 概念

  • [JVM] 概念辨析:classpath / jar - 博客园/千千寰宇
  • classpathJVM用到的一个环境变量,它用来指示JVM如何搜索class
  • classpath就是一组目录的集合,它设置的搜索路径与操作系统相关
  • 在Windows系统上,用;分隔,带空格的目录用""括起来,可能长这样:

    C:\work\project1\bin;C:\shared;"D:\My Documents\project1\bin"
    

    在Linux系统上,用:分隔,可能长这样:

    /usr/shared:/usr/local/bin:/home/johnny/bin
    

    获取 classpath 路径

    //方式1  
    classpath = System.getProperty("java.class.path");
    //classpath:D:\Program\Java\jdk1.8.0_261\jre\lib\charsets.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\deploy.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\access-bridge-64.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\cldrdata.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\dnsns.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\jaccess.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\jfxrt.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\localedata.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\nashorn.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\sunec.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\sunjce_provider.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\sunmscapi.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\sunpkcs11.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\ext\zipfs.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\javaws.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\jce.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\jfr.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\jfxswt.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\jsse.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\management-agent.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\plugin.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\resources.jar;D:\Program\Java\jdk1.8.0_261\jre\lib\rt.jar;E:\source_code\xxx\xxx-bigdata\xxx-common-demo\target\classes;D:\Program\IDEA\IDEA_COMMUNITY_2023.2\lib\idea_rt.jar
    

    获取当前项目的 target classes 路径 (不推荐)

    public class ClassPathDemo {  
        public static void main(String[] args) {  
            String classpath = null;  
            //方式1
            //String classpath = ClassPathDemo.class.getResource("/").getPath();
            //classpath:/E:/source_code/xxx/xxx-bigdata/xxx-common-demo/target/classes/  
    		//或 file:/C:/Users/EDY/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/META-INF/versions/9/
            //方式2 【推荐】  
            classpath = ClassLoader.getSystemResource("").getPath();
    		//classpath:/E:/source_code/xxx/xxx-bigdata/xxx-common-demo/target/classes/  
            //或 file:/C:/Users/EDY/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/META-INF/versions/9/
    		//Thread.currentThread().getContextClassLoader().getResource("");
    		//或 jar:file:/C:/Users/EDY/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/META-INF/versions/9/
            //方式3 | 仅适用于 servlet web 项目  
            //ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();  
            //classpath = context.getResource("").getFile().getAbsolutePath();  
            System.out.println("classpath:" + classpath); 
    

    此获取方式,在 Windows 环境下,并不完全可靠。
    Linux 环境下的值,尚未试验过。

    Q:为何IDE(IDEA)中执行java代码获取路径:ClassLoader.getSystemResource("").getPath() 错误,返回为file:/C:/Users/EDY/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/META-INF/versions/9/ 而非/D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/classes/

    IDE(IDEA)中执行java代码获取路径:ClassLoader.getSystemResource("").getPath()this.getClass().getClassLoader().getResource("").getPath() 错误,返回为file:/C:/Users/EDY/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/META-INF/versions/9/ 而非/D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/classes/

  • JUnit 测试环境:在 JUnit 测试环境中,ClassLoader.getSystemResource("") 获取的是系统类加载器的资源路径。由于 JUnit 测试类的加载器可能与主程序的加载器不同,因此它返回的是 JUnit JAR 文件的路径,而不是项目的 target/classes 目录。 【确实如此】
  • public class XxxxTest {
        @Test 
        public void xxxTest(){
            String path = ClassLoader.getSystemResource("").getPath();
    
  • 资源路径的特殊性getResource("") 获取的是当前类加载器的资源路径,而 JUnit 测试类的资源路径通常是 JAR 文件中的路径,而不是项目的工作目录。
  • 指定一个已知的资源文件
    如果你需要通过类加载器获取路径,可以指定一个已知的资源文件,例如 application.properties,然后通过这个资源文件的路径来推导项目路径。

    String resourcePath = this.getClass().getClassLoader().getResource("application.properties").getPath();
    System.out.println("资源路径: " + resourcePath);
    

    试验: Xxx.class.getResource("").getPath() / ClassLoader.getSystemResource("").getPath()

  • ClassLoader#getSystemResource
  • 本地运行(Windows)

    ClassLoader.getSystemResource("").getPath()
    ///D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/classes/ 【非JUnit环境下】
    //file:/C:/Users/EDY/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/META-INF/versions/9/ 【JUnit环境下】
    

    在线运行 : https://www.jsongj.com/compiler/java

    public class Main {
    	public static void main(String[] args) {
    		System.out.println( ClassLoader.getSystemResource("").getPath() );// "/home/output/"
    

    在线运行 : https://www.jsongj.com/compiler/java

    public class Main {
    	public static void main(String[] args) {
    		System.out.println( Main.class.getResource("").getPath() ); // "/home/output/"
    
  • com.alibaba.fastjson2.JSON
  • import com.alibaba.fastjson2.JSON;
    JSON.class.getResource("").getPath();
    file:/D:/Program-Data/Maven-Repository/com/alibaba/fastjson2/fastjson2/2.0.37/fastjson2-2.0.37.jar!/com/alibaba/fastjson2/ 【非JUnit环境下】
    file:/D:/Program-Data/Maven-Repository/com/alibaba/fastjson2/fastjson2/2.0.37/fastjson2-2.0.37.jar!/com/alibaba/fastjson2/ 【JUnit环境下】
    
  • java.io.File
  • File.class.getResource("").getPath();
    //java.lang.NullPointerException 【非JUnit环境下】
    //java.lang.NullPointerException 【JUnit环境下】
    
  • com.xxx.sdk.java.xxx.parse.CanAscLogGenerator
  • CanAscLogGenerator.class.getResource("").getPath();
    // /D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/com/xxx/sdk/java/xxx/parse/ 【非JUnit环境下】
    // /D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/com/xxx/sdk/java/xxx/parse/ 【JUnit环境下】
    CanAscLogGenerator.class.getResource("log4j2.properties").getPath()
    // java.lang.NullPointerException【非JUnit环境下】
    // java.lang.NullPointerException【JUnit环境下】
    CanAscLogGenerator.class.getClassLoader().getResource("").getPath()
    // /D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/classes/ 【非JUnit环境下】
    // file:/C:/Users/EDY/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/META-INF/versions/9/ 【JUnit环境下】
    CanAscLogGenerator.class.getClassLoader().getResource("log4j2.properties").getPath() //技巧:指定一个项目下的已知资源文件
    // /D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/classes/log4j2.properties 【非JUnit环境下】
    // /D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/log4j2.properties 【JUnit环境下】
    

    4 获取当前工程根路径

    方式1: System.getProperty("user.dir")

  • 在Java程序中,可以通过System.getProperty("user.dir")来获取当前工作目录的路径,即程序运行时所在的目录。这个属性通常用于读取或写入文件时指定文件相对路径,以便程序能够正确找到文件。
  • 举例说明,如果当前工作目录是/Users/username/Documents,那么System.getProperty("user.dir")将返回/Users/username/Documents。
  • //获取当前工作目录的路径  
    //String projectRootPath = ( new File("") ).getCanonicalPath();//方式1  
    String projectRootPath = System.getProperty("user.dir");//方式2  
    System.out.println("projectRootPath :" + projectRootPath);//D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java
    

    方式2 FilePathUtils

    猜测: 本质上还是和 "user.dir" 息息相关。

    public class FilePathUtils {
        public static final String FILE_SEPARATOR = System.getProperty("file.separator");
         * 获取所在项目的根路径
         * @usage 
         *  在 xxx-sdk-java 工程中调用时 : "file:///D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java"
         *  在 xxx-sdk-util 工程中调用时 : "file:///D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-util"
         *  String path = FilePathUtils.getProjectRootPath() + "/target/test-classes/some/xxx";
         *  // "file:///D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/some/xxx"
         *  URL url = new URL(path);
         *  new File(url.getPath()).exists() = true
         * @return ""
        public static String getProjectRootPath() {
            //String dir = ( new File("src/main/java") ).getAbsolutePath();// eg: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java\src\main\java"
            //String dir = ( new File("src/main/resources") ).getAbsolutePath();// eg: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java\src\main\resources"
            String dir = ( new File("") ).getAbsolutePath();// eg: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java"
            //dir = "file://" + "/" + dir.replaceAll("\\\\", "/");
            dir = "file://" + "/" + dir.replace(FILE_SEPARATOR, "/");
            return dir;
    

    方式2 基于 ProtectionDomain 获取当前JAR包所处目录

  • ProtectionDomain
  • [Java/JVM/安全] ProtectionDomain : Java 安全模型的核心组件 - 博客园/千千寰宇
  • CASE 获取本JAR包的所处目录
  • 5 获取用户主目录

    String userHomePath = null;  
    userHomePath = org.apache.commons.io.FileUtils.getUserDirectoryPath();
    // 等效于 : System.getProperty("user.home");System.out.println("userHomePath :" + userHomePath);
    //C:\Users\xxxx
    

    6 获取OS临时目录

    String tempDirectoryPath = FileUtils.getTempDirectoryPath();
    //等效于 : System.getProperty("java.io.tmpdir")System.out.println("tempDirectoryPath :" + tempDirectoryPath);
    // C:\\Users\\xxxx\\AppData\\Local\\Temp\\
    

    H 附件:工具类

    ClassLoaderUtils

    ClassLoaderUtils

    import lombok.extern.slf4j.Slf4j;
    import java.io.File;
    import java.net.URL;
     * ClassLoader 工具类
     * @update-time 2025.6.5 11:12
    @Slf4j
    public class ClassLoaderUtils {
        public static final String FILE_SEPARATOR = System.getProperty("file.separator");
         * 定位目标项目的 classpath 路径的文件名称
         * @note
         * 1. 要求放置在应用工程的源码根目录(src/) 或 资源根目录(resources/)下。
         * 2. 其文件内容:可编写任意内容,也可为空。
        public static String PROJECT_CLASSPATH_FILE = "PROJECT_CLASSPATH";
        public static String TEST_PROJECT_CLASSPATH_FILE = "TEST_PROJECT_CLASSPATH";
         * 通过 classloader 、相对路径,获得绝对路径
         * @sample
         *     getAbsolutePath(ClassLoaderUtil.class.getClassLoader(), "")) : /D:/Workspace/CodeRepositories/xxx-platform/xxx-modules/xxx-backend/target/classes/
         * @param relativePath
         * @param classLoader
         *   [1] 获取ClassLoader的方式
         *   ClassLoader classLoader = ClassLoader.getSystemClassLoader();
         *   ClassLoader classLoader = Thread.currentThread().getContextClassLoader()
         *   ClassLoader classLoader = XXClass.class.getClassLoader();
         * @return
        public static String getAbsolutePath(ClassLoader classLoader, String relativePath){
            String absolutePath = null;
            URL resource = classLoader.getResource(relativePath);// ClassLoader.getSystemResource(relativePath);
            if(resource != null){
                absolutePath = resource.getPath();
            } else{
                log.warn("the relative path's resource not for classpath!relativePath:{}", relativePath);
            return absolutePath;
         * 获取调用本方法的项目所在的项目 classpath
         * @note
         *   注意,哪个工程调用本方法,则该工程下就必须提前创建好 {@link #PROJECT_CLASSPATH_FILE } 文件,即使是空文件
         * @return
         * @usage
         * 例如: xxx-sdk-java 中调用本方法后的返回值: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java\target\classes"
         * 例如: xxx-sdk-java-test 中调用本方法后的返回值:
         *   若 正式源码 子工程下没有放置 {@link #PROJECT_CLASSPATH_FILE } 文件,但 TEST 子工程放了,则返回: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java\target\test-classes"
         *   若 正式源码 子工程下已放置有 {@link #PROJECT_CLASSPATH_FILE } 文件,且 TEST 子工程有放置,则返回: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java\target\classes"
         *   若 正式源码 子工程下已放置有 {@link #PROJECT_CLASSPATH_FILE } 文件,但 TEST 子工程没放置,则返回: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java\target\classes"
         *   若均无该文件,则返回 null
        public static String getProjectClassPath(){
            File path = getProjectClassPathDirectory();
            return path==null?null:path.getPath();
        public static File getProjectClassPathDirectory(){
            //new File( CloudCanMessageParseTest.class.getClassLoader().getResource(ClassLoaderUtils.PROJECT_CLASSPATH_FILE).getPath() ).getParentFile().getPath()
            URL resource = ClassLoader.getSystemResource(PROJECT_CLASSPATH_FILE);
            File path = resource==null?null:new File( resource.getPath() );
            return path == null?null:path.getParentFile();
         * 获取调用本方法的项目所在的项目测试子工程的 classpath
         * @note 建议仅在 测试子工程中调用
         * @return
         *   eg: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java\target\test-classes"
        public static String getTestProjectClassPath(){
            File path = getTestProjectClassPathDirectory();
            return path==null?null:path.getPath();
        public static File getTestProjectClassPathDirectory(){
            URL resource = ClassLoader.getSystemResource(TEST_PROJECT_CLASSPATH_FILE);
            File path = resource==null?null:new File( resource.getPath() );
            return path == null?null:path.getParentFile();
         * 获取所在项目的根路径
         * @usage
         *  String path = getProjectRootPath() + "/target/test-classes/some/xxx";
         *  // "file:///D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java/target/test-classes/some/xxx"
         *  URL url = new URL(path);
         *  new File(url.getPath()).exists() = true
         * @return ""
         *   eg: "file:///D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-java" (JUnit 环境 or 非 JUnit 环境)
        public static String getProjectRootPath() {
            String dir = ( new File("") ).getAbsolutePath();// eg: "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-java"
            //dir = "file://" + "/" + dir.replaceAll("\\\\", "/");
            dir = "file://" + "/" + dir.replace(FILE_SEPARATOR, "/");
            return dir;
         * 获取应用程序JAR包所处路径
         * @param applicationClazz 应用程序的 Class 类
         *     1. 不能是 JDK 的 Class 类,例如: Object.class , Class.class , ... (将报错)
         * @return
         *   "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-helper\target" (源码工程在运行时的获取结果)
         *   "D:\Workspace\Projects\XXX-Project\xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar" (JAR包在运行时的获取结果)
        public static String getApplicationJarDirectory(Class applicationClazz){
            // 获取当前类的 ProtectionDomain
            ProtectionDomain domain = applicationClazz.getProtectionDomain();//只能是应用工程的自定义类,不能是 jdk 的 类(如: Object.class , Class.class)
            URL location = domain.getCodeSource().getLocation();
            File jarFile = null;
            try {
                // 转换为文件路径
                jarFile = new File(location.toURI());
                //String jarDirectory = jarFile.getParent(); // JAR 所在目录
            } catch (Exception exception) {
                log.error("get current jar path fail !exception:", exception);
            log.info("current jar path: {}", jarFile.getAbsolutePath());//"file:/D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-helper/target/classes/" or "D:\Workspace\Projects\XXX-Project\xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar"
            return jarFile == null ? null : jarFile.getParentFile().getAbsolutePath();
    
  • DemoTest - 1
  • import org.apache.commons.io.FileUtils; // org.apache.commons.io.FileUtils#listFiles(java.io.File, org.apache.commons.io.filefilter.IOFileFilter, org.apache.commons.io.filefilter.IOFileFilter)
    public class XxxxxxxServiceImpl implements IXxxxxxxService {
        public static String CLASSPATH;
    	//...
        static {
            //CLASSPATH = ClassLoaderUtils.getAbsolutePath(XxxPeriodicCollectMessageParseServiceImpl.class.getClassLoader() , "");
            //CLASSPATH = FilePathUtils.getProjectRootPath().replace("file://", "");
            CLASSPATH = ClassLoaderUtils.getProjectClassPath(); //JAR包在服务器端运行时,此值为 null
            log.info("CLASSPATH:{}", CLASSPATH);
            //XXX_FILES_DIR_PATH = CLASSPATH + "/target/classes/" + "can/dbc/"; //本地目录
            XXX_FILES_DIR_PATH = CLASSPATH + CAN_DBC_DIR; //本地目录
            if( !FileUtil.exist(XXX_FILES_DIR_PATH) ){//非本地目录 (基于 Dockerfile 构建的 Docker环境)
                XXX_FILES_DIR_PATH = CAN_DBC_DIR;
            log.info("XXX_FILES_DIR_PATH:{}", XXX_FILES_DIR_PATH);
        public void Xxx(){
    	    //...
            List<String> xxxFileLocalRelativePaths = FileUtils.listFiles(new File( XXX_FILES_DIR_PATH ), TrueFileFilter.TRUE, TrueFileFilter.TRUE).stream().map(file -> {
                return file.getAbsolutePath();
            } ).collect(Collectors.toList());
    		//...
    	//...
    

    Z 获取指定路径文件的 URL/InputStream 对象

    XXServiceBizApplication 的路径 : src/main/java/com.xx.yy.zz.biz.XXServiceBizApplication
    FileTest 的路径 : src/test/java/com.test.FileTest
    Object 的路径 : java.lang.Object
    Thread 的路径 : java.lang.Thread
    messages_en_US.propertie 的路径 : src/main/resources/i18n/messages_en_US.properties
    

    URL|InputStream : java.lang.Class#getResource(path)|getResourceAsStream(String path)

  • (1)不以 / 开头时,默认:以当前class类文件所在路径为基准,目标文件相对于该类文件的路径
  • URL url = XXServiceBizApplication.class.getResource("");//获得当前class类文件的URI目录,不包括类文件自己!
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/com/xx/yy/zz/biz
    Thread.currentThread().getContextClassLoader().getResource("")
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/
    URL url = XXServiceBizApplication.class.getResource("./../../../../../i18n/messages_en_US.properties");
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/i18n/messages_en_US.properties
    URL url = Object.class.getResource("./../../i18n/messages_en_US.properties");//Object 的路径 : java.lang.Object
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/i18n/messages_en_US.properties
    InputStream inputStream = XXServiceBizApplication.class.getResourceAsStream("./../../../../../i18n/messages_en_US.properties");
    
  • (2)以 / 开头,则:从 ClassPath 根下获取。
  • URL url = XXServiceBizApplication.class.getResource("/");//当前的classpath的绝对URI路径
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/
    URL url = XXServiceBizApplication.class.getResource("/i18n/messages_en_US.properties");
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/i18n/messages_en_US.properties
    InputStream inputStream = XXServiceBizApplication.class.getResourceAsStream("/i18n/messages_en_US.properties");
    

    URL|InputStream : java.lang.ClassLoader#getResource(path)|getResourceAsStream(String path)

  • / 开头,则:不被允许 ———— 即:path不能以/开头
  • URL url = ClassLoader.getSystemResource("/") //【X,错误示范】
    //null
    ClassLoader.getSystemResourceAsStream("/") //【X,错误示范】
    //null
    ClassLoader.getSystemClassLoader().getResource("/")//【X,错误示范】
    //null
    URL url = Thread.currentThread().getContextClassLoader().getResource("/"); //【X,错误示范】
    //null
    URL url = XXServiceBizApplication.class.getClassLoader().getResource("/"); //【X,错误示范】
    //null
    
  • 不以 / 开头时,则:默认从ClassPath根下获取
  • URL url = ClassLoader.getSystemResource("")
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/
    ClassLoader.getSystemClassLoader().getResource("")
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/
    URL url = XXServiceBizApplication.class.getClassLoader().getResource("");
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/
    URL url = XXServiceBizApplication.class.getClassLoader().getResource("./i18n/messages_en_US.properties");
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/i18n/messages_en_US.properties
    URL url = Thread.currentThread().getContextClassLoader().getResource("i18n/messages_en_US.properties"); 
    ///E:/source_code/xxx/xx_service/xx-service-biz/target/classes/i18n/messages_en_US.properties
    InputStream inputStream = XXServiceBizApplication.class.getClassLoader().getResourceAsStream("i18n/messages_en_US.properties");
    InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("i18n/messages_en_US.properties");
    

    Y 推荐文献

  • classpath和jar - 廖雪峰
  • [JVM] 概念辨析:classpath / jar - 博客园/千千寰宇
  • X 参考文献

  • java通过文件的相对路径怎么获取绝对路径 - 51CTO
  • 【JAVA】获取当前项目的classpath路径 - CSDN
  • [Java SE] 基础工具库 : Apache Commons IO - 博客园
  • Java 获取路径的方法归总 - CSDN
  • Java如何获取相对路径文件 - jb51.net
  •