目录
在开发环境中运行,如eclips
在src目录下
在非src目录下
以jar包形式运行,linux系统
在src目录下
在非src目录下,但在jar包内
在jar包外
jar包访问第三方依赖,的类路径配置
在开发环境中运行,如eclips
在src目录下
可以用绝对路径和相对路径来读取,绝对路径为文件在磁盘的存放位置,这里暂且不讨论。
用相对路径可按如下操作获取文件资源:
File file = new File("src/main/resources/properties/basecom.properties");
InputStream in = new FileInputStream(file);
也可以通过类加载方式:
//读取根目录下的tmp(src/):
// 第一种方法
InputStream in = App.class.getResourceAsStream("/tmp");
// 第二种方法
InputStream in =ClassLoader.getSystemClassLoader().getResourceAsStream("tmp");
//读取App类同级目录下的tmp(src/space/yukai)
// 第一种方法
InputStream in = App.class.getResourceAsStream("tmp");
// 第二种方法
InputStream in =ClassLoader.getSystemClassLoader().getResourceAsStream("space/yukai/tmp");
//第三种方法
InputStream in = App.class.getResourceAsStream("/space/yukai/tmp");
//读取MyClassloader同级目录下的tmp(src/space/yukai/classloader):
// 第一种方法
InputStream in = App.class.getResourceAsStream("classloader/tmp");
// 第二种方法
InputStream in =ClassLoader.getSystemClassLoader().getResourceAsStream("space/yukai/classloader/tmp");
//第三种方法
InputStream in = App.class.getResourceAsStream("/space/yukai/classloader/tmp");
在非src目录下
lib与src同级,想获取lib目录下的文件
File file = new File("./lib");
System.out.println(file.getAbsolutePath());
File[] listFiles = file.listFiles();
以jar包形式运行,linux系统
在src目录下
当将工程导出jar包或war包时可用以下方法获取
使用Class.getResource或者是ClassLoader.getResourceAsStream()将文件内容放到InputStream中
String s1 = this.getClass().getResource("/log4j.properties").getPath();
或者为:
String s1 = CodeTest.class.getResource("/log4j.properties").getPath();
注意,使用class的getRescource时,要注意路径前要加"/",即根目录,此处的根目录是src
若像如下使用:
String class_str = this.getClass().getResource("logback.xml").getPath();
则会出错如下:
使用ClassLoader时,如下:
this.getClass().getClassLoader().getResource()
在使用ClassLoader时,路径前面不能加"/",使用相对路径。
public void readProperties(){
String ss = TempTest.class.getResource("/").getPath();
System.out.println(ss);
String s = new File(ss).getParentFile().getPath();
System.out.println(s);
String system_str = System.getProperty("user.dir");
System.out.println(system_str);
}
运行结果如下:
将上述readProperties函数打包为jar包在命令行使用java -jar TempTest.jar运行时,结果如下:
由此可见,打包成jar包时和在ide中直接运行的结果并不一样,所以在jar包中的class类要访问自己jar包中的资源文件时,应该使用Class.getResource或者是getResourceAsStream放在InputStream中,再进行访问。但是该方法只能访问到src下的资源文件,因为其根目录对应的就是src,无法访问到项目根目录下src外的文件,如上述项目结构图中的blackWhite中的文件无法访问到,
关于class.getResource && classloader.getResource
源码中:Class.getResourceAsStream(String name)
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
上面的代码可以看出, Class.getResourceAsStream(String name) 最终还是调用了 classloader.getResourceAsStream(String name) 。但是两者还是有一些区别的,注意 name =resolveName(name)这一行,Class.getResourceAsStream(String name)在这里做了一些处理:Class.resolveName(String name)
通过测试类进行测试:
public class App {
public static void main(String[] args) {
System.out.println("App.class.getClassLoader().getResource(\"\") : " +
App.class.getClassLoader().getResource(""));
System.out.println("App.class.getClassLoader().getResource(\"/\") : " +
App.class.getClassLoader().getResource("/"));
System.out.println("App.class.getResource(\"\") : " + App.class.getResource(""));
System.out.println("App.class.getResource(\"/\") : " + App.class.getResource("/"));
}
}
结果如下:
App.class.getClassLoader().getResource("") :
file:/D:/workspace/eclipse/cluster/TestClassloader/bin/
App.class.getClassLoader().getResource("/") : null
App.class.getResource("") :
file:/D:/workspace/eclipse/cluster/TestClassloader/bin/space/yukai/
App.class.getResource("/") : file:/D:/workspace/eclipse/cluster/TestClassloader/bin/
calssloder.getResource("")方法返回了classpath根路径(eclipse工程中,编译生成的类文件存放在/bin目录下);
calssloder.getResource("/")方法返回null,说明calssloder.getResource不支持以"/"开头的参数;
class.getResource("")方法返回了App.class所在的路径;
class.getResource("/")与calssloder.getResource("")表现一致,返回了classpath的根路径
在非src目录下,但在jar包内
如图想打jar包后能继续访问lib中的json文件,可以用JarFile类来实现。
package com.test.jar;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ReadSource {
public static void main(String[] args) throws Exception {
String path = ReadSource.class.getProtectionDomain().getCodeSource().getLocation().getPath();//获取jar包的绝对路径
path = java.net.URLDecoder.decode(path, "UTF-8");//转换处理中文及空格,但是如果路径中包含中文,就会变成带“%xx%xx”格式的字符串。所以应该这样写才对:
System.out.println("path: "+path);
JarFile localJarFile = new JarFile(new File(path));
Enumeration<JarEntry> entries = localJarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
System.out.println(jarEntry.getName());
String innerPath = jarEntry.getName();
if(innerPath.contains(".json")&& !innerPath.contains("jar")){
InputStream inputStream =
ReadSource.class.getClassLoader().getResourceAsStream(innerPath);
BufferedReader br = new BufferedReader(new
InputStreamReader(inputStream));
String line="";
while((line=br.readLine())!=null){
System.out.println(innerPath+"内容为:"+line);
}
}
}
}
}
结果:
在jar包外
比如在jar包同级目录下有名为testInfo的文件夹,
File file = new File("./testInfo");可获取该文件夹对象。
file.getAbsolutePath();可获取该文件夹对象的绝对路径。
jar包访问第三方依赖,的类路径配置
手动配置MANITAST.MF中的class_path配置,即需要的第三方jar包
打包可执行jar包时,MANIFEST.MF总是个让人头疼的东西,经常出现这种那种问题。
一个例子:
Manifest-Version: 1.0
Main-Class: test.Main
Class-Path: ./ ./lib/commons-collections-3.2.jar ./lib/commons-dbcp-1.2.2.jar ./lib/commons-lang-2.3.jar ./lib/commons-logging-1.1.jar
各部分解释:
Manifest-Version MF文件版本号
Main-Class 包含main方法的类
Class-Path 执行这个jar包时的ClassPath
以下是需要注意的各个要点:
- Manifest-Version、Main-Class和Class-Path后面跟着一个英文的冒号,冒号后面必须跟着一个空格,然后才是版本号、类和ClassPath。
- Class-Path中的各项应使用空格分隔,不是逗号或分号。
- Class-Path中如果有很多项,写成一行打包的时候会报错line too long,这时需要把Class-Path分多行写。注意:从第二行开始,必须以两个空格开头,三个以上我没试过,不过不用空格开头和一个空格开头都是不行的,我已经试过了。
- Class-Path写完之后最后一定要有一个空行。
5. jar包内有些配置文件想放在jar包外面,比如文件config.properties:如果这个文件是以路径方式载入的,比如new file("./config/config.properties"),那么将config.properties放在jar包相同目录下的config目录下即可,也就是说“./”路径等价于jar包所在目录;如果这个文件是以ClassPath下的文件这种方式载入的,比如在Spring中载入classpath:config.properties,则在MF文件的配置文件的ClassPath中添加“./”,然后将这个配置文件与jar包放在同一个目录即可,当然也可以在MF文件的配置文件的ClassPath中添加“./config/”,然后把配置文件都放在jar包相同目录下的config目录下。