1. Overview
1.概述
While JSON is a de-facto standard for RESTful services, in some cases, we might want to work with XML. We can fall back to XML for different reasons: legacy applications, using a more verbose format, standardized schemas, etc.
虽然 JSON 是 RESTful 服务的事实标准,但在某些情况下,我们可能希望使用 XML。我们可以出于不同的原因使用 XML:传统应用程序、使用更冗长的格式、标准化模式等。
Spring provides us with a simple way to support XML endpoints with no work from our side. In this tutorial, we’ll learn how to leverage Jackson XML to approach this problem.
Spring为我们提供了一种简单的方法来支持 XML 端点,而我们无需做任何工作。在本教程中,我们将学习如何利用 Jackson XML 来解决这一问题。
2. Dependencies
2.依赖关系
The first step is to add the dependency to allow XML mapping. Even if we’re using spring-boot-starter-web, it doesn’t contain the libraries for XML support by default:
第一步是添加 dependency 以允许 XML 映射。即使我们使用的是spring-boot-starter-web,它默认也不包含支持 XML 的库:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.16.0</version>
</dependency>
We can leverage the Spring Boot version management system by omitting the version, ensuring the correct Jackson library versions are used across all dependencies.
通过省略版本,我们可以利用 Spring Boot 版本管理系统,确保在所有依赖项中使用正确的 Jackson 库版本。
Alternatively, we can use JAXB to do the same thing, but overall, it’s more verbose, and Jackson generally provides us with a nicer API. However, if we’re using Java 8, JAXB libraries are located in the javax package with the implementation, and we won’t need to add any other dependencies to our application.
或者,我们也可以使用 JAXB 来完成同样的工作,但总体而言,JAXB 更为冗长,而且 Jackson 一般会为我们提供更漂亮的 API。不过,如果我们使用的是 Java 8,JAXB库位于 javax 包中的实现中,因此我们无需在应用程序中添加任何其他依赖项。
On Java versions starting from 9, the javax package was moved and renamed to jakarta, so JAXB requires an additional dependency:
在 Java 9 开始的版本中,javax 包被移动并更名为 jakarta,因此 JAXB 需要附加依赖关系:。
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
Also, it needs a runtime implementation for XML mappers, which might create too much confusion and subtle issues.
此外,它还需要 XML 映射器的运行时实施,这可能会造成太多的混乱和微妙的问题。
3. Endpoints
3.终点
Since JSON is a default format for Spring REST controllers, we need to explicitly identify the endpoints that consume and produce XML. Let’s consider this simple echo controller:
由于 JSON 是 Spring REST 控制器的默认格式,因此我们需要明确标识消耗和生成 XML 的端点。让我们来看看这个简单的 echo 控制器:
@RestController
@RequestMapping("/users")
public class UserEchoController {
@ResponseStatus(HttpStatus.CREATED)
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public User echoJsonUser(@RequestBody User user) {
return user;
}
@ResponseStatus(HttpStatus.CREATED)
@PostMapping(consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
public User echoXmlUser(@RequestBody User user) {
return user;
}
}
The only purpose of the controller is to receive a User and send it back. The only difference between these endpoints is that the first works with JSON format. We specify it explicitly in @PostMapping, but for JSON, we can omit the consumes and produces attributes.
控制器的唯一目的是接收 User 并将其发送回去。这些端点之间的唯一区别是,第一个端点使用 JSON 格式。我们在 @PostMapping 中明确指定了它,但对于 JSON 格式,我们可以省略 consumes 和 produces 属性。
The second endpoint works with XML. We must identify it explicitly by providing the correct types to the consumes and produces values. This is the only thing we need to do to configure the endpoint.
第二个端点使用 XML。我们必须为 consumes 和 produces 值提供正确的类型,从而明确地识别它。
4. Mappings
4.映射
We’ll be working with the following User class:
我们将使用以下 User 类:
public class User {
private Long id;
private String firstName;
private String secondName;
public User() {
}
// getters, setters, equals, hashCode
}
Technically, we don’t need anything else, and the endpoint should support the following XML straight away:
从技术上讲,我们不需要其他任何东西,端点应能直接支持以下 XML:
<User>
<id>1</id>
<firstName>John</firstName>
<secondName>Doe</secondName>
</User>
However, if we want to provide other names or translate legacy conventions to ones we use in our application, we might want to use special annotations. @JacksonXmlRootElement and @JacksonXmlProperty are the most common annotations to use for this.
但是,如果我们想提供其他名称或将传统约定转换为我们在应用程序中使用的名称,我们可能需要使用特殊注解。 @JacksonXmlRootElement和@JacksonXmlProperty是最常用的注解。
If we opt to use JAXB, it is also possible to configure our mappings with annotations only, and there’s a different set of annotations, for example, @XmlRootElement and @XmlAttribute. In general, the process is quite similar. However, note that JAXB might require explicit mapping.
如果我们选择使用 JAXB,也可以仅使用注解来配置映射,并且有不同的 注解集,例如,@XmlRootElement 和 @XmlAttribute。总的来说,过程非常相似。不过,请注意 JAXB 可能需要显式映射。
5. Conclusion
5.结论
Spring REST provides us with a convenient way to create RESTful services. However, they aren’t constrained to JSON only. We can use them with other formats, for example, XML. Overall, the transition is transparent, and the entire setup is made with several strategically placed annotations.
Spring REST 为我们提供了创建 RESTful 服务的便捷方法。不过,它们并不局限于 JSON 格式。我们还可以使用其他格式,例如 XML。总的来说,过渡是透明的,整个设置是通过几个战略性放置的注解完成的。
As usual, the code from the tutorial is available over on GitHub.
与往常一样,教程中的代码可在 GitHub 上获取。