路径获取常用方法:
Javaweb的不常用方法:
以工程名为/DemoWeb为例:
访问的jsp为:http://localhost:8080/DemoWeb/test/index.jsp
1 JSP中获得当前应用的相对路径和绝对路径
(1)得到工程名:request.getContextPath()
结果:/DemoWeb
(2)得到包含工程名的当前页面全路径:request.getRequestURI()
结果:/DemoWeb/test/testpath.jsp
(3)得到IE地址栏地址:request.getRequestURL()
结果:http://localhost:8080/DemoWeb/test/testpath.jsp
(4)得到当前页面所在目录下全名称:request.getServletPath()
结果:/test/testpath.jsp
(5)得到页面所在服务器的全路径(实际的路径):application.getRealPath(“testpath.jsp”)
结果:D:\Develop Files\apache-tomcat-5.5.15\apache-tomcat-5.5.15\webapps\DemoWeb\testpath.jsp
D:\Develop Files\apache-tomcat-5.5.15\apache-tomcat-5.5.15为tomcat的安装路径
2.java 的Class中获得相对路径,绝对路径的方法
(1)类的绝对路径:
System.out.println(TestPath.class.getResource("/").getPath());
结果:/E:/workspace/workspace_tcc/DemoWeb/WebRoot/WEB-INF/classes/
System.out.println(TestPath.class.getResource(""));
结果:file:/E:/workspace/workspace_tcc/DemoWeb/WebRoot/WEB-INF/classes/demo1/
(2)得到工程的路径:System.getProperty(“user.dir”)
结果:E:\workspace\workspace_tcc\DemoWeb
(3)获取WEB-INF路径:request.getServletContext().getRealPath("/") 有误
结果:E:/workspace/workspace_tcc/DemoWeb/WebRoot/WEB-INF/
个人实践获取javaweb路径
this.getServletContext()和req.getServletContext()都是通过ServletContext()来获取路径
String realPath1 = this.getServletContext().getRealPath("/");
String realPath2 = this.getServletContext().getRealPath("/WEB-INF/upload");
String realPath3 = req.getServletContext().getRealPath("/");
System.out.println(realPath1);
System.out.println(realPath2);
System.out.println(realPath3);
结果:(项目名称:smbms)
E:\javaWEB\apache-tomcat-9.0.40\webapps\smbms\
E:\javaWEB\apache-tomcat-9.0.40\webapps\smbms\WEB-INF\upload
E:\javaWEB\apache-tomcat-9.0.40\webapps\smbms\
Java项目中根据相对路径和绝对路径获取文件的方法
首先,项目中文件分布情况如下,innerFile.txt位于test.test包下,innerInnerFile.txt位于test.test.inner包下,outterFile.txt位于包的根目录下,
那么,在App类里,如何根据相对路径、绝对路径获取innerFile.txt、innerInnerFile.txt和outterFile.txt呢?
class.getResource(name)
先来看一下Class.getResource(name)
方法,该方法接收一个表示文件路径的参数,返回一个URL对象,该URL对象表示的name指向的那个资源(文件)。这个方法是在类中根据name获取资源。其中,name可以是文件的相对路径(相对于该class类来说),也可以是绝对路径(绝对路径的话,根目录符号/
是代表项目路径而不是磁盘的根目录)。例如,如下两种根据路径获取文件的效果是一样的 :
App.class.getResource('innerFile.txt')
App.class.getResource('/test/test/innerFile.txt')
由于innerFile.txt和App类是在同一个包下,所以通过App.class和相对路径可以获取到App这个类的包下面的innerFile.txt文件。而当传入的是绝对路径/test/test/innerFile.txt
,getResource()方法是从项目的包的根目录开始解析路径的。所以这两种获取文件的效果是一样的。
classLoader.getResource(name)
该方法的作用与class.getResource(name)
的作用一样,接收一个表示路径的参数,返回一个URL对象,该URL对象表示name对应的资源(文件)。但是,与class.getResource(name)
不同的是,该方法只能接收一个相对路径,不能接收绝对路径如/xxx/xxx
。并且,接收的相对路径是相对于项目的包的根目录来说的。比如,如下两种获取文件的效果是一样的:
App.class.getResource('innerFile.txt')
App.class.getClassLoader().getResource('test/test/innerFile.txt')
classLoader.getResource('test/test/innerFile.txt')
是相对于项目的包的根目录来解析路径的,所以通过该路径能够获取到innerFile.txt,并且不能传入绝对路径,否则报错。
介绍完了这两种,那么应该能够根据这两种方法分别获取到innerInnerFile.txt文件和outterFile.txt文件吧?
class.getResource(name)与classLoader.getResource(name)的联系
如上所述,class.getResource(name)
能够接受相对路径和绝对路径,而classLoader.getResource(name)
只能接收相对路径,那么这两种方法的联系是什么呢?
通过查看class.getResource(name)
源码,可以看到,class.getResource(name)
最终其实是通过classLoader.getResource(name)
来获取资源文件的,如,
// class.getResource(name)方法
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name);
}
其中,class.getResource(name)
首先会对name进行解析和处理,如,
// class.getResource(path)中对path预处理path = resolveName(path)
private String resolveName(String name) {
if (name == null) {
return name;
}
if (!name.startsWith("/")) {
Class<?> c = this;
while (c.isArray()) {
c = c.getComponentType();
}
String baseName = c.getName(); // 获取带包路径的类名,此处类名是App,包的路径是test.test,所以baseName就是test.test.App。
int index = baseName.lastIndexOf('.');
if (index != -1) {
name = baseName.substring(0, index).replace('.', '/') // 给参数加上当前类所在的包的路径前缀,即在name之前加上test/test,之后会委托给classLoader来getResource(path),而classLoader默认是从项目根路径获取资源的。
+"/"+name;
}
} else {
// path以'/'开头,则去掉开头的'/',采用classLoader.getResource(去掉开头'/'后的path)来获取资源。
name = name.substring(1);
}
return name;
}
其中,如果传入的是绝对路径,那么去掉最前面的/
,然后会委托给classLoader.getResource(name)
处理;如果传入的是相对路径,那么首先获取到当前class类的完整包名,把包名中的.
替换成/
,也就是说,App类获取到包名是test.test.App
,那么会被替换成test/test/App
,然后委托给classLoader.getResource(name)
处理。
总结
class.getResource(name)
中name可以写成绝对路径/test/test/innerFile.txt
和相对路径【假设该class位于test.test包下】”innerFile.txt”,其中绝对路径的/
是相当于项目的classpath根目录,相对路径是相对于当前class的路径。而classLoader.getResource(name)
中的name一定要写成相对路径如test/test/innerFile.txt
(最前面不能是/
),并且这个相对路径是相对于项目的classpath根目录的路径,相当于class.getResource(name)
中写绝对路径/test/test/innerFile.txt
。
这2个方法都是返回URL对象,接着可以通过getPath()方法获取String类型的路径:
this.getClass.getClassLoader().getResource('test/test/innerFile.txt').getPath
()
可以通过这个方式直接获取输入流:
InputStream is = TemplateExcelUtils.class.getClassLoader().getResourceAsStream("template/"+sourcePath);
注意:class.getResource()和classLoader.getResource()获取的路径可以从项目根路径开始的,项目根路径指的是如图:(我们打包后的项目中,层级是下图所示的层级)