我正在寻找一种方法来列出Java中任意包的所有子包。
这样的事情:
Package basePackage = getPackage("com.mypackage");
for(Package subPackage : basepackage.getSubPackages()){
System.out.println(subPackage.getName());
}
有办法吗?提前谢谢。
IDE(让我们说Netbeans)如何做到这一点?
更新:
我正在尝试找到MyBatis的所有mappers包。在我的项目中,所有映射器包都必须命名为“* .mappers”。例如:“a.b.mappers”或“a.b.c.mappers”。问题是我只知道基础包,并且不确定它下面有多少个映射包。
更新: 这是我的代码试图使用反射库来做到这一点:
private Set<String> getPackagesNames() {
Reflections reflections = new Reflections("com.mypackage");
Set<Class<? extends Object>> allClasses = reflections.getSubTypesOf(Object.class);
Set<String> packageNames = new HashSet<>();
for( Iterator<Class<? extends Object>> it = allClasses.iterator(); it.hasNext(); ) {
Class<? extends Object> subClass= it.next();
packageNames.add(subClass.getPackage().getName());
}
return packageNames;
}
不确定为什么这不起作用。这里没有上课....
更新
这是我的代码。有点慢,但在我的情况下表现并不是那么大。我之前从未使用过Spring,所以如果有更好的方法可以做到,请告诉我。感谢。
private static Set<String> getPackages(String basePackage) throws IOException, ClassNotFoundException {
Set<String> packagesNames = new HashSet<>();
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + "/" + "**/*.class";
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
for( Resource resource : resources ) {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
Class aClass = Class.forName(metadataReader.getClassMetadata().getClassName());
String packageName = aClass.getPackage().getName();
packagesNames.add(packageName);
}
}
return packagesNames;
}
private static String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
}
大部分代码都是从How do I read all classes from a Java package in the classpath?
复制的答案 0 :(得分:7)
我认为获取包的最简单方法是使用
获取类加载器的所有包Package.getPackages()
并使用您的包名称
过滤它packageName.startsWith("com.yourcompany.yourpackage")
答案 1 :(得分:0)
1)从包中加载任何类并获取其URL
URL u = Test.class.getResource("");
2)确定它是文件还是罐子。
2)使用File.list()获取目录或使用JarFile.getEntries获取jar来查找子包
答案 2 :(得分:0)
解决此问题的另一种可能方法是使用系统类加载器加载类路径中的所有jar / zip文件,然后只需检查它们。
表现不会很好。因为我们正在检查jar / zip文件,但它确实有效。
以下是一些示例代码:
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.JarInputStream;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
public class ClasspathLister {
public static void main(String[] args) {
listPackages("com/fasterxml").forEach(s -> {
System.out.printf("%s%n", s.replace("/", ".").replaceAll("\\.$", ""));
});
}
private static Set<String> listPackages(String prefix) {
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
return Arrays.stream(sysloader.getURLs())
.filter(u -> u.toString().matches("(?i).+(\\.jar|\\.zip)$"))
.flatMap(u -> listJar(u, prefix).stream())
.collect(Collectors.toCollection(TreeSet::new));
}
private static Set<String> listJar(URL u, String prefix) {
Set<String> packages = new LinkedHashSet<>();
try (JarInputStream in =
new JarInputStream(Files.newInputStream(Paths.get(u.toURI())))) {
ZipEntry ze;
while ((ze = in.getNextEntry()) != null) {
if (ze.isDirectory() && ze.getName().startsWith(prefix)) {
packages.add(ze.getName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return packages;
}
}
这将输出如下内容:
com.fasterxml
com.fasterxml.jackson
com.fasterxml.jackson.annotation
com.fasterxml.jackson.core
com.fasterxml.jackson.core.base
com.fasterxml.jackson.core.filter
com.fasterxml.jackson.core.format
com.fasterxml.jackson.core.io
com.fasterxml.jackson.core.json
com.fasterxml.jackson.core.sym
com.fasterxml.jackson.core.type
com.fasterxml.jackson.core.util
com.fasterxml.jackson.databind
com.fasterxml.jackson.databind.annotation
com.fasterxml.jackson.databind.cfg
com.fasterxml.jackson.databind.deser
com.fasterxml.jackson.databind.deser.impl
com.fasterxml.jackson.databind.deser.std
com.fasterxml.jackson.databind.exc
...
答案 3 :(得分:0)
详细说明:IDE实际上读取了依赖项的JAR文件。在JAR文件中,它只是一个目录结构。这与Java ClassLoader存储它的方式不同。