Java在J2EE工程中路径寻址问题终极解决方案

前言

Java的路径问题,非常难搞。最近的工作涉及到创建和读取文件的工作,这里我就给大家彻底得解决Java路径问题。

 

Java路径

Java中使用的路径,分为两种:绝对路径和相对路径。具体而言,又分为四种:

 

一、 URI形式的绝对资源路径

 

如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/aaa.b

 

URLURI的特例。URL的前缀/协议,必须是Java认识的。URL可以打开资源,而URI则不行。

 

URLURI对象可以互相转换,使用各自的toURI(),toURL()方法即可!

 

二、 本地系统的绝对路径

 

D:/java/eclipse32/workspace/jbpmtest3/bin/aaa.b

 

Java.io包中的类,需要使用这种形式的参数。

 

但是,它们一般也提供了URI类型的参数,而URI类型的参数,接受的是URI样式的String。因此,通过URI转换,还是可以把URI样式的绝对路径用在java.io包中的类中。

 

三、 相对于classpath的相对路径

 

 如:相对于

 

file:/D:/java/eclipse32/workspace/jbpmtest3/bin/这个路径的相对路径。其中,bin是本项目的classpath。所有的Java源文件编译后的.class文件复制到这个目录中。

 

四、 相对于当前用户目录的相对路径

 

就是相对于System.getProperty("user.dir")返回的路径。

 

对于一般项目,这是项目的根路径。

 

对于JavaEE服务器,这可能是服务器的某个路径。这个并没有统一的规范!

 

所以,绝对不要使用相对于当前用户目录的相对路径。然而:

默认情况下,java.io 包中的类总是根据当前用户目录来分析相对路径名。此目录由系统属性 user.dir 指定,通常是 Java 虚拟机的调用目录。

 

这就是说,在使用java.io包中的类时,最好不要使用相对路径。否则,虽然在J2SE应用程序中可能还算正常,但是到了J2EE程序中,一定会出问题!而且这个路径,在不同的服务器中都是不同的!

 

 

相对路径最佳实践

推荐使用相对于当前classpath的相对路径,因此,我们在使用相对路径时,应当使用相对于当前classpath的相对路径

1) ClassLoader类的getResource(String name) getResourceAsStream(String name)等方法,使用相对于当前项目的classpath的相对路径来查找资源。

 

2) 读取属性文件常用到的ResourceBundle类的getBundle(String path)也是如此

通过查看ClassLoader类及其相关类的源代码,我发现,它实际上还是使用了URI形式的绝对路径。

 

相对路径本质上还是绝对路径

因此,归根结底java本质上只能使用绝对路径来寻找资源。所有的相对路径寻找资源的方法,都不过是一些便利方法。不过是API在底层帮助我们构建了绝对路径,从而找到资源。

下面是一些得到classpath和当前类的绝对路径的一些方法,你可能需要使用其中的一些方法来得到你需要的资源的绝对路径。

1FileTest.class.getResource("")

得到的是当前类FileTest.class文件的URI目录。不包括自己!

如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/com/test/

2FileTest.class.getResource("/")

得到的是当前的classpath的绝对URI路径。

如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

3Thread.currentThread().getContextClassLoader().getResource("")

得到的也是当前ClassPath的绝对URI路径。

如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

4FileTest.class.getClassLoader().getResource("")

得到的也是当前ClassPath的绝对URI路径。

如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

5ClassLoader.getSystemResource("")

得到的也是当前ClassPath的绝对URI路径。

如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/

 

我推荐使用Thread.currentThread().getContextClassLoader().getResource("")来得到当前的classpath的绝对路径的URI表示法。

 

 

public class PathUtil {

/***********************************************这些都是J2EE环境下的路径,不适合J2SE环境**************************************************************
* 1)obj.getClass().getClassLoader().getResource()>>>>>>>>>file:/E:/workspace/STY/Web/STY/WEB-INF/classes/(取到的classPath的路径)
* 2)obj.getClass().getClassLoader().getResource("/")>>>>>>>>null(是取不到路径的)
*
* 3)obj.getClass().getResource("")>>>>>>>>>file:/E:/workspace/STY/Web/STY/WEB-INF/classes/com/path/(取的是当前文件的文件夹路径,不包括该文件名)
* 4)obj.getClass().getResource("/")>>>>>>>>>file:/E:/workspace/STY/Web/STY/WEB-INF/classes/(取到的classPath的路径)
*
* 5)obj.getClass().getResource("1.xml")>>>>>>>>>file:/E:/workspace/STY/Web/STY/WEB-INF/classes/com/path/1.xml(可以使用相对路径)
* 6)obj.getClass().getClassLoader().getResource(com/path/1.xml"/")>>>>>>>>file:/E:/workspace/STY/Web/STY/WEB-INF/classes/com/path/1.xml(使用相对路径)
*
* 7)obj.getClass().getResource("/com/path/1.xml")>>>>>>>>file:/E:/workspace/STY/Web/STY/WEB-INF/classes/com/path/1.xml(使用相对路径)
*
* 总结:
* obj.getClass().getClassLoader().getResource()可以直接得到classpath,然后通过classpath进行相对地址取地址
* obj.getClass().getResource("/")也可以直接得到classpath,然后通过相对地址取地址
* obj.getClass().getResource("") 可以得到该类所存放的文件夹目录,然后通过相对地址取地址
***********************************************************************************************************************************************/
public static void main(String[] args) {

 

PathUtil obj = new PathUtil();

//1、obj.getClass().getClassLoader().getResource("")
String TestString = "obj.getClass().getClassLoader().getResource(" + ")";
System.out.println(TestString + ">>>>>>>>>" + obj.getClass().getClassLoader().getResource("com/../com/path/1.xml").getPath());

 

//2、obj.getClass().getClassLoader().getResource("/")
TestString = "obj.getClass().getClassLoader().getResource(" + ""/"" + ")";
System.out.println(TestString + ">>>>>>>>" + obj.getClass().getClassLoader().getResource("/"));


//3、obj.getClass().getResource("").getPath()
TestString = "obj.getClass().getResource("+""")";
System.out.println(TestString + ">>>>>>>>>" + obj.getClass().getResource("").getPath());

//4、obj.getClass().getResource("/")
TestString ="obj.getClass().getResource(" + ""/"" +")";
System.out.println(TestString + ">>>>>>>>>" + obj.getClass().getResource("/").getPath());

//5、obj.getClass().getResource("1.xml")
TestString = "obj.getClass().getResource("+""1.xml")";
System.out.println(TestString + ">>>>>>>>>" + obj.getClass().getResource("1.xml").getPath());

//6、obj.getClass().getClassLoader().getResource("com/path/1.xml")
TestString = "obj.getClass().getClassLoader().getResource(" + "com/path/1.xml"/"" + ")";
System.out.println(TestString + ">>>>>>>>" + obj.getClass().getClassLoader().getResource("com/path/1.xml").getPath());

//7、obj.getClass().getResource("/com/path/1.xml")
TestString = "obj.getClass().getResource(" + ""/com/path/1.xml"" +")";
System.out.println(TestString + ">>>>>>>>" + obj.getClass().getResource("/com/path/1.xml").getPath());

//8、获取文件的绝对地址(去掉路径前面的/)
String absolutePath= new File(obj.getClass().getResource("/com/path/1.xml").getPath()).getAbsolutePath();
System.out.println("absolutePath>>>>>>>>"+absolutePath);
String path = new File(obj.getClass().getResource("/com/path/1.xml").getPath()).getPath();
System.out.println("path>>>>>>>>"+path);
String pathIntetor = new File(absolutePath).getPath();
System.out.println("pathIntetor>>>>>>>>"+pathIntetor);

//9、取WEB-INF路径下的文件
String webInfPath = obj.getClass().getResource("/").getPath(); //得到classpath路径
webInfPath = webInfPath.substring(0, webInfPath.length()- "classes/".length())+"web.xml";
webInfPath = new File (webInfPath).getAbsolutePath();
System.out.println("webInfPath>>>>>>>>"+webInfPath);

//10、Thread类,得到的是claspath路径
String threadPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
threadPath = new File(threadPath).getAbsolutePath();
System.out.println("threadPath>>>>>>>>"+threadPath);

//11、ClassLoader.getSystemResource("")

String classLoaderPath = ClassLoader.getSystemResource("").getPath();

//threadPath = new File(threadPath).getAbsolutePath();
System.out.println("classLoaderPath>>>>>>>>"+classLoaderPath);

}

 

}

 

 

 

 

终极path解决方案

 

public class ResourceLoaderUtil{

 

private static Log log = LogFactory.getLog(ResourceLoaderUtil.class);

//向上寻址分隔符
private final static String updest ="../";

//向下寻址分隔符
private final static String forwarddest= "/";

/**
* @Description:通过相对路径获取到制定的文件输入流
* @param relativePath
* @return
* @throws MalformedURLException
* @throws IOException
* @author wangweifeng
* @since:2014-10-24 下午04:23:55
*/
public static InputStream getStream(String relativePath) throws MalformedURLException, IOException {
return ResourceLoaderUtil.getStream(ResourceLoaderUtil.getExtendResource(relativePath));
}

/**
* @Description:根据提供的URL,返回文件的流
* @param url
* @return
* @throws IOException
* @author wangweifeng
* @since:2014-10-24 下午04:25:23
*/
public static InputStream getStream(URL url) throws IOException {
if (url != null) {
return url.openStream();
} else {
return null;
}
}
/**
* @Description:根据相对地址获取到Properties文件
* @param resource
* @return
* @author wangweifeng
* @since:2014-10-24 下午04:38:42
*/
public static Properties getProperties(String resource) {
Properties properties = new Properties();
try {
properties.load(getStream(resource));
} catch (IOException e) {
throw new RuntimeException("couldn't load properties file '" + resource + "'", e);
}
return properties;
}

/**
* @Description:根据相对地址返回制定资源文件
* @param relativePath
* @return
* @author wangweifeng
* @since:2014-10-24 下午04:53:07
*/
public static File getFile(String relativePath) {
try {
File file = new File(ResourceLoaderUtil.getExtendResource(relativePath).getPath());
return file;
} catch (Exception e) {
throw new RuntimeException("couldn't load file '" + relativePath + "'", e);
}
}

/**
* 思路:
* 1、当前路径,或者classpath内寻址
* 2、以"/"开始的寻址相对路径等于"",即从classpath路径开始
* 3、处理"/"之后的寻址的相对路径,不含有向上寻址的可能性,直接用clasLoader寻址
* 4、处理"/"之后的寻址的相对路径含有向上寻址符,则开始进行寻址逻辑
**/
public static URL getExtendResource(String relativePath) throws MalformedURLException {
ResourceLoaderUtil.log.info("传入的相对路径:" + relativePath);
URL resourceAbsoluteURL = null;
// 不以"../"(向上)或以"/"(向下)开头,即取的是claspath路径下的文件
if ((!relativePath.contains(updest)) && (!relativePath.startsWith(forwarddest))) { // 当前路基
resourceAbsoluteURL = ResourceLoaderUtil.getResource(relativePath);
System.out.println("相对寻址完成后路径为>>>>" + resourceAbsoluteURL);
return resourceAbsoluteURL;
}
if (relativePath.substring(0, 1).equals(forwarddest)) {
relativePath = relativePath.substring(1);
if ("".equals(relativePath) || !(relativePath.contains(updest))) {
return getExtendResource(relativePath);
}
}
// 从classpath向下寻址
String classPathAbsolutePath = ResourceLoaderUtil.getAbsolutePathOfClassLoaderClassPath();
// 有效寻址路径
String wildcardString = relativePath.substring(0, relativePath.lastIndexOf(updest) + updest.length());
relativePath = relativePath.substring(relativePath.lastIndexOf(updest) + updest.length());

 

classPathAbsolutePath = ResourceLoaderUtil.cutLastString(classPathAbsolutePath, wildcardString, updest);
String resourceAbsolutePath = classPathAbsolutePath + relativePath;
ResourceLoaderUtil.log.info("绝对路径:" + resourceAbsolutePath);
resourceAbsoluteURL = new URL(resourceAbsolutePath);
System.out.println("相对寻址完成后路径为>>>>" + resourceAbsoluteURL);
return resourceAbsoluteURL;
}

/**
* @Description:得到加载Java类,使用全限定类名。
* @param className
* @return
* @author wangweifeng
* @since:2014-10-24 下午01:15:39
*/
private static Class loadClass(String className) {
try {
return getClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException("class not found '" + className + "'", e);
}
}
/**
* @Description:得到类加载器
* @return
* @author wangweifeng
* @since:2014-10-24 下午01:14:39
*/
private static ClassLoader getClassLoader() {
return ResourceLoaderUtil.class.getClassLoader();
}

/**
*得到本Class所在的ClassLoader的Classpath的绝对路径。
*URL形式的
*@return
*/
private static String getAbsolutePathOfClassLoaderClassPath() {
ResourceLoaderUtil.log.info(ResourceLoaderUtil.getClassLoader().getResource("").toString());
return ResourceLoaderUtil.getClassLoader().getResource("").toString();
}

/**
* @Description:根据classLoader获取资源地址
* @param resource
* @return URL
* @author wangweifeng
* @since:2014-10-24 下午02:11:26
*/
private static URL getResource(String resource) {
ResourceLoaderUtil.log.info("传入的相对于classpath的路径:" + resource);
return ResourceLoaderUtil.getClassLoader().getResource(resource);
}

 


/**
* @descroption:相对寻址的核心方法
* @param 根据relativePath中包含向上寻址部分,获兑正确地址
* @param source == classPathAbsolutePath 相对地址
* @param relativePath 部分相对地址 ../lib/../../
* @param dest向上寻址分隔符,此处定义为../
* @author wangweifeng
* @since:2014-10-24 下午03:00:23
*/
private static String cutLastString(String source, String partRelativePath, String dest) {
if (partRelativePath.startsWith(dest)) {// 向上寻址一次
source = source.substring(0, source.lastIndexOf("/", source.length() - 2) + 1);
partRelativePath = partRelativePath.substring(dest.length());
System.out.println(source);
} else {
String forWordPath = partRelativePath.substring(0, partRelativePath.indexOf(dest));
partRelativePath = partRelativePath.substring(partRelativePath.indexOf(dest));
source = source + forWordPath;
System.out.println(source);
}
if (!"".equals(partRelativePath)) {
cutLastString(source, partRelativePath, dest);
}
return source;
}

 

 

 

 

 

 

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/richelle009/p/4053615.html