package com.s.rest.util;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.LinkedHashSet; import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile; /**
* 扫描2包下的所有类
* <p>Title: ClassUtil.java</p>
* <p>Description: </p>
* @author lichao1
* @date 2018年12月3日
* @version 1.0
*/
public class ClassUtil { private static Set<Class<?>> classList;
static {
classList = getClasses("com.esri.rest");
}
/**
* 从包package中获取所有的Class
*
* @param pack
* @return
*/
public static Set<Class<?>> getClasses(String pack) { // 第一个class类的集合
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
// 是否循环迭代
boolean recursive = true;
// 获取包的名字 并进行替换
String packageName = pack;
String packageDirName = packageName.replace('.', '/');
// 定义一个枚举的集合 并进行循环来处理这个目录下的things
Enumeration<URL> dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
// 循环迭代下去
while (dirs.hasMoreElements()) {
// 获取下一个元素
URL url = dirs.nextElement();
// 得到协议的名称
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol)) {
// System.err.println("file类型的扫描");
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件 并添加到集合中
findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
} else if ("jar".equals(protocol)) {
// 如果是jar包文件
// 定义一个JarFile
// System.err.println("jar类型的扫描");
JarFile jar;
try {
// 获取jar
jar = ((JarURLConnection) url.openConnection()).getJarFile();
// 从此jar包 得到一个枚举类
Enumeration<JarEntry> entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
// 获取后面的字符串
name = name.substring(1);
}
// 如果前半部分和定义的包名相同
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
// 如果以"/"结尾 是一个包
if (idx != -1) {
// 获取包名 把"/"替换成"."
packageName = name.substring(0, idx).replace('/', '.');
}
// 如果可以迭代下去 并且是一个包
if ((idx != -1) || recursive) {
// 如果是一个.class文件 而且不是目录
if (name.endsWith(".class") && !entry.isDirectory()) {
// 去掉后面的".class" 获取真正的类名
String className = name.substring(packageName.length() + 1, name.length() - 6);
try {
// 添加到classes
classes.add(Class.forName(packageName + '.' + className));
} catch (ClassNotFoundException e) {
// log
// .error("添加用户自定义视图类错误
// 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}
}
} catch (IOException e) {
// log.error("在扫描用户定义视图时从jar包获取文件出错");
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
} return classes;
} /**
* 以文件的形式来获取包下的所有Class
*
* @param packageName
* @param packagePath
* @param recursive
* @param classes
*/
public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,
Set<Class<?>> classes) {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory()) {
// log.warn("用户定义包名 " + packageName + " 下没有任何文件");
return;
}
// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter() {
// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
public boolean accept(File file) {
return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
}
});
// 循环所有文件
for (File file : dirfiles) {
// 如果是目录 则继续扫描
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,
classes);
} else {
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0, file.getName().length() - 6);
try {
// 添加到集合中去
// classes.add(Class.forName(packageName + '.' +
// className));
// 经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
classes.add(
Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));
} catch (ClassNotFoundException e) {
// log.error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
} public static void main(String[] args) {
System.out.println(classList);
Object[] ts = classList.toArray();
for(Object t:ts){
Class<?> tt = (Class<?>) t;
System.out.println(tt.getName());
}
}
}

原文:http://guoliangqi.iteye.com/blog/644876

Java 获取指定包下的所有类的更多相关文章

  1. Java获取指定包名下的所有类的全类名的解决方案

        最近有个需求需要获取一个指定包下的所有类的全类名,因此特意写了个获取指定包下所有类的全类名的工具类.在此记录一下,方便后续查阅 一.思路         通过ClassLoader来查找指定包 ...

  2. java.util.regex包下的Pattern类和Matcher类的使用总结

    一.介绍 Java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现1.Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不 ...

  3. java 查找指定包下的类

    package com.jason.test; import java.io.File; import java.io.IOException; import java.io.UnsupportedE ...

  4. Java -- 获取指定接口的所有实现类或获取指定类的所有继承类

    Class : ClassUtil package pri.lime.main; import java.io.File; import java.io.IOException; import jav ...

  5. java获取指定路径下的指定文件/java.io.File.listFiles(FilenameFilter filter)

    java.io.File.listFiles(FilenameFilter filter) 返回抽象路径名数组,表示在目录中此抽象路径名表示,满足指定过滤器的文件和目录. 声明 以下是java.io. ...

  6. 004 关于Java如何扫描指定package下所有的类

    q前言: 在工作中看到这个知识点,就顺便参考了百度的一些资料,整理一下,希望以后用的到. 一:理论部分 1.使用场景 写一个MVC框架,需要从包中扫描出组件并注册到容器中,而JDK没有提供现成的从方法 ...

  7. java.util.regex包下的Pattern和Matcher详解(正则匹配)

    java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现(建议在阅读本文时,打开java API文档,当介绍到哪个方法时,查看java API中的方法说明,效果 ...

  8. Java反射 - 1(得到类对象的几种方法,调用方法,得到包下的所有类)

    通过反射获得对象的方法 准备工作: 有一个User类如下 package o1; /** * Created by yesiming on 16-11-19. */ public class User ...

  9. IO流-获取指定目录下文件夹和文件对象【File类】

    一.运用File类实现获取指定目录下文件夹和文件对象 1.File类 2.方法: 获取文件绝对路径 :getAbsolutePath 案例: import java.io.File; /** * 获取 ...

随机推荐

  1. MySQL Community Server 5.5.56 ZIP Archive 绿色解压版 window安装步骤

    MySQL Community Server 5.5.56  ZIP Archive  绿色解压版 window安装步骤 首先 准备好启动配置文件my.ini [mysqld] #设置字符集为utf8 ...

  2. BZOJ1021 [SHOI2008]循环的债务

    Description Alice.Bob和Cynthia总是为他们之间混乱的债务而烦恼,终于有一天,他们决定坐下来一起解决这个问题. 不过,鉴别钞票的真伪是一件很麻烦的事情,于是他们决定要在清还债务 ...

  3. less教程

    平时在工作中,偶尔会遇到老大让你修改原来写好的样式,如果修改的多的话,修改起来是非常麻烦的.他不像js一样,定义变量.函数,需要修改某些值,直接修改方法就行了.less的出现,恰恰帮我们解决了这个问题 ...

  4. 浏览器根对象window之Location

    1. Location Location 对象包含有关当前 URL 的信息.Location 对象是 Window 对象的一个部分,可通过 window.location 属性来访问. 1.1 Loc ...

  5. 微服务&spring cloud架构系列汇总

    为了方便查找,把微服务&微服务架构之spring cloud架构系列文章按时间正序整理了一下,记录如下:   1. 微服务架构之spring cloud 介绍 2. 微服务架构之spring ...

  6. 线性表接口的实现_Java

    线性表是其组成元素间具有线性关系的一种线性结构,对线性表的基本操作主要有插入.删除.查找.替换等,这些操作可以在线性表的任何位置进行.线性表可以采用顺序存储结构和链式存储结构表示. 本接口的类属于da ...

  7. .net core系列之《.net平台历程介绍以及.net framework和.net core对比》

    一..Net平台的背景 1.2010之前 的PC时代的时候,互联网规模还不是特别庞大,以静态编译式语言为代表的JAVA和.Net没什么太大区别,.net以windows自居. 2.2010年以JAVA ...

  8. jsonp和ajax的区别

    一.Ajax工作原理 相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步化.对于用户请求ajax引擎会做一些数据验证和数据处理,不是所有请求都提交给服务器,当需要从服务 ...

  9. cocos ide使用binding-generator导出来的c++类

    time:2015/03/19 cocos版本:3.2 描述:用了ide运行一个实例[1]的时候需要增加c++类,正确导出来之后,直接使用vs2012启动是没有问题的,但是使用ide启动却提示找不到模 ...

  10. Linux入门-3 Linux磁盘及文件系统管理

    1. 磁盘基本概念 1.1 磁盘结构:盘片(单碟vs多碟).磁头(读写数据) 1.2 磁盘在Linux中的表示 1.3 分区概念 2 使用fdisk进行磁盘管理 3 Linux文件系统 mke2fs ...