首先,Java中的getResourceAsStream获取项目下的指定资源有以下几种:
一:获取src下的指定资源
1 通过Class.getResource 来获取。 path 不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下(即'/'代表src)获取。其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源
//必须要从根节点进行获取,即以/ 开头
TempMain.class.getResource("/application.yml");
2 Class.getResourceAsStream 与Class.getResource 一样,只是将获取到的URL 进行了流的处理
TempMain.class.getResourceAsStream("/application.yml");
3 Class.getClassLoader.getResourceAsStream(String path) :默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。
TempMain.class.getClassLoader().getResourceAsStream("application.yml");
4 备注:
如果当前项目里引用里其他的jar 包,并且在相同的路径下存在着相同的文件,那么也会读取到,spring 的starter 就是利用改机制来发现配置类,从而实现自动装配的
二:获取web项目下的指定资源
1)、 ServletContext. getResourceAsStream(String path):默认从WebAPP根目录(即:要发布在服务器下的项目的根目录(与src同级的web文件夹下))下取资源,path是否以’/'开头无所谓;
A)、在web项目的根目录下有myfile.xml文件,则应该使用:
getServleContext().getResourceAsStream("myfile.xml");
2)、Jsp下的application内置对象就是上面的ServletContext的一种实现
三 获取指定包下的所有class类
需要先将包名转化为路径名,比如讲org.apache 转换为 org/apache ,然后通过循环遍历找到该文件下有哪些类,然后在将路径名转化为类名,通过反射即可拿到。
或者通过第一步获取到了资源文件 , 然后通过解析资源文件, 获取到对应的ClassName ,然后通过反射来实现 。 (可以使用Spring 中的 ClassReader )
四 获取jar包里的class文件
先通过第一种方法获取到对应的jar文件,然后通过
1.通过jarFile
JarFile jarFile = new JarFile(file);
2 通过 jarInputStream ,Demo里有
获取到jarFile,接着通过第三部即可
五 demo
public class ClassUtil {
private static final byte[] JAR_MAGIC = {'P', 'K', 3, 4};
public static void main(String[] args) throws IOException {
ClassUtil classUtil = new ClassUtil();
List<Class> classes = classUtil.listClass("com.google");
System.out.println(classes);
}
public List<Class> listClass(String packageName) throws IOException {
List<String> list = listResource(packageName);
List<Class> result = new ArrayList<>();
for (String name : list) {
name = name.substring(0, name.lastIndexOf(".")).replace("/", ".");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
Class<?> aClass = classLoader.loadClass(name);
result.add(aClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return result;
}
public List<String> listResource(String packageName) throws IOException {
String path = packageName.replace(".", "/");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource(path);
URL jarUrl = findJarForResource(url);
// 如果是jar包的话
if (jarUrl != null) {
return listResources(new JarInputStream(jarUrl.openStream()), path);
}
InputStream is = url.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
List<String> resources = Lists.newArrayList();
String line;
while ((line = reader.readLine()) != null) {
//如果是类的话
if (line.indexOf(".class") > 0) {
resources.add(path + "/" +line);
// 是目录的话
}else{
List<String> children = listResource(path + "/" + line);
if(children!=null && children.size()>0){
resources.addAll(children);
}
}
}
reader.close();
return resources;
}
private URL findJarForResource(URL url) throws IOException {
String jarUrl = url.getPath();
int index = jarUrl.indexOf(".jar");
if (index < 0) {
return null;
}
jarUrl = jarUrl.substring(0, index + 4);
URL testUrl = new URL(jarUrl);
if (isJar(testUrl)) {
return testUrl;
}
return null;
}
// 通过文件的魔数来判断是否是jar 文件
private boolean isJar(URL testUrl) throws IOException {
InputStream inputStream = testUrl.openStream();
byte[] buffer = new byte[JAR_MAGIC.length];
inputStream.read(buffer, 0, JAR_MAGIC.length);
if (Arrays.equals(JAR_MAGIC, buffer)) {
return true;
}
inputStream.close();
return false;
}
// 通过jar 来获取resourced
protected List<String> listResources(JarInputStream jar, String path) throws IOException {
//为path 在开头和末尾添加 /
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.endsWith("/")) {
path = path + "/";
}
List<String> resources = new ArrayList<>();
for (JarEntry entry; (entry = jar.getNextJarEntry()) != null; ) {
if (!entry.isDirectory()) {
StringBuilder name = new StringBuilder(entry.getName());
// 进行文件名的统一
if (name.charAt(0) != '/') {
name.insert(0, '/');
}
if (name.indexOf(path) == 0) {
// 去掉开头的斜杠
resources.add(name.substring(1));
}
}
}
return resources;
}
}