谈谈Java开发中遇到的资源文件路径问题(二)

在 谈谈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/。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值