Spring Batch生成XML报xmlns重复绑定错误该如何解决
错误原因
该异常是由于StaxEventItemWriter和Jaxb2Marshaller同时尝试声明默认命名空间,值冲突导致:你在StaxEventItemWriter的根节点属性中指定了默认命名空间为http://entreprise.uk/ns,但Person类没有配置对应命名空间,JAXB序列化时会默认将默认命名空间绑定为空值,XML规范不允许同一上下文重复绑定默认命名空间,因此抛出错误。
解决方案
按照以下步骤修改配置即可生成符合要求的XML:
步骤1:修改Person类注解
给@XmlRootElement增加namespace属性,和目标命名空间保持一致:
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "Person", namespace = "http://entreprise.uk/ns") public class Person { // 原有属性和逻辑保持不变 }
步骤2:调整Writer配置
移除StaxEventItemWriter中setRootElementAttributes配置的xmlns属性,改为给JAXB marshaller配置命名空间前缀映射,确保默认命名空间正确生效:
Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(Person.class); // 配置JAXB序列化属性 Map<String, Object> marshallerProps = new HashMap<>(); marshallerProps.put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // 适配JAXB实现的命名空间前缀映射,让目标命名空间作为默认无前缀的命名空间 marshallerProps.put("com.sun.xml.bind.namespacePrefixMapper", new com.sun.xml.bind.marshaller.NamespacePrefixMapper() { @Override public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { if ("http://entreprise.uk/ns".equals(namespaceUri)) { return ""; } return suggestion; } }); marshaller.setMarshallerProperties(marshallerProps); StaxEventItemWriter<Person> itemWriter = new StaxEventItemWriter<>(); itemWriter.setRootTagName("Persons"); itemWriter.setMarshaller(marshaller); // 不需要单独配置根节点的xmlns属性,JAXB会自动生成 itemWriter.setResource(new FileSystemResource(Paths.get("personOutput.xml").toFile())); itemWriter.afterPropertiesSet(); return itemWriter;
可选兼容方案
如果你不想修改Person类的注解,可通过自定义StaxEventItemWriter根节点写入逻辑实现,避免命名空间重复声明冲突:
StaxEventItemWriter<Person> itemWriter = new StaxEventItemWriter<>() { @Override protected void startDocument(XMLEventWriter writer) throws XMLStreamException { super.startDocument(writer); // 手动创建带命名空间的根元素 XMLEventFactory eventFactory = XMLEventFactory.newInstance(); Namespace defaultNs = eventFactory.createNamespace("http://entreprise.uk/ns"); StartElement root = eventFactory.createStartElement("", "http://entreprise.uk/ns", "Persons", null, Collections.singleton(defaultNs).iterator()); writer.add(root); } @Override protected void endDocument(XMLEventWriter writer) throws XMLStreamException { XMLEventFactory eventFactory = XMLEventFactory.newInstance(); writer.add(eventFactory.createEndElement("", "http://entreprise.uk/ns", "Persons")); super.endDocument(writer); } }; // 不需要配置setRootTagName和setRootElementAttributes itemWriter.setMarshaller(marshaller); itemWriter.setResource(new FileSystemResource(Paths.get("personOutput.xml").toFile())); itemWriter.afterPropertiesSet();
内容的提问来源于stack exchange,提问作者flywell
相关产品推荐
相关产品推荐

