D:\Myeclipse10\Common\plugins\com.genuitec.eclipse.easie.tomcat.myeclipse_9.0.0.me201109141806\tomcat\bin\
在 谈谈Java开发中遇到的资源文件路径问题(一) 中,我们已经聊了开发JavaSe应用程序的相对路径问题。
现在就聊聊开发web应用时,相对路径的问题吧。
这是我在myeclipse中新建的web工程的路径:D:\JAVA\MyEclipse10\ThreeDaysWeb
这是我tomcat服务器的路径(我的tomcat服务器是myeclipse集成进来的):
D:\JAVA\MyEclipse\Common\plugins\com.genuitec.eclipse.easie.tomcat.myeclipse_9.0.0.me201109141806\tomcat
这是我把web工程发布到tomcat服务上的路径:
D:\JAVA\MyEclipse10\.metadata\.me_tcat\webapps\ThreeDaysWeb
哎,集成进来的tomcat路径怎么看怎么不顺眼,米办法,将就着吧!
现在我们来发现以下相对路径的相对点是那个目录吧!!!
新建一个Servlet:
/ThreeDaysWeb/src/three/day/filepath/DbcfgServlet.java
新建一个普通Java类:
/ThreeDaysWeb/src/three/day/filepath/DbcfgNormal.java
代码如下:
package three.day.filepath;
import java.io.File;
import java.io.IOException;
public class DbcfgNormal {
public static void readCfgFile(String cfgFileName) throws IOException{
File file = new File(cfgFileName);
if(!file.exists()) file.createNewFile();
System.out.println(file.getAbsolutePath());
}
}
package three.day.filepath;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DbcfgServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("------------------Servlet类输出----------------");
readCfg01();
System.out.println("-----------------普通Java类输出-------------------");
DbcfgNormal.readCfgFile("dbcfg.properties");
}
private void readCfg01()
throws FileNotFoundException, IOException {
File file = new File("dbcfg.properties");
if(!file.exists()) file.createNewFile();
System.out.println(file.getAbsolutePath());
}
}
代码很简单,现在看看运行效果吧:
------------------Servlet类输出----------------
D:\JAVA\MyEclipse\Common\plugins\com.genuitec.eclipse.easie.tomcat.myeclipse_9.0.0.me201109141806\tomcat\bin\dbcfg.properties
-----------------普通Java类输出-------------------
D:\JAVA\MyEclipse\Common\plugins\com.genuitec.eclipse.easie.tomcat.myeclipse_9.0.0.me201109141806\tomcat\bin\dbcfg.properties
很吃惊吧,相对路径的参考点竟然是tomcat目录下的bin目录:
D:\JAVA\MyEclipse\Common\plugins\com.genuitec.eclipse.easie.tomcat.myeclipse_9.0.0.me201109141806\tomcat\bin
这样一来,我们就算我使用相对路径也没意思了。那这样一说,我们就只能使用绝对路径咯。那怎么获取web应用在文件系统中的绝对路径呢,不至于写死吧?
不怕,先看一下代码,
package three.day.filepath;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DbcfgServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*System.out.println("------------------Servlet类输出----------------");
readCfg01();
System.out.println("-----------------普通Java类输出-------------------");
DbcfgNormal.readCfgFile("dbcfg.properties");*/
getContextRealPath();
}
private void readCfg01()
throws FileNotFoundException, IOException {
File file = new File("dbcfg.properties");
if(!file.exists()) file.createNewFile();
System.out.println(file.getAbsolutePath());
}
private void getContextRealPath(){
String contextPath = getServletContext().getRealPath("");
System.out.println(contextPath);
}
}
运行效果如下:
D:\JAVA\MyEclipse10\.metadata\.me_tcat\webapps\ThreeDaysWeb
这个就是web应用部署在web服务器后,在文件系统中的绝路径,
看到这绝对路径以后是轻松很多了,你可以使用这个绝对路径创建、读写任何目录或文件啦
如:
String contextPath = getServletContext().getRealPath("");
File file01 = new File(contextPath + File.seperator + "filename.txt");
或者
File file02 = new File(contextPath ,"filename.txt");
如果文件不存在,就加上对应的创建代码:
file02.createNewFile();
或者创建新目录
file02.mkdirs();
另外,如果我想知道WebRoot目录下images这个文件夹在文件系统中的绝对路径,其实可以这样做
String contextPath = getServletContext().getRealPath("images");
System.out.println(contextPath);
这时的输出效果:
D:\JAVA\MyEclipse10\.metadata\.me_tcat\webapps\ThreeDaysWeb\images
这样就不用我拼接绝对路径了,就更加干脆了。
上面通过绝对路径获取web资源的路径的,下面聊聊如何通过类装载器获取web资源吧。
在web开发,为什么需要用到类装载器去获取资源呢?
我们知道,在Servlet类中,我们可以
String contextPath = getServletContext().getRealPath("images");这方法获取任意存在的web资源的绝对路径,然后使用绝对路径就可以操作资源,
但是如果是在普通Java类中,我们能使用getServletContext()这个方法吗?
当然你反问,你把getServletContext()的返回值 做为一个参数传给 一个普通类,那么普通类就可以和Servlet类一样使用绝对路径访问资源了。
可是这就不符合软件设计的思想了,增加了代码之间的耦合度,像我们学的ssh框架都是追求松耦合的。
这样,我们就想到在普通Java类中使用类装载器去读取资源文件咯。
记得,在谈谈Java开发中遇到的资源文件路径问题(一)中,谈到JavaSe应用通过类装载器读取资源时,使用相对路径的参考点是工程目录下的bin目录的,
那么在web应用中通过类装载器去读取资源,使用相对路径时,相对的是哪一个目录呢?
先看代码:
一个普通Java类,使用类装载器获取某个资源,这里下假设,web部署到tomcat服务后,在文件系统中的绝对路径(D:\JAVA\MyEclipse10\.metadata\.me_tcat\webapps\ThreeDaysWeb)
是 ClassLoader使用相对路径时的参考点
所以一开始,把配置文件dbcfg.properties放置在(D:\JAVA\MyEclipse10\.metadata\.me_tcat\webapps\ThreeDaysWeb)下
package three.day.filepath;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class DbcfgNormal {
public static void readCfgFile(String cfgFileName) throws IOException{
File file = new File(cfgFileName);
if(!file.exists()) file.createNewFile();
System.out.println(file.getAbsolutePath());
}
public static void loaderFindFile(String relativePath){
ClassLoader loader = DbcfgNormal.class.getClassLoader();
System.out.println(loader);
InputStream is = loader.getResourceAsStream(relativePath);
if(is != null)
System.out.println("has find the cfg file");
else
System.out.println("file not found");
}
}
在Servlet类调用普通类的服务:
package three.day.filepath;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DbcfgServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*System.out.println("------------------Servlet类输出----------------");
readCfg01();
System.out.println("-----------------普通Java类输出-------------------");
DbcfgNormal.readCfgFile("dbcfg.properties");*/
//getContextRealPath();
DbcfgNormal.loaderFindFile("dbcfg.properties");
}
private void readCfg01()
throws FileNotFoundException, IOException {
File file = new File("dbcfg.properties");
if(!file.exists()) file.createNewFile();
System.out.println(file.getAbsolutePath());
}
private void getContextRealPath(){
String contextPath = getServletContext().getRealPath("images");
System.out.println(contextPath);
}
}
运行效果:
WebappClassLoader
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@1742700
file not found
从上面输出结果,你是不是已经发现,tomcat是使用了自己的类装载器,其中repositories的属性值 /WEB-INF/classes/
是不是就是我们寻找的相对路径的参考点呢?
把配置文件dbcfg.properties放置在 /WEB-INF/classes/下
再次运行
效果如下:
WebappClassLoader
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@1742700
has find the cfg file
这次果真找到了文件,那有没有可能 /WEB-INF就是相对路径的参考点呢?把配置文件放在其下。
再运行
WebappClassLoader
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@1742700
file not found
文件找不到了,其实微微分析一下,也知道不可能的,
因为D:\JAVA\MyEclipse10\.metadata\.me_tcat\webapps\ThreeDaysWeb
跟D:\JAVA\MyEclipse10\.metadata\.me_tcat\webapps\ThreeDaysWeb\WEB-INF 这两个目录,
其实你可以理解成一个目录,既然放置在ThreeDaysWeb不可以,那WEB-INF也就不可以咯。
WEB-INF其实就是存放只有内部可以访问的资源。
最终,我们可以得出结论:在web应用中,通过类装载器获取资源,使用相对路径的参考点是/WEB-INF/classes/。
原文出处:http://blog.youkuaiyun.com/qq1130141391/article/details/12317333