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

前言

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

Java路径

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

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

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

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

URL和URI对象可以互相转换,使用各自的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和当前类的绝对路径的一些方法,你可能需要使用其中的一些方法来得到你需要的资源的绝对路径。

1,FileTest.class.getResource("")

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

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

2,FileTest.class.getResource("/")

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

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

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

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

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

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

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

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

5,ClassLoader.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;
}

时间: 2024-10-22 12:44:41

Java在J2EE工程中路径寻址问题终极解决方案的相关文章

[Java][Web]Web 工程中的各类地址的写法

// 1. request.getRequestDispatcher("/index.html").forward(request,response); // 以 / 开头,对于浏览器 / 表示网站,对于服务器 / 表示当前的 web应用 // \ 反斜杠 用于访问硬盘资源的路径分隔符 // 2. response.sendRedirect("/day05/index.html"); // 3. this.getServletContext().getRealPat

Bootstrap轮播(carousel)插件中图片变形的终极解决方案——使用jqthumb.js

在顶求网的首页中我使用了BootStrap的轮播(carousel)插件来展示文章中的图片.我在程序中自动抓取文章的第一张图片作为该轮播控件中要显示的图片,由于文章的图片大小不一,而轮播插件的大小基本是固定的,所以展示的时候图片出现了变形.在网上找了很多中方式也没有解决(过程曲折,不再赘述),直到找到了这款Jquery的缩放插件——jqthumb.js.下面来看看如何使用它以及如何利用它来控制轮播控件中图片的大小,而且能够做到不变形,可以显示图片的主要部分(类似于微信朋友圈的图片混排效果——不知

在vs2012 中配置opencv的终极解决方案

总结一下在配置opencv的步骤(VS2012+opencv2.4.8) 1. 配置环境变量,配置好环境变量之后有可能要重启计算机才会有效,我就属于这种情况. 我们首先要在 计算机-属性-高级系统设置-环境变量 里添加你的opencv 路径, 我的opencv直接安装在C盘,有些文章里讲在 系统变量里添加路径,我这里用户变量和系统变量都添加了,如下:我的计算机是win7 64 位,所以我x86 和x64都添加进去了,因为可能在VS里面debug时切换64位和32位进行调试. 2.在VS里添加op

Java前辈:学习J2EE流程中的经验和教训

Java前辈:学习J2EE流程中的经验和教训 在这里我谈谈我在学习j2ee流程,并谈到在此过程中领会的经验和教训.以便后来者少走弯路. Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE.这三块相互补充,应用范围不同. J2SE就是Java2的标准版,主要用于桌面应用软件的编程: J2ME主要应用于嵌入是系统开发,如手机和PDA的编程: J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统. 先学习j2se 要学习j2ee就要先学习j2

Eclipse工程中关联Java源代码 !

Eclipse中看Java源代码 Eclipse工程中关联Java源代码 ! JavaEclipseJDKCC++如何在Eclipse sdk中查看jar源代码如:*.jar 1.点 "window"-> "Preferences" -> "Java" -> "Installed JRES" 2.此时"Installed JRES"右边是列表窗格,列出了系统中的 JRE 环境,选择你的JR

Java路径问题终于解决方式—可定位全部资源的相对路径寻址

1.在Java项目中,应该通过绝对路径訪问文件.下面为訪问的经常用法: 第一种方法:类名.class.getResource("/").getPath()+文件名称 另外一种方法:Thread.currentThread().getContextClassLoader().getResource("").getPath()+文件名称[主要使用] 如果文件夹结构例如以下 如今src文件夹下的类文件须要訪问config文件夹下的配置文件. 2.使用第一种方法 new F

Java路径问题最终解决方案—可定位所有资源的相对路径寻址

1.在Java项目中,应该通过绝对路径访问文件,以下为访问的常用方法: 第一种方法:类名.class.getResource("/").getPath()+文件名 第二种方法:Thread.currentThread().getContextClassLoader().getResource("").getPath()+文件名[主要使用] 假设目录结构如下 现在src目录下的类文件需要访问config目录下的配置文件. 2.使用第一种方法 new FileInput

Eclipse的Java工作集和多工程构建路径

一.Java工作集: Eclipse有一个小功能,就是创建Java Working Set.它的作用是解决Package Explorer窗格中创建很多工程时出现拥挤的麻烦. 在创建(New对话框)时可以加入原来存在的Java工程.创建完后,在左方Package Explorer窗格的右上方下拉菜单中选择Select Working Set然后选择Selected Working Sets打开创建的工作集.之后切换就可以直接在下拉菜单中选择即可(自动出现在下拉菜单中). 如果希望加入新的工程到工

web工程中的各种路径(eclipse开发)

目前遇到的 web 工程中要写url和路径的文件有 webContent中.jsp/.html src中的servlet类 src非servlet类的普通类 .jsp/.html form表单提交的action 1. 跳转到.jsp 使用相对路径,相对于web工程根目录 <!-- from JSP1.jsp to JSP2.jsp --> <!-- JSP1.jsp中的form --> <form action="File/JSP2.jsp"> &l