0

我有一个带有模型 DTO 的罐子。我希望这些类(标有@XmlRootElement)可用于 Jersey 1 HTTP 客户端。我的初始化代码是:

ClientConfig cc = new DefaultClientConfig(MyContextResolver.class);
Client client = Client.create(cc);

MyContextResolver(实现ContextResolver<JAXBContext>)中,我尝试过:

jaxbContext = JAXBContext.newInstance(Class1.class, Class2.class);

它可以工作,但它不是动态的(我必须手动添加类,一个接一个)。

我也使用了 Spring 并且它有效,但我想要一个无 Spring 的解决方案。

有更好的解决方案吗?一种自动扫描 jar 中的所有类并将它们添加到上下文中的方法?谢谢。

4

2 回答 2

1

您是否有理由希望拥有一个同时处理所有类的上下文?如果您有名称冲突,您将面临例外的风险。

为什么不简单地拥有一个 ContextResolver ,其工作方式如下:

Map<Class,JAXBContect> cache = new ConcurrentHashMap<>();
getContext(Class<?> type) {
 JAXBContect  context = cache.get(type);
 if (context ==  null) }
    context = JAXBContext.newInstance(type);
    cache.put(type,context);
 }
 return context;    
}

JAXB 将解决必要的类依赖关系(唯一的问题是子类,但这些应在父类中标记为@XMLSeeAlso)。

唯一的潜在问题是您会在运行时而不是在启动期间发现任何 JAXB 问题。但与此同时,任何错误都只会影响依赖于错误注释类的客户端,其余的都会起作用。

于 2015-02-24T22:33:05.283 回答
0

我最终手动扫描了罐子......

public static List<Class> listClassesInPackage(String jarName, String packageName) throws IOException {
    packageName = packageName.replaceAll("\\.", "/");
    JarInputStream jarFile = new JarInputStream(new FileInputStream(jarName));
    JarEntry jarEntry = null;
    List<Class> classes = new ArrayList();
    do {
        try {
            jarEntry = jarFile.getNextJarEntry();
            if (jarEntry != null && jarEntry.getName().startsWith(packageName) && jarEntry.getName().endsWith(".class")) {
                Class<?> forName = Class.forName(jarEntry.getName().replaceAll("/", "\\.").replaceAll(".class", ""));
                XmlRootElement xmlAnnotation = forName.getAnnotation(XmlRootElement.class);
                if (xmlAnnotation != null) {
                    classes.add(forName);
                }
            }
        } catch (ClassNotFoundException | IOException ex) {
            // ignore this class
        }
    } while (jarEntry != null);
    return classes;
}

调用:

List<Class> packageClasses = listClassesInPackage(
                Meta.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "pt.iol.model2");
jaxbContext = JAXBContext.newInstance(packageClasses.toArray(new Class[0]));
于 2015-02-25T14:29:36.703 回答