从IntelliJ运行Dropwizard应用返回XML响应格式与jar运行不一致
问题原因分析
- 该差异由运行时使用的XML序列化实现不一致导致:
- IDEA本地运行时,Classpath中存在完整的JAXB实现对应的JAX-RS MessageBodyWriter组件,会识别代码里的JAXB注解(
@XmlRootElement、@XmlAttribute等),生成符合预期的属性式XML结构 - 打包成可执行Jar运行时,由于使用的打包插件(通常是maven-shade-plugin)没有正确合并
META-INF/services下的服务注册文件,导致JAXB的JAX-RS provider没有被Dropwizard扫描到,自动降级使用Jackson XML序列化组件。而Jackson默认没有开启JAXB注解支持,会直接把类名作为根元素、字段作为子节点序列化,就出现了不符合预期的返回结构。
- IDEA本地运行时,Classpath中存在完整的JAXB实现对应的JAX-RS MessageBodyWriter组件,会识别代码里的JAXB注解(
解决方案
可任选以下一种方案修复:
方案1:配置maven-shade-plugin合并服务注册文件
如果希望继续使用JAXB序列化,修改pom.xml中shade插件的配置,添加ServicesResourceTransformer合并服务配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>${maven.shade.version}</version> <configuration> <transformers> <!-- 合并服务注册文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <!-- 保留Dropwizard原有必须的transformer配置 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>${你的启动类全路径}</mainClass> </transformer> </transformers> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin>
重新打包后即可生效。
方案2:开启Jackson的JAXB注解支持
如果希望统一使用Jackson做XML序列化,可以在Dropwizard的Application类的run方法中,给Jackson的XML mapper注册JAXB注解模块:
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; @Override public void run(YourConfiguration config, Environment env) { // 注册JAXB注解支持模块 env.getObjectMapper().registerModule(new JaxbAnnotationModule()); // 原有其他初始化逻辑 }
Dropwizard 2.0.24默认已经自带jackson-module-jaxb-annotations依赖,不需要额外引入,配置后JAXB注解会被Jackson识别,两种运行环境的XML返回结构就会保持一致。
方案3:直接使用Jackson XML注解替换JAXB注解
如果没有兼容JAXB的需求,可以直接把类上的JAXB注解换成Jackson XML的对应注解,不需要额外配置就能序列化得到预期效果:
@Getter @NoArgsConstructor @AllArgsConstructor @ToString @EqualsAndHashCode @JacksonXmlRootElement(localName = "Error") public class ErrorResponse { @NonNull @JacksonXmlProperty(isAttribute = true, localName = "msg") private String msg; @JacksonXmlProperty(isAttribute = true, localName = "display") protected String display; @JacksonXmlProperty(isAttribute = true, localName = "action") private String action; @NotNull @JacksonXmlProperty(isAttribute = true, localName = "type") private String type; @JacksonXmlProperty(isAttribute = true, localName = "code") private String code; }
内容的提问来源于stack exchange,提问作者Jawad Azzam
相关产品推荐
相关产品推荐

