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

如何在JAXB RI中使用自定义命名空间?解决属性不支持报错

问题解决:JAXB RI自定义命名空间前缀映射配置

错误原因

  1. 属性名错误:JAXB RI(Jakarta EE 4+)中,正确的命名空间前缀映射属性为jakarta.xml.bind.marshaller.NAMESPACE_PREFIX_MAPPER,而非你使用的org.glassfish.jaxb.namespacePrefixMapper或内部runtime属性。
  2. 依赖内部实现:你自定义的映射类继承了GlassFish内部的org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper,这是内部实现类,不应直接依赖,需改用Jakarta规范提供的接口。
  3. 实体无命名空间关联:你的实体类未绑定任何命名空间,导致编组时不会触发前缀映射逻辑。

具体修改步骤

1. 修正自定义NamespacePrefixMapper类

改用Jakarta规范的Marshaller.NamespacePrefixMapper接口,代码如下:

package io.test.convert;

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

public class CustomNamespacePrefixMapper implements Marshaller.NamespacePrefixMapper {
    public static final Map<String, String> NAMESPACE_MAP = Map.of(
            "http://www.w3.org/2001/XMLSchema-instance", "xsi",
            "https://example1.com/", "example1",
            "https://example2.com/", "example2",
            "https://test.com/", "test",
            "https://test2.com/", "test2");

    private Map<String, String> namespaceMap;

    public CustomNamespacePrefixMapper(final Map<String, String> namespaceMap) {
        this.namespaceMap = namespaceMap;
    }

    public CustomNamespacePrefixMapper() {
        this(new HashMap<>(NAMESPACE_MAP));
    }

    @Override
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        return namespaceMap.getOrDefault(namespaceUri, suggestion);
    }
}

2. 给实体类关联命名空间

推荐在包级别配置默认命名空间,在io.test.convert包下创建package-info.java:

@XmlSchema(
        namespace = "https://example1.com/",
        elementFormDefault = XmlNsForm.QUALIFIED,
        xmlns = {
                @XmlNs(prefix = "example1", namespaceURI = "https://example1.com/"),
                @XmlNs(prefix = "test", namespaceURI = "https://test.com/"),
                @XmlNs(prefix = "test2", namespaceURI = "https://test2.com/")
        }
)
package io.test.convert;

import jakarta.xml.bind.annotation.XmlNs;
import jakarta.xml.bind.annotation.XmlNsForm;
import jakarta.xml.bind.annotation.XmlSchema;

也可以直接在类级别指定,比如修改Child1的@XmlRootElement:

@XmlRootElement(name = "Child1", namespace = "https://example1.com/")

3. 修正JAXBContext与Marshaller配置

JAXBContext无需设置前缀映射属性,仅需在Marshaller上用正确属性名配置:

package io.test.convert;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;

public class MainXML {
    public static void main(String[] args) throws Exception {
        // 直接创建JAXBContext,无需传递前缀映射属性
        final JAXBContext jaxbContext = JAXBContext.newInstance("io.test.convert", Thread.currentThread().getContextClassLoader());

        final Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        // 使用Jakarta规范的属性名设置前缀映射
        marshaller.setProperty(Marshaller.NAMESPACE_PREFIX_MAPPER, new CustomNamespacePrefixMapper());

        final Child1 child1 = new Child1();
        child1.setName("Batman");
        child1.setAge("30");
        child1.setType("Superhero");
        child1.setOriginalName("Bruce Wayne");

        marshaller.marshal(child1, System.out);
    }
}

4. 优化依赖配置

可移除jaxb-core依赖,jaxb-runtime已包含核心功能:

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.30</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-xjc</artifactId>
        <version>4.0.4</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>4.0.4</version>
    </dependency>

    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencies>

修改后效果

编组生成的XML会自动带上配置的命名空间前缀,示例输出:

<example1:Child1 xmlns:example1="https://example1.com/" xmlns:test="https://test.com/" xmlns:test2="https://test2.com/">
    <example1:name>Batman</example1:name>
    <example1:age>30</example1:age>
    <example1:originalName>Bruce Wayne</example1:originalName>
</example1:Child1>

内容的提问来源于stack exchange,提问作者BATMAN_2008

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:13:21