【Java】包扫描工具(含jar包)

本文详细介绍了一种用于扫描Java包和类的工具,包括普通包扫描和jar包扫描的方法。通过递归遍历目录和处理class文件,实现了对指定包及其子包内所有类的查找。同时,介绍了如何通过URL判断包的类型并进行相应处理。

 包扫描工具:

 

1.普通包扫描:

 

	// 需要包的路径和包名称
	private void packageScanner(String packagePath, String packageName) {
		// 通过包路径得到当前文件
		File currentFile = new File(packagePath);
		
		if(!currentFile.exists()) {
			return;
		}
		// 得到当前文件下的所有文件
		// 通过文件过滤器接口得到所有的目录类型的文件
		File[] listFile = currentFile.listFiles(new FileFilter() {
			
			// 若当前文件是目录则返回true,否则就是最终的class文件
			// java内部最终执行的是对源码预编译的字节码文件,是class文件
			@Override
			public boolean accept(File pathname) {
				if (currentFile.isDirectory()) {
					return true;
				}
				return pathname.getName().endsWith(".class");
			}
		});
		// 递归遍历,扫描所有的目录,并更新当前目录的路径
		for (File file : listFile) {
			if (file.isDirectory()) {
				packageScanner(file.getAbsolutePath(),
						packageName + "." + file.getName());
			} else {
				// 扫描到类时,去除后缀,得到该类全名
				String fileName = file.getName();
				int index = fileName.indexOf(".class");
				fileName = fileName.substring(0, index);
				String className = packageName + "." + fileName;
				try {
					Class<?> klass = Class.forName(className);
					dealClass(klass);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
	}
	

2.jar包扫描: 

    // URL 是统一资源定位符。
	// 对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,
	//是互联网上标准资源的地址。
	//互联网上的每个文件都有一个唯一的URL,
	//它包含的信息指出文件的位置以及浏览器应该怎么处理它。
	private void packageScanner(URL url) {
		try {
			JarURLConnection jarURLConnection = 
					(JarURLConnection) url.openConnection();
			JarFile jarFile = jarURLConnection.getJarFile();
			Enumeration<JarEntry> jarEntries = jarFile.entries();
			while (jarEntries.hasMoreElements()) {
				JarEntry jarEntry = jarEntries.nextElement();
				if (jarEntry.isDirectory() || !jarEntry.getName().endsWith(".class")) {
					continue;
				}
				String className = jarEntry.getName();
				int index = className.indexOf(".class");
				className = className.substring(0, index).replace("/", ".");
				try {
					Class<?> klass = Class.forName(className);
					dealClass(klass);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

 3.对包的类型判断,该方法由外部调用(上述两个方法仅为当前方法使用)。

public void packageScan(String rootPackage) {
		// 类加载
		this.classLoder = Thread.currentThread().getContextClassLoader();
		Enumeration<URL> urls;
		try {
			urls = classLoder.getResources(rootPackage.replace(".", "/"));
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				// 获取协议名称
				String jarPortocol = url.getProtocol();
				// 根据URL判断其属性
				if (jarPortocol.equals("file")) {
					// 抽象出路径名
					try {
						File file = new File(url.toURI());
						packageScanner(file.getAbsolutePath(), rootPackage);
					} catch (URISyntaxException e) {
						e.printStackTrace();
					}
				} else if (jarPortocol.equals("jar")) {
					packageScanner(url);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

 4.该工具类为抽象类,将得到的类交由用户处理。并且还需添加根据类来对该类所在包的扫描的方法。

	// 将扫描出来的类由用户处理
	public abstract void dealClass(Class<?> klass);

	// 通过类来扫描类所在的包
	public void packageScan(Class<?> klass) {
		packageScan(klass.getPackage().getName());
	}

完整代码: 

package com.chy.package_scan.core;

import java.io.File;
import java.io.FileFilter;
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 PackageScan {
	private ClassLoader classLoder;
	
	public PackageScan() {
	}
	
	public abstract void dealClass(Class<?> klass);
	
	private void packageScan(String packagePath, String packageName) {
		File currentFile = new File(packagePath);
		
		if(!currentFile.exists()) {
			return;
		}

		File[] listFile = currentFile.listFiles(new FileFilter() {
			
			@Override
			public boolean accept(File pathname) {
				if (currentFile.isDirectory()) {
					return true;
				}
				return pathname.getName().endsWith(".class");
			}
		});

		for (File file : listFile) {
			if (file.isDirectory()) {
				packageScan(file.getAbsolutePath(),
						packageName + "." + file.getName());
			} else {
				String fileName = file.getName();
				int index = fileName.indexOf(".class");
				fileName = fileName.substring(0, index);
				String className = packageName + "." + fileName;
				try {
					Class<?> klass = Class.forName(className);
					dealClass(klass);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private void packageScan(URL url) {
		try {
			JarURLConnection jarURLConnection = 
					(JarURLConnection) url.openConnection();
			JarFile jarFile = jarURLConnection.getJarFile();
			Enumeration<JarEntry> jarEntries = jarFile.entries();
			while (jarEntries.hasMoreElements()) {
				JarEntry jarEntry = jarEntries.nextElement();
				if (jarEntry.isDirectory() || !jarEntry.getName().endsWith(".class")) {
					continue;
				}
				String className = jarEntry.getName();
				int index = className.indexOf(".class");
				className = className.substring(0, index).replace("/", ".");
				try {
					Class<?> klass = Class.forName(className);
					dealClass(klass);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void packageScan(Class<?> klass) {
		packageScan(klass.getPackage().getName());
	}
	
	public void packageScan(String rootPackage) {
		this.classLoder = Thread.currentThread().getContextClassLoader();
		Enumeration<URL> urls;
		try {
			urls = classLoder.getResources(rootPackage.replace(".", "/"));
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				String jarPortocol = url.getProtocol();
				if (jarPortocol.equals("file")) {
					try {
						File file = new File(url.toURI());
						packageScan(file.getAbsolutePath(), rootPackage);
					} catch (URISyntaxException e) {
						e.printStackTrace();
					}
				} else if (jarPortocol.equals("jar")) {
					packageScan(url);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值