我们用java做web应用的时候,最后会部署到服务器中,一般就是一个war包,或者是ear包。同时,我们常常需要读取一些固定路径的文件内容,比如针对某个功能的配置文件,比如某个jar包中的文件等。当我们需要做到这些的前提,就是知道文件或者jar的决定路径,这样我们可以通过File的API来获取其中的内容。
获取一个web应用的部署路径,一般有2种方式:
1.从request中获取,也就是当客户端向服务端发送请求时,截取其中的请求路径中内容来获取应用的部署路径,这是一种常用的方法。下面以jsf的请求为例
war包部署的路径:
public static String getDeployWarPath() {
FacesContext ctx = FacesContext.getCurrentInstance();
String deployPath = ((ServletContext) ctx.getExternalContext().getContext()).getRealPath("/");
if (!deployPath.endsWith(String.valueOf(File.separatorChar)))
deployPath += File.separatorChar;
if (deployWarPath == null) {
deployWarPath = deployPath;
}
return deployPath;
}
ear包部署的路径:
public static String getDeployEarPath() {
String deployPath = getDeployWarPath();
deployPath = deployPath.substring(0, deployPath.lastIndexOf(File.separatorChar));
deployPath = deployPath.substring(0, deployPath.lastIndexOf(File.separatorChar));
deployPath = deployPath + File.separatorChar;
return deployPath;
}
这种获取方式有一个致命缺陷,就是需要应用启动运行,并且有请求发生时,才能从servlet中获取,一旦你需要在应用启动的时候获取,那么就无能为力了,下面介绍第二种获取方式
2.通过java的类加载获取
我们都知道,java虚拟机会将java文件编译成.class文件。对于一个web应用,这些文件有2个去处。src下面的会被存放到WEB-INF\classes文件夹下面,如果是关联jar的方式,那么会被编译成.class的jar包,放到WEB-INF\lib下面,java的类加载机制决定了我们可以通过这种途径来获取。
public class JsfHelper
{
public static String deployWarPath = null;
static {
URL url = JsfHelper.class.getResource("JsfHelper.class");
String temppath = url.toString();
int startIndex = temppath.indexOf("file:");
int index = temppath.indexOf("WEB-INF");
deployWarPath = temppath.substring(startIndex + "file:".length() + 1, index);
// 如果是linux的操作系统,并且开始没有file分隔符的话,那么要加上
if (System.getProperty("os.name").indexOf("Linux") != -1) {
if (!deployWarPath.startsWith(File.separator)) {
deployWarPath = File.separator + deployWarPath;
}
}
}
}
在JsfHelper类里面有个静态代码区,这块static包含的代码会在类加载的时候运行仅有的一次,一般我们为了兼容windows和linux,file的分隔符不会写死/,而是会写成File.separator ,同时上面那段代码有个针对linux的特殊处理,linux上路径以分隔符开始,windows下面是以盘名开始的,有点不一样。