今天的工具功能是包扫描,只需要调用指定方法,输入想要查询的包名称,就可以自动查询得到该路径下所有的类(包括jar包),该工具实现了一个抽象方法供使用者使用,用这个方法可以去筛选该包下的类达到自己的目的。
package com.mec.mpring.core;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public abstract class PackageScanner {
public PackageScanner() {
}
//因为扫描到的类的相关具体操作不是本工具需要完成的,
//因此给一个抽象方法,具体操作由工具使用者完成。
//用这个方法可以去筛选使用者需要扫描的包下的类达到自己的目的。
public abstract void dealClass(Class<?> klass);
//处理普通包,注意这里面有递归,如果找到类就调用dealClass方法,若包下还有包,那么就要继续调用自身进行扫描,知道扫描结束。
private void dealPackage(File cur, String packageName) {
File[] files = cur.listFiles();
for (File file : files) {
if (file.isFile()) {
String fileName = file.getName();
if (!fileName.endsWith(".class")) {
continue;
}
fileName = fileName.replace(".class", "");
String className = packageName + "." + fileName;
try {
Class<?> klass = Class.forName(className);
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
dealPackage(file, packageName + "." + file.getName());
}
}
}
//处理jar包,需要注意的是,如果要扫描自己写的jar包,那么导出jar包时必须勾选 add directory entries选项,否则扫描失败。
private void dealJar(URL url) {
try {
JarURLConnection connection = (JarURLConnection) url.openConnection();
JarFile jarFile = connection.getJarFile();
Enumeration<JarEntry> entryList = jarFile.entries();
while (entryList.hasMoreElements()) {
JarEntry jarEntry = entryList.nextElement();
if (jarEntry.isDirectory() || !jarEntry.getName().endsWith(".class")) {
continue;
}
String className = jarEntry.getName();
className = className.replace(".class", "");
className = className.replace('/', '.');
try {
Class<?> klass = Class.forName(className);
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//这个方法是使用者需要调用的方法,它可以实现普通包和jar包的扫描。使用者只需提供包路径(例如:com.mec.util)即可。
public void scanPackage(String packageName) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String pathName = packageName.replace('.', '/');
try {
synchronized (pathName) {
}
Enumeration<URL> urls = classLoader.getResources(pathName);
System.out.println("urls" +" " + urls);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
System.out.println("url" +" "+ url);
System.out.println("url.getProtocol()" +" " + url.getProtocol());
if (url.getProtocol().equals("jar")) {
dealJar(url);
} else {
try {
File curFile = new File(url.toURI());
dealPackage(curFile, packageName);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
如上图所示:右边是代码示例。我扫描的包是com.mec.rmi,所以工具将该目录下所有类都输出了,用粉色圈出来的是RMIServer的内部类,也输出了。
今天的工具就介绍到这里吧。欢迎批评指正~