springboot RestTemplate 发送xml、接收xml、pojo中的属性转为属性;java对象转xml;xml转java对象

本文介绍了在SpringBoot项目中,如何处理老系统只支持XML接口的情况,包括添加jackson-dataformat-xml依赖,设置MediaType,以及如何使用Jackson注解进行XML到POJO的自动转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

调用第三方接口时,它们的系统比较老,只支持接收xml而不支持json,默认的springboot RestTemplate不支持发送xml,添加依赖就可以解决这个问题。

添加jackson-dataformat-xml依赖

FasterXML/jackson-dataformat-xml是一个xml编、解码库。

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>version</version>
 </dependency>

这个版本号应该填什么呢?根据依赖关系spring-boot-starter-web---->spring-webmvc---->jackson-dataformat-xml,找到pom中的配置。

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
   <artifactId>jackson-dataformat-xml</artifactId>
   <version>2.9.8</version>
   <scope>compile</scope>
   <optional>true</optional>
 </dependency>

顺便说一下,因为它是optional的,所以要引用。

RestTemplate发送xml

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.HttpEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;


HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
final URI uri = UriComponentsBuilder.fromUriString(“url”).build().toUri();
User user= new User();
HttpEntity<User> request = new HttpEntity<>(user, headers);
//响应是xml,也会自动转为POJO
final Result result= restTemplate.postForObject(uri,request , Result.class);

代码中的UserResult都是普通的POJO,发送时会自动的转换为xml,POJO中的属性会转换为xml中的节点,如果要转换为节点的属性,则在属性上添加@JacksonXmlProperty

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;

@Data
public class User{
    /**
     *指定为属性
     */
    @JacksonXmlProperty(isAttribute = true)
    private String name;
    /**
     * 默认的是节点
     */
    private BigDecimal money;
}

jackson-dataformat-xml常用的注解

jackson-dataformat-xml常用的几个注解有@JacksonXmlElementWrapper@JacksonXmlProperty@JacksonXmlRootElement@JacksonXmlText

  • @JacksonXmlElementWrapper
    • 用在集合元素上,可指定名称
  • @JacksonXmlProperty
    • 用在类的属性上,可以指定名称及属性转为节点or属性
  • @JacksonXmlRootElement
    • 指定根元素名称,用在类上
  • @JacksonXmlText
    • 转为xml后没有元素包裹,是个文本节点

更多信息可参考Jackson XML annotations,值得一提的是,对于集合属性,如果要同时指定容器容器内元素的名称,如下

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@JacksonXmlElementWrapper(localName = "users") //容器的名称
@JacksonXmlProperty(localName = "user")//容器元素的名称
private List<User> users;

java转换xml

以上是用Jackson XML annotations实现xml和java之间的转换,如果用RestTemplate来发送、接收xml,那么用以上方式是合适的;有时我们需要手动转换xml和java,那就要用到JAXB(Java Architecture for XML Binding),这是jdk自带的,类都在 javax.xml.bin.*,如将下属xmll转为java对象

<?xml version="1.0" ?>
<root>
   	<user_info  user_name = "姓名1" create_date = "2011/1/7 1:56:08">用户ID1</user_info >
    <user_info user_name = "姓名2" create_date = "2012/2/7 1:56:09">用户ID2</user_info >
</root>

那么类通常如下

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

//这个类是根元素,xml中的根元素是root,所以这里命名为root
@XmlRootElement(name = "root")
//@XmlAccessorType用来控制类的哪些属性序列化到xml或者反序列化到java对象,这里取值XmlAccessType.FIELD,
//表示所有属性,无论私有属性还是公有属性都映射到xml
@XmlAccessorType(XmlAccessType.FIELD)
public class OutpatientEMRIdRoot {

    @XmlElement(name = "user_info ")
    private List<UserInfo> userInfos;
}
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;


@XmlAccessorType(XmlAccessType.FIELD)
public class UserInfo {
    
    @XmlAttribute(name = "user_name")
    private String userName;

    @XmlAttribute(name = "create_date")
    private String createDate;
}
  • @XmlElement表示是一个xml元素
  • @XmlAttribute表示是xml元素的attribute,比如 <ele_name my_attr=""> 这里的my_attr就是xml attribute
  • @XmlAccessorType注解接受一个枚举类型XmlAccessType作为参数,有以下几种可选值:
    • NONE:默认情况下,不自动处理任何成员。必须显式地使用@XmlElement、@XmlAttribute等注解标记成员。
    • PUBLIC_MEMBER:只处理公共成员(公有的字段和方法)。
    • PACKAGE_MEMBER:处理包内可见的成员(包括公有、保护和包内访问级别的字段和方法)。
    • PROTECTED_MEMBER:处理受保护的成员(包括公有和受保护的字段和方法)。
    • FIELD:处理所有字段(无论访问级别)。这是最宽松的设置,通常用于完全控制XML映射,而不需要显式地使用其他注解。
    • DEFAULT:使用JAXB默认的行为,这通常是处理所有公共的getter/setter方法。

转换的关键代码

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import javax.xml.transform.dom.DOMSource;
import javax.xml.bind.JAXBException;

String xml = "";

try {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(new InputSource(new StringReader(xml)));
    JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
    Root root = (Root) unmarshaller.unmarshal(new DOMSource(doc));
} catch (Exception e) {
    e.printStackTrace();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值