Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我可以在EJB3容器内的类路径中动态发现xml文件吗?_Java_Xml_Ejb 3.0_Classpath - Fatal编程技术网

Java 我可以在EJB3容器内的类路径中动态发现xml文件吗?

Java 我可以在EJB3容器内的类路径中动态发现xml文件吗?,java,xml,ejb-3.0,classpath,Java,Xml,Ejb 3.0,Classpath,背景: 我们项目的一个组件使用spring进行操作。一些SQL代码是基于给定的XMLSpring配置动态生成的 起初,将所有XML配置存储在类路径上的同一个包中是不错的(然后在调用服务时将其作为资源加载),但随着时间的推移,我们最终得到了大量的配置。现在是将配置分离到不同名称空间的时候了 目标 我想要的是,给定类路径上的起始包,递归地遍历目录结构并动态发现任何SpringXML文件。(这样,在添加新配置/包时,服务仍会找到这些文件) 问题 通过使用Thread.getContextClasslo

背景:

我们项目的一个组件使用spring进行操作。一些SQL代码是基于给定的XMLSpring配置动态生成的

起初,将所有XML配置存储在类路径上的同一个包中是不错的(然后在调用服务时将其作为资源加载),但随着时间的推移,我们最终得到了大量的配置。现在是将配置分离到不同名称空间的时候了

目标

我想要的是,给定类路径上的起始包,递归地遍历目录结构并动态发现任何SpringXML文件。(这样,在添加新配置/包时,服务仍会找到这些文件)

问题

通过使用
Thread.getContextClassloader().getResource(myBasePackage)
,然后获取一个文件对象并使用它在文件系统上遍历树,在EJB容器外部运行时,我能够很好地完成我的目标。笨重,我知道,但它仍然是类路径相关的,而且它工作正常

但是,您不能在EJB容器中执行此操作(您根本无法与文件系统交互),因此我不得不使用相当烦人的解决方法,在该方法中,我维护了一个要搜索的硬编码包列表

问题


有没有一种方法(在EJB容器中运行)可以动态地遍历类路径(从给定的起始位置)来搜索任意资源?

简短回答:在遵守EJB规范的情况下没有。因为规范设想容器在各种非标准情况下运行,所以它不可能做到这一点

更详细的回答:因为您不是动态创建这些资源,所以我将编写一个例程,在构建时为您提供所有资源的列表,并将它们放入EJB知道如何引用的动态生成的文件中。因此,您基本上创建了一个目录列表,其中列出了可以加载到EJB中的包和文件,这些包和文件在一个主文件中引用


Spring回答:Spring支持在类路径上查找资源,尽管我不知道这在EJB上下文中的效果如何(我怀疑它是否兼容EJB,但我没有检查)。一些细节。

免责声明:如前所述,不建议在类路径中创建资源,这取决于明确禁止的EJB容器。这可能会给您带来很多问题,因为容器可能会将您的资源分解到另一个文件夹中,甚至在整个集群中复制资源(如果是这样的话)。为了动态创建资源,您必须创建一个自定义类加载器。所以,我永远不会这么做。直接访问文件系统比访问类路径更好。如果您使用远程文件系统+文件锁,它就不那么难看了,而且最终是集群安全的

即使在我解释了所有这些之后,您仍然希望使用类路径,那么您可以尝试这样做:通过

ClassLoader cld = Thread.currentThread().getContextClassLoader();
从基本包开始枚举所有实例

Enumeration<URL> basePackageUrls = cld.getResources(basePackagePath);
枚举basePackageUrls=cld.getResources(basePackagePath);
每个URL通常是一个文件链接(file:///home/scott/.../MyResource.properties)或者一个jar链接(file:///lib.jar!/com/domain/MyResource.properties)。您必须检查URL中的模式。使用该方法,使用普通JavaAPI枚举文件夹的内容并查找子包。继续,直到扫描完所有包

请参阅下面的课程(很快将与我的开源项目一起发布)。它实现了一个类路径扫描器,您可以将其传入选择器。它就像一个访客。这是我为你做的工作,如果不是,从中获取想法。请参见末尾的示例注释选择器

public class ClasspathScanner
{

    private static final Log log = LogFactory.getLog(ClasspathScanner.class);
    private static final String JAR_FILE_PATTERN = ".jar!";

    private ClassSelector selector;
    private Set<Class<?>> classes;

    // PUBLIC METHODS ------------------------------------------------------------------------------

    public synchronized Set<Class<?>> scanPackage(String basePackage, ClassSelector selector)
        throws Exception
    {
        if (selector == null)
        {
            throw new NullPointerException("Selector cannot be NULL");
        }
        this.selector = selector;
        this.classes = new HashSet<Class<?>>();
        Set<Class<?>> aux;
        try
        {
            scanClasses0(basePackage);
            aux = this.classes;
        }
        finally
        {
            this.selector = null;
            this.classes = null;
        }

        return aux;
    }

    // HELPER CLASSES ------------------------------------------------------------------------------

    private void scanClasses0(String basePackage)
        throws IOException, ClassNotFoundException, FileNotFoundException
    {
        File packageDirectory = null;
        ClassLoader cld = getLoader();
        String basePackagePath = basePackage.replace('.', '/');
        Enumeration<URL> basePackageUrls = cld.getResources(basePackagePath);
        if (basePackageUrls == null || !basePackageUrls.hasMoreElements())
        {
            throw new ClassNotFoundException("Base package path not found: [" + basePackagePath
                + "]");
        }
        while (basePackageUrls.hasMoreElements())
        {
            String packagePath = basePackageUrls.nextElement().getFile();
            if (packagePath.contains(JAR_FILE_PATTERN))
            {
                scanJarFile(basePackagePath, packagePath);
            }
            else
            {
                packageDirectory = new File(packagePath);
                scanDirectory(basePackage, packageDirectory);
            }
        }
    }

    private void scanDirectory(String packageName, File packagePath)
        throws ClassNotFoundException, FileNotFoundException
    {
        if (packagePath.exists())
        {
            File[] packageFiles = packagePath.listFiles();
            for (File file : packageFiles)
            {
                if (file.isFile() && file.getName().endsWith(".class"))
                {
                    String fullFileName = packageName + '.' + file.getName();
                    checkClass(fullFileName);
                }
                else if (file.isDirectory())
                {
                    scanDirectory(packageName + "." + file.getName(), file);
                }
            }
        }
        else
        {
            throw new FileNotFoundException(packagePath.getPath());
        }
    }

    private void scanJarFile(String basePackagePath, String jarFileUrl)
        throws IOException, ClassNotFoundException
    {
        String jarFilePath = jarFileUrl.substring("file:".length(), jarFileUrl
            .indexOf(JAR_FILE_PATTERN)
            + JAR_FILE_PATTERN.length() - 1);
        log.debug("URL JAR file path: [" + jarFilePath + "]");
        jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
        log.debug("Decoded JAR file path: [" + jarFilePath + "]");
        JarFile jar = new JarFile(new File(jarFilePath));
        for (Enumeration<JarEntry> jarFiles = jar.entries(); jarFiles.hasMoreElements();)
        {
            JarEntry file = jarFiles.nextElement();
            String fileName = file.getName();
            if (!file.isDirectory() && fileName.endsWith(".class")
                && fileName.startsWith(basePackagePath))
            {
                String className = fileName.replace('/', '.');
                checkClass(className);
            }
        }
    }

    private void checkClass(String fullFilePath) throws ClassNotFoundException
    {
        String className = fullFilePath.substring(0, fullFilePath.length() - 6);
        Class<?> c = getLoader().loadClass(className);
        if (selector.select(c))
        {
            classes.add(c);
        }
    }

    private ClassLoader getLoader()
    {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if (loader == null)
        {
            loader = getClass().getClassLoader();
        }
        return loader;
    }

    // INNER CLASSES -------------------------------------------------------------------------------

    public interface ClassSelector
    {
        boolean select(Class<?> clazz);
    }

    public static class AnnotatedClassSelector implements ClassSelector
    {
        private final Class<? extends Annotation>[] annotations;

        public AnnotatedClassSelector(Class<? extends Annotation>... annotations)
        {
            this.annotations = annotations;
        }

        public boolean select(Class<?> clazz)
        {
            for (Class<? extends Annotation> ac : annotations)
            {
                if (clazz.isAnnotationPresent(ac))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
公共类类路径扫描程序
{
私有静态最终日志日志=LogFactory.getLog(ClasspathScanner.class);
私有静态最终字符串JAR_FILE_PATTERN=“.JAR!”;
私有类选择器;
private Set>scanPackage(字符串basePackage,类选择器)
抛出异常
{
if(选择器==null)
{
抛出新的NullPointerException(“选择器不能为NULL”);
}
this.selector=选择器;
this.classes=newhashset>aux;
尝试
{
scanClasses0(基本包);
aux=这个类;
}
最后
{
this.selector=null;
this.classes=null;
}
返回aux;
}
//助手类------------------------------------------------------------------------------
私有void扫描类0(字符串basePackage)
抛出IOException、ClassNotFoundException、FileNotFoundException
{
File packageDirectory=null;
ClassLoader cld=getLoader();
字符串basePackagePath=basePackage.replace('.','/');
枚举basePackageUrls=cld.getResources(basePackagePath);
if(basePackageUrls==null | |!basePackageUrls.hasMoreElements())
{
抛出新的ClassNotFoundException(“未找到基本包路径:[”+basePackagePath
+ "]");
}
while(basePackageUrls.hasMoreElements())
{
字符串packagePath=basePackageUrls.nextElement().getFile();
if(packagePath.contains(JAR\u文件\u模式))
{
scanJarFile(basePackagePath,packagePath);
}
其他的
{
packageDirectory=新文件(packagePath);
扫描目录(basePackage、packageDirectory);
}
}
}
私有void扫描目录(字符串packageName、文件packagePath)
抛出ClassNotFoundException、FileNotFoundException
{
if(packagePath.exists())
{
File[]packageFiles=packagePath.listFiles();