【问题标题】:JAXB Won't Accept CustomEscapeHandlerJAXB 不接受 CustomEscapeHandler
【发布时间】:2018-05-22 17:08:48
【问题描述】:

我正在开发一个执行大量 XML 操作的应用程序,因此我试图让 JAXB 在其中工作。对于 CustomEscapeHandler,我有以下类: 导入com.sun.xml.bind.marshaller.CharacterEscapeHandler;

import java.io.IOException;
import java.io.Writer;

public class CustomEscapeHandler implements CharacterEscapeHandler {
    private static final CharacterEscapeHandler theInstance = new CustomEscapeHandler();

    private CustomEscapeHandler() {
    }

    public static CharacterEscapeHandler getInstance() {
        return theInstance;
    }

    public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException {
        int limit = start + length;
        for(int i = start; i < limit; ++i) {
            char c = ch[i];
            if (c == 38 || c == 39 || c == 60 || c == 62 || c == 13 || c == 34 && isAttVal) {
                if (i != start) {
                    out.write(ch, start, i - start);
                }

                start = i + 1;
                switch(ch[i]) {
                    case '\"':
                        out.write("&quot;");
                        break;
                    case '&':
                        out.write("&amp;");
                        break;
                    case '<':
                        out.write("&lt;");
                        break;
                    case '>':
                        out.write("&gt;");
                        break;
                    case '\'':
                        out.write("&apos;");
                        break;
                }
            }
        }

        if (start != limit) {
            out.write(ch, start, limit - start);
        }
    }
}

如果我使用

jaxbMarshaller.setProperty("com.sun.xml.internal.bind.characterEscapeHandler", CustomEscapeHandler.getInstance());

我明白了

javax.xml.bind.PropertyException: property "com.sun.xml.internal.bind.characterEscapeHandler" must be an instance of type com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler, not my.package.CustomEscapeHandler

所以如果我把它改成

jaxbMarshaller.setProperty("com.sun.xml.bind.marshaller.CharacterEscapeHandler", CustomEscapeHandler.getInstance());

我明白了

javax.xml.bind.PropertyException: name: com.sun.xml.bind.marshaller.CharacterEscapeHandler value: my.package.CustomEscapeHandler@e2b4f3
    at javax.xml.bind.helpers.AbstractMarshallerImpl.setProperty(AbstractMarshallerImpl.java:358)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.java:527)
    at my.package.util.XmlUtils.convert(XmlUtils.java:39)
    at my.package.util.XmlUtils.convertFormToXml(XmlUtils.java:28)
    at my.package.FormsMain.saveXML(FormsMain.java:362)
    at my.package.FormsMain.saveForms(FormsMain.java:499)
    at my.package.FormsMain.lambda$createWindow$3(FormsMain.java:231)

查看堆栈跟踪,它试图在内部包中使用编组器,它还查看反编译的代码,期望转义处理程序是内部包中 CharacterEscapeHandler 的实现。

如何让 JAXB 不使用内部包实现?

一个月过去了,还是没能找到解决办法。我在网上看到的每个示例都扩展了 CharacterEscapeHandler 的内部版本。

【问题讨论】:

    标签: java jaxb


    【解决方案1】:

    这里的问题是使用内部“com.sun.xml.internal”包中的 CharacterEscapeHandler。即使您的代码可以工作,这也不是一个好主意。而是使用 com.sun.xml.bind.marshaller.CharacterEscapeHandler 中的类似类,它将为您解决问题。

    【讨论】:

    • 您是否尝试过这样做,而不是使用自定义的:jaxbMarshaller.setProperty(CharacterEscapeHandler.class.getName(), (CharacterEscapeHandler) (chars, start, length, b, writer) -> writer.write(chars, start, length) );
    【解决方案2】:

    您应该能够通过设置启动属性来控制使用什么编组器:

     javax.xml.bind.context.factory=com.sun.xml.bind.v2.ContextFactory
    

    这会将其设置为 JAXB 参考实现而不是内部上下文工厂,相应地,您获得的编组器将是 com.sun.xml.bind.v2.runtime.MarshallerImpl 类型而不是内部的。

    如果您查看 JAXBContext 类的内部,在 newInstance 方法中,您会看到它调用了一个类 ContextFinder.find,并且正是该方法读取 javax.xml.bind.context.factory 属性以了解 JAXB要使用的上下文工厂。

    【讨论】:

      【解决方案3】:

      以下启动属性确实为我解决了这个问题(其他解决方案都不起作用)。

      将以下启动选项添加到你的java程序/应用服务器/spring boot app...:

      -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory

      这可能与 jaxb.jar / META-INF/services 文件夹中的附加条目有关...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多