You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JAXB生成Java类后,生成XML时如何保留XSD指定的元素名称并正确添加命名空间

JAXB生成Java类后,生成XML时如何保留XSD指定的元素名称并正确添加命名空间

看起来你遇到了JAXB序列化时命名空间丢失、元素名称自动小写的问题,我之前也踩过类似的坑,给你分步骤说下怎么解决:

先找问题根源

你的Java类注解看起来是对的,但序列化后出问题,主要有两个原因:

  1. 生成的类的**包级注解(package-info.java)**可能没配置正确,导致默认命名空间和元素格式不生效
  2. Spring RestTemplate默认的JAXB转换器没有正确处理命名空间和元素名称映射

解决步骤

1. 确保XJC生成的类注解完全正确

首先要让XJC生成符合要求的Java类,最好用**绑定文件(binding.xjb)**来约束生成规则,避免XJC默认的驼峰转换搞乱元素名称。

第一步:创建binding.xjb文件

放在src/main/resources/xjb目录下,内容如下:

<jaxb:bindings version="2.1"
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <!-- 绑定目标XSD,设置全局规则 -->
    <jaxb:bindings schemaLocation="你的XSD文件路径(比如src/main/resources/xsd/your-schema.xsd)" node="/xsd:schema">
        <!-- 指定生成的包名 -->
        <jaxb:schemaBindings>
            <jaxb:package name="com.yourcompany.model"/>
            <!-- 配置默认命名空间,前缀为空(即默认命名空间) -->
            <jaxb:xmlNs prefix="" namespace="https://transaction.elementexpress.com"/>
        </jaxb:schemaBindings>

        <!-- 强制所有元素使用qualified格式(继承默认命名空间) -->
        <jaxb:globalBindings elementFormDefault="qualified"/>

        <!-- 确保Application元素生成的Java属性名是application,但XML元素名保留XSD的Application -->
        <jaxb:bindings node="//xsd:element[@name='Application']">
            <jaxb:property name="application"/>
        </jaxb:bindings>

        <!-- 确保ApplicationID元素的XML名称保留大写 -->
        <jaxb:bindings node="//xsd:element[@name='ApplicationID']">
            <jaxb:property name="applicationID"/>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

第二步:用Maven JAXB插件重新生成类

在pom.xml里配置插件,指定绑定文件:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.5.0</version>
    <executions>
        <execution>
            <goals>
                <goal>xjc</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <schemaDirectory>${project.basedir}/src/main/resources/xsd</schemaDirectory>
        <bindingDirectory>${project.basedir}/src/main/resources/xjb</bindingDirectory>
        <bindingFiles>binding.xjb</bindingFiles>
        <packageName>com.yourcompany.model</packageName>
    </configuration>
</plugin>

执行mvn jaxb2:xjc重新生成类,此时要检查两个关键点:

  • 生成的com.yourcompany.model/package-info.java必须有以下注解:
    @XmlSchema(
        namespace = "https://transaction.elementexpress.com",
        elementFormDefault = XmlNsForm.QUALIFIED
    )
    package com.yourcompany.model;
    
    import javax.xml.bind.annotation.XmlNsForm;
    import javax.xml.bind.annotation.XmlSchema;
    
  • Application类里的applicationID字段注解应该是:
    @XmlElement(name = "ApplicationID", namespace = "https://transaction.elementexpress.com", required = true)
    protected String applicationID;
    
  • BatchTotalsQuery类里的application字段注解应该是:
    @XmlElement(name = "Application", namespace = "https://transaction.elementexpress.com", required = true)
    protected Application application;
    

2. 配置RestTemplate的JAXB转换器,强制输出命名空间

Spring默认的JAXB转换器可能不会主动输出默认命名空间,需要自定义Marshaller配置:

创建RestTemplate配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;

import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.Marshaller;

@Configuration
public class RestTemplateConfig {

    @Bean
    public Jaxb2Marshaller jaxb2Marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        // 指定生成类的包路径
        marshaller.setPackagesToScan("com.yourcompany.model");
        
        // 配置Marshaller属性,强制输出默认命名空间和格式化XML
        Map<String, Object> properties = new HashMap<>();
        properties.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        properties.put(Marshaller.JAXB_DEFAULT_NAMESPACE, "https://transaction.elementexpress.com");
        marshaller.setMarshallerProperties(properties);
        
        return marshaller;
    }

    @Bean
    public RestTemplate restTemplate(Jaxb2Marshaller jaxb2Marshaller) {
        RestTemplate restTemplate = new RestTemplate();
        
        // 替换默认的JAXB转换器为自定义的
        Jaxb2RootElementHttpMessageConverter converter = new Jaxb2RootElementHttpMessageConverter();
        converter.setMarshaller(jaxb2Marshaller);
        converter.setUnmarshaller(jaxb2Marshaller);
        
        // 移除原来的JAXB转换器,添加自定义的
        restTemplate.getMessageConverters().removeIf(c -> c instanceof Jaxb2RootElementHttpMessageConverter);
        restTemplate.getMessageConverters().add(converter);
        
        return restTemplate;
    }
}

3. 用配置好的RestTemplate发送请求

现在再用你的代码发送请求,生成的XML就会符合要求了:

@Autowired
private RestTemplate restTemplate;

public void sendBatchQuery() {
    BatchTotalsQuery query = new BatchTotalsQuery();
    Application application = new Application();
    application.setApplicationID("20586");
    query.setApplication(application);

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_XML);
    HttpEntity<BatchTotalsQuery> entity = new HttpEntity<>(query, headers);

    // 发送请求
    String response = restTemplate.postForObject("https://certtransaction.elementexpress.com", entity, String.class);
}

此时生成的XML会是你想要的:

<BatchTotalsQuery xmlns="https://transaction.elementexpress.com">
    <Application>
        <ApplicationID>20586</ApplicationID>
    </Application>
</BatchTotalsQuery>

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 11:15:36