上一篇中,我向大家讲述了遍历jar包时所遇到的困难,本篇将向大家分享最终版代码。

package com.itkt.mtravel.hotel.util;import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;public class PackageUtil {public static void main(String[] args) throws Exception {String packageName = "com.wang.vo.request.hotel";// List<String> classNames = getClassName(packageName);List<String> classNames = getClassName(packageName, false);if (classNames != null) {for (String className : classNames) {System.out.println(className);}}}/*** 获取某包下(包括该包的所有子包)所有类* @param packageName 包名* @return 类的完整名称*/public static List<String> getClassName(String packageName) {return getClassName(packageName, true);}/*** 获取某包下所有类* @param packageName 包名* @param childPackage 是否遍历子包* @return 类的完整名称*/public static List<String> getClassName(String packageName, boolean childPackage) {List<String> fileNames = null;ClassLoader loader = Thread.currentThread().getContextClassLoader();String packagePath = packageName.replace(".", "/");URL url = loader.getResource(packagePath);if (url != null) {String type = url.getProtocol();if (type.equals("file")) {fileNames = getClassNameByFile(url.getPath(), null, childPackage);} else if (type.equals("jar")) {fileNames = getClassNameByJar(url.getPath(), childPackage);}} else {fileNames = getClassNameByJars(((URLClassLoader) loader).getURLs(), packagePath, childPackage);}return fileNames;}/*** 从项目文件获取某包下所有类* @param filePath 文件路径* @param className 类名集合* @param childPackage 是否遍历子包* @return 类的完整名称*/private static List<String> getClassNameByFile(String filePath, List<String> className, boolean childPackage) {List<String> myClassName = new ArrayList<String>();File file = new File(filePath);File[] childFiles = file.listFiles();for (File childFile : childFiles) {if (childFile.isDirectory()) {if (childPackage) {myClassName.addAll(getClassNameByFile(childFile.getPath(), myClassName, childPackage));}} else {String childFilePath = childFile.getPath();if (childFilePath.endsWith(".class")) {childFilePath = childFilePath.substring(childFilePath.indexOf("\\classes") + 9, childFilePath.lastIndexOf("."));childFilePath = childFilePath.replace("\\", ".");myClassName.add(childFilePath);}}}return myClassName;}/*** 从jar获取某包下所有类* @param jarPath jar文件路径* @param childPackage 是否遍历子包* @return 类的完整名称*/private static List<String> getClassNameByJar(String jarPath, boolean childPackage) {List<String> myClassName = new ArrayList<String>();String[] jarInfo = jarPath.split("!");String jarFilePath = jarInfo[0].substring(jarInfo[0].indexOf("/"));String packagePath = jarInfo[1].substring(1);try {JarFile jarFile = new JarFile(jarFilePath);Enumeration<JarEntry> entrys = jarFile.entries();while (entrys.hasMoreElements()) {JarEntry jarEntry = entrys.nextElement();String entryName = jarEntry.getName();if (entryName.endsWith(".class")) {if (childPackage) {if (entryName.startsWith(packagePath)) {entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));myClassName.add(entryName);}} else {int index = entryName.lastIndexOf("/");String myPackagePath;if (index != -1) {myPackagePath = entryName.substring(0, index);} else {myPackagePath = entryName;}if (myPackagePath.equals(packagePath)) {entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));myClassName.add(entryName);}}}}} catch (Exception e) {e.printStackTrace();}return myClassName;}/*** 从所有jar中搜索该包,并获取该包下所有类* @param urls URL集合* @param packagePath 包路径* @param childPackage 是否遍历子包* @return 类的完整名称*/private static List<String> getClassNameByJars(URL[] urls, String packagePath, boolean childPackage) {List<String> myClassName = new ArrayList<String>();if (urls != null) {for (int i = 0; i < urls.length; i++) {URL url = urls[i];String urlPath = url.getPath();// 不必搜索classes文件夹if (urlPath.endsWith("classes/")) {continue;}String jarPath = urlPath + "!/" + packagePath;myClassName.addAll(getClassNameByJar(jarPath, childPackage));}}return myClassName;}
}

由于我们并不确定jar包生成时采用的哪种方式,如果采用默认生成jar包的方式,那我们通过Thread.currentThread().getContextClassLoader().getResource()是获取不到的,因此我增加了从所有jar包中搜索提供的包域名,这样功能就完善了很多。

那么就此关于“如何遍历包中所有类”就结束了,PackageUtil这个类的功能还有些少,不排除日后进一步完善的可能,如果大家关于这个util有什么新的需求或者建议,随时欢迎大家提出。发现bug的,也请及时通知我以便改进。

============友情链接============

Java遍历jar包所有类-后续 http://blog.csdn.net/wangpeng047/article/details/8202353

Java遍历包中所有类 http://blog.csdn.net/wangpeng047/article/details/8124390

Java遍历包中所有类-终续相关推荐

  1. Java遍历包中所有类

    由于项目需要,我想获得某包下所有的类(包括该包的所有子包),从网上找了找,没有什么能用的,即使找到了写的也不怎样,效率低下.索性就自己写吧,正好也锻炼锻炼写代码的功底.特此分享出来,希望能帮到大家.. ...

  2. Java遍历包中所有类包括jar包(完整转载)

    第一部分转自 :http://blog.csdn.net/wangpeng047/article/details/8124390 第二部分转自:http://blog.csdn.net/wangpen ...

  3. Java遍历包中所有类(完整转载:-))

    第一部分转自 :http://blog.csdn.net/wangpeng047/article/details/8124390 第二部分转自:http://blog.csdn.net/wangpen ...

  4. java调用包中的类_java调用另一个包中的类的方法

    java调用另一个包中的类的方法 发布时间:2020-05-18 15:04:40 来源:亿速云 阅读:199 作者:小新 今天小编给大家分享的是java调用另一个包中的类的方法,相信很多人都不太了解 ...

  5. 关于java同步包中ConcurrentLinkedQueue类的深入分析与理解

    一,官方描写叙述 一个基于连接节点的无界线程安全队列.这个队列的顺序是先进先出.队列头部的元素是留在队列中时间最长的,队列尾部的元素是留在队列中时间最短的.新元素被插入到元素的尾部,队列从队列的头部检 ...

  6. java同一个包中,类之间的的调用

    如果是静态方法,直接 类名.方法名即可,如果是非静态方法,则需new一个对象出来,然后用对象.方法名调用 如: public class A{ public static void T(){ Syst ...

  7. java 扫描类_Java扫描指定包中所有类

    1. 扫描类 import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.n ...

  8. Throwable是java.lang包中一个专门用来处理异常的类

    答:Throwable是java.lang包中一个专门用来处理异常的类.它有两个子类,即Error 和Exception,它们分别用来处理两组异常. Error用来处理程序运行环境方面的异常,比如,虚 ...

  9. 6 日期字符串转日期_Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类...

    因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API.Stephen向JCP提交了 ...

最新文章

  1. 杨辉三角 用php写,PHP_PHP写杨辉三角实例代码,复制代码 代码如下: ?php // - phpStudy...
  2. C# ToString()用法汇总
  3. python requests 示例_Python Requests模块的简单示例
  4. [MAC] Mac OS X下快速复制文件路径的方法
  5. 插件~Nuget中包与包的依赖关系
  6. 本地虚拟机上的docker安装mysql_Linux虚拟机上安装docker,并使用docker安装mysql,tomcat...
  7. iis下php 500错误
  8. linux无法设置变量,linux – crontab在作业之前无法设置变量
  9. 病毒周报(100118至100124)
  10. DC域【软件分发】失败的处理手段
  11. amazeUI的icon图标库
  12. 以太坊公链节点连接节点超时问题排查
  13. spark sample采样
  14. printf输出二进制
  15. 第11期:Hadoop零基础学习路线
  16. 摄像头水平视野垂直视野?_动物穿越:新视野的梦想更新
  17. CSI笔记【2】:正交频分多路复用技术/OFDM
  18. Unity 使用UnityWebRequest问题小结
  19. 3.《程序猿扯淡系列》约会的艺术--教你如何逆袭
  20. 限制input框只能输入数字,加减号也不可以输入

热门文章

  1. 【电脑连接wifi不能访问网页但是微信和QQ可以登录如何解决】
  2. 擅在各个现货黄金时间图捕捉时机
  3. 《从日薪五元到亿万身家》成杰“逆袭”励志畅销有声书即将上线啦
  4. 句子类型 - 祈使句
  5. Vue3报错之 Failed to load resource: the server responded with a status of 404 (Not Found)
  6. 强制性异常和非强制性异常
  7. 简单的数值 variant
  8. TX- index contention的解决方法
  9. 人工智能的最大危险是什么?
  10. python 根据gdb省库提取属性,输出房地一体申请表