JAXB无法识别自定义CustomEscapeHandler的解决方案求助
Hey there, sorry to hear this has been plaguing you for a month—let's break down what's going on and fix it for good.
The Root Cause
The problem boils down to which JAXB implementation your project is using:
- JDK-built-in JAXB (available in Java 6-8) relies on internal
com.sun.xml.internalpackages. This is why your custom handler keeps getting rejected unless it implements the internalCharacterEscapeHandler. - Standalone JAXB RI (the official reference implementation from GlassFish) uses public
com.sun.xml.bindpackages, which is what you want to use to avoid internal dependencies.
Most online examples you found are likely targeting the old JDK-built-in version, which is why they don't address your issue.
Step-by-Step Solution
1. Replace JDK-built-in JAXB with Standalone RI Dependencies
First, you need to exclude the JDK's internal JAXB and add the standalone implementation to your project. Here's how to do it with Maven (adjust for Gradle if needed):
<dependencies> <!-- JAXB API --> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <!-- JAXB Implementation (runtime) --> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.1</version> <scope>runtime</scope> </dependency> <!-- JAXB Core Utilities --> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0.1</version> </dependency> <!-- Activation API (required for JAXB 2.3+) --> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> </dependencies>
For Java 9+, since JAXB was removed from the JDK, you'll also need to add module declarations in your module-info.java:
requires javax.xml.bind; requires com.sun.xml.bind;
2. Update Your CustomEscapeHandler to Use the Public Package
Make sure your handler implements the public com.sun.xml.bind.marshaller.CharacterEscapeHandler (not the internal com.sun.xml.internal one):
import com.sun.xml.bind.marshaller.CharacterEscapeHandler; import java.io.IOException; import java.io.Writer; public class CustomEscapeHandler implements CharacterEscapeHandler { private static final CustomEscapeHandler INSTANCE = new CustomEscapeHandler(); public static CustomEscapeHandler getInstance() { return INSTANCE; } @Override public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException { // Add your custom escape logic here for (int i = start; i < start + length; i++) { char c = ch[i]; switch (c) { case '<': out.write("<"); break; case '>': out.write(">"); break; case '&': out.write("&"); break; case '\"': if (isAttVal) out.write("""); else out.write(c); break; default: out.write(c); break; } } } }
3. Configure Marshaller with the Correct Property Key
When setting your custom handler, use the public property key (matching the standalone RI):
import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; public class JaxbExample { public static void main(String[] args) throws Exception { JAXBContext jaxbContext = JAXBContext.newInstance(YourPojoClass.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // Set your custom escape handler using the public property key jaxbMarshaller.setProperty("com.sun.xml.bind.marshaller.CharacterEscapeHandler", CustomEscapeHandler.getInstance()); // Optional: Format output for readability jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Marshal your object jaxbMarshaller.marshal(yourPojoInstance, System.out); } }
Key Notes to Avoid Pitfalls
- Classpath Priority: Ensure the standalone JAXB dependencies are loaded before any JDK internal classes. Most build tools (Maven/Gradle) handle this automatically, but double-check if you have conflicting dependencies.
- Framework Integration: If you're using a framework like Spring, make sure it's configured to use the standalone JAXB implementation. For example, Spring's
Jaxb2Marshallerwill pick up the standalone RI if it's on the classpath.
内容的提问来源于stack exchange,提问作者user4880619

