如何配置Feign/JAXB将空列表序列化为带空内容的标签
解决Feign/JAXB空列表生成自闭合XML标签的问题
当通过Feign调用SOAP服务时,JAXB将空列表序列化为自闭合标签<someName />,要改成成对标签<someName></someName>,可以通过以下几种方式实现:
方法一:配置JAXB Marshaller(基于MOXy实现)
如果使用EclipseLink MOXy作为JAXB实现(需在jaxb.properties中指定javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory),可以在创建Marshaller时设置属性强制生成成对空标签:
Marshaller marshaller = jaxbContext.createMarshaller(); // 开启空元素成对标签生成 marshaller.setProperty("eclipselink.marshal-empty-elements", Boolean.TRUE);
如果是Feign集成场景,可自定义JAXB编码器注入该配置,替换默认编码器。
方法二:自定义XmlAdapter处理空列表
创建适配器类,将空列表转换为非null的空集合,触发JAXB生成成对标签:
import javax.xml.bind.annotation.adapters.XmlAdapter; import java.util.ArrayList; import java.util.List; public class EmptyListAdapter extends XmlAdapter<List<String>, List<String>> { @Override public List<String> unmarshal(List<String> v) throws Exception { return v; } @Override public List<String> marshal(List<String> v) throws Exception { return (v == null || v.isEmpty()) ? new ArrayList<>() : v; } }
无需修改生成代码的配置方式
通过JAXB外部绑定文件(binding.xml),在生成代码时自动为目标字段添加适配器:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1"> <jaxb:bindings schemaLocation="your-service.wsdl" node="//xs:element[@name='someName']"> <jaxb:property> <jaxb:typeAdapter value="com.your.package.EmptyListAdapter"/> </jaxb:property> </jaxb:bindings> </jaxb:bindings>
生成代码时指定该绑定文件(如Maven的maven-jaxb2-plugin添加<bindingDirectory>配置)。
方法三:自定义Feign编码器替换自闭合标签
如果上述方法不生效,可在Feign编码器中手动替换XML内容:
public class CustomJaxbEncoder extends JaxbEncoder { public CustomJaxbEncoder(JAXBContext context) { super(context); } @Override public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException { try { StringWriter writer = new StringWriter(); getJAXBContext().createMarshaller().marshal(object, writer); // 替换自闭合标签为成对标签 String processedXml = writer.toString().replaceAll("<someName />", "<someName></someName>"); template.body(processedXml, StandardCharsets.UTF_8); } catch (JAXBException e) { throw new EncodeException("XML序列化失败", e); } } }
然后在Feign客户端配置中注入该编码器:
@Configuration public class SoapClientConfig { @Bean public Encoder feignEncoder() throws JAXBException { JAXBContext context = JAXBContext.newInstance(YourGeneratedRequestClass.class); return new CustomJaxbEncoder(context); } }
内容的提问来源于stack exchange,提问作者Rafał Borkowski
相关产品推荐
相关产品推荐

