Spring Boot Rest XML example - Web service with XML Response - BezKoderhttps://www.bezkoder.com/spring-boot-rest-xml/
在本 Spring Boot 教程中,我将向您展示一个 Restful Web 服务示例,其中 Spring REST 控制器可以接收/使用 XML 请求正文并返回 XML 响应而不是 JSON。我们还使用 Spring Data JPA 与数据库(MySQL/PostgreSQL)进行交互。
更多实践:
– Spring Boot、Spring Data JPA – 构建 Rest CRUD API 示例
– Spring Boot + GraphQL + MySQL 示例
部署:
–在 AWS 上部署 Spring Boot 应用程序 – Elastic Beanstalk
– Docker Compose:Spring Boot 和 MySQL 示例
内容[隐藏]
Spring Boot XML REST 服务返回 XML 响应Spring Boot Rest XML 示例概述技术项目结构创建和设置 Spring Boot 项目配置 Spring Datasource、JPA、Hibernate定义数据模型创建存储库接口为 XML 类型配置内容协商创建 Spring Rest API 控制器运行和测试结论延伸阅读源代码
Spring Boot XML REST 服务呈现 XML 响应的方法有两种:
使用 Jackson XML 扩展 ( jackson-dataformat-xml) 来呈现 XML 响应很容易,只需添加以下依赖项:
com.fasterxml.jackson.dataformat jackson-dataformat-xml
使用具有依赖关系的 JAXB:
org.glassfish.jaxb jaxb-runtime
所以 XML 可以通过@XmlRootElement在数据模型 lass 处注解来渲染:
@XmlRootElement
public class Tutorial {
private String title;
// .. getters and setters
}
在这个例子中,我们将使用第一种方式。
返回 XML 响应MediaType.APPLICATION_XML_VALUE您可以通过使用作为注释的produces值来告诉控制器哪些方法应该返回 XML 响应。@RequestMapping
@RequestMapping(value="/tutorials/{id}", produces=MediaType.APPLICATION_XML_VALUE)
public ResponseEntity getTutorialById(@PathVariable("id") long id) {
// ...
}
如果您想让所有 Controller 方法都返回 XML 响应,则不必用produces=MediaType.APPLICATION_XML_VALUE. 只需通过实施WebMvcConfigurer和覆盖来实施内容协商configureContentNegotiation()。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_XML);
}
}
Spring Boot Rest XML 示例概述
我们将构建一个为教程应用程序提供 CRUD API 的 Restful Web 服务:
每个教程都有 ID、标题、描述、发布状态。API 帮助创建、检索、更新、删除教程。APIs 还支持自定义查找器方法,例如按已发布状态或按标题查找。XML 是 HTTP 请求和响应的内容类型。
以下是 API:
| 方法 | 网址 | 行动 |
|---|---|---|
| 邮政 | /api/教程 | 创建新教程 |
| 得到 | /api/教程 | 检索所有教程 |
| 得到 | /api/tutorials/:id | 检索教程:id |
| 放 | /api/tutorials/:id | 更新教程:id |
| 删除 | /api/tutorials/:id | 删除教程:id |
| 删除 | /api/教程 | 删除所有教程 |
| 得到 | /api/教程/已发布 | 查找所有已发布的教程 |
| 得到 | /api/tutorials?title=[关键字] | 查找标题包含的所有教程keyword |
– 我们使用 Spring Data JPA 的 CRUD 操作和查找方法JpaRepository。
– 根据我们配置项目依赖和数据源的方式,数据库可以是 PostgreSQL 或 MySQL。
爪哇 8Spring Boot 2.2.1(带有 Spring Web MVC、Spring Data JPA)PostgreSQL/MySQLMaven 3.6.1杰克逊数据格式 XML 2.10.1 项目结构
–WebConfig实现WebMvcConfigurer。这是我们设置默认内容类型的地方。
–Tutorial数据模型类对应实体和表教程。
–是为 CRUD 方法和自定义查找器方法TutorialRepository扩展JpaRepository的接口。它将自动装配到TutorialController.
–TutorialController是一个RestController,它具有 RESTful 请求的请求映射方法,例如:getAllTutorials、createTutorial、updateTutorial、deleteTutorial、findByPublished …
– Spring Datasource、JPA 和 Hibernate 的配置应用程序.properties。
– pom.xml包含 Spring Boot、ackson Dataformat XML 和 MySQL/PostgreSQL 的依赖项。
使用Spring Web 工具或您的开发工具(Spring Tool Suite、Eclipse、Intellij)创建一个 Spring Boot 项目。
然后打开pom.xml并添加这些依赖项:
org.springframework.boot spring-boot-starter-data-jpaorg.springframework.boot spring-boot-starter-webcom.fasterxml.jackson.dataformat jackson-dataformat-xml
我们还需要再添加一个依赖项。
– 如果你想使用MySQL:
mysql mysql-connector-javaruntime
– 或PostgreSQL:
配置 Spring Datasource、JPA、Hibernateorg.postgresql postgresqlruntime
在 src/main/resources 文件夹下,打开 application.properties 并写入这些行。
– 对于 MySQL:
spring.datasource.url= jdbc:mysql://localhost:3306/testdb?useSSL=false spring.datasource.username= root spring.datasource.password= 123456 spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect # Hibernate ddl auto (create, create-drop, validate, update) spring.jpa.hibernate.ddl-auto= update
– 对于 PostgreSQL:
spring.datasource.url= jdbc:postgresql://localhost:5432/testdb spring.datasource.username= postgres spring.datasource.password= 123 spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect # Hibernate ddl auto (create, create-drop, validate, update) spring.jpa.hibernate.ddl-auto= update
spring.datasource.username&spring.datasource.password属性与您的数据库安装相同。Spring Boot 使用 Hibernate 进行 JPA 实现,我们MySQL5InnoDBDialect为 MySQL 或PostgreSQLDialectPostgreSQL配置spring.jpa.hibernate.ddl-auto用于数据库初始化。我们将 value 设置为 value,update以便在数据库中创建一个表,自动对应于定义的数据模型。对模型的任何更改也将触发对表的更新。对于生产,这个属性应该是validate。 定义数据模型
我们的数据模型是具有四个字段的教程:id、title、description、published。
在模型包中,我们定义了Tutorial类。
model/Tutorial.java
package com.bezkoder.spring.datajpa.xml.model;
import javax.persistence.*;
@Entity
@Table(name = "tutorials")
public class Tutorial {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "title")
private String title;
@Column(name = "description")
private String description;
@Column(name = "isPublished")
private boolean published;
public Tutorial() {
}
public Tutorial(String title, String description, boolean published) {
this.title = title;
this.description = description;
this.published = published;
}
public long getId() {
return id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isPublished() {
return published;
}
public void setPublished(boolean isPublished) {
this.published = isPublished;
}
@Override
public String toString() {
return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]";
}
}
–@Entity注解表明该类是一个持久的 Java 类。
–@Table注释提供映射该实体的表。
–@Id注释用于主键。
–@GeneratedValue注解用于定义主键的生成策略。GenerationType.AUTO表示自动增量字段。
–@Column注释用于定义数据库中映射注释字段的列。
让我们创建一个存储库以与数据库中的教程进行交互。
在存储库包中,创建TutorialRepository扩展接口JpaRepository。
repository/TutorialRepository.java
package com.bezkoder.spring.datajpa.xml.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import com.bezkoder.spring.datajpa.xml.model.Tutorial; public interface TutorialRepository extends JpaRepository{ List findByPublished(boolean published); List findByTitleContaining(String title); }
现在我们可以使用 JpaRepository 的方法:save(), findOne(), findById(), findAll(), count(), delete(), deleteById()... 而不实现这些方法。
我们还定义了自定义查找器方法:
– findByPublished():返回所有published具有输入值的教程published。
- findByTitleContaining():返回所有标题包含输入的教程title。
该实现由Spring Data JPA自动插入。
为 XML 类型配置内容协商现在我们要在我们的 Spring Boot 项目中实现内容协商。
config/WebConfig.java
package com.bezkoder.spring.datajpa.xml.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_XML);
}
}
创建 Spring Rest API 控制器
最后,我们创建一个控制器,提供用于创建、检索、更新、删除和查找教程的 API。
controller/TutorialController.java
package com.bezkoder.spring.datajpa.xml.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.bezkoder.spring.datajpa.xml.model.Tutorial;
import com.bezkoder.spring.datajpa.xml.repository.TutorialRepository;
@CrossOrigin(origins = "http://localhost:8081")
@RestController
@RequestMapping("/api")
public class TutorialController {
@Autowired
TutorialRepository tutorialRepository;
@GetMapping("/tutorials")
public ResponseEntity> getAllTutorials(@RequestParam(required = false) String title) {
try {
List tutorials = new ArrayList();
if (title == null)
tutorialRepository.findAll().forEach(tutorials::add);
else
tutorialRepository.findByTitleContaining(title).forEach(tutorials::add);
if (tutorials.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(tutorials, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping("/tutorials/{id}")
public ResponseEntity getTutorialById(@PathVariable("id") long id) {
Optional tutorialData = tutorialRepository.findById(id);
if (tutorialData.isPresent()) {
return new ResponseEntity<>(tutorialData.get(), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PostMapping("/tutorials")
public ResponseEntity createTutorial(@RequestBody Tutorial tutorial) {
try {
Tutorial _tutorial = tutorialRepository.save(new Tutorial(tutorial.getTitle(), tutorial.getDescription(), false));
return new ResponseEntity<>(_tutorial, HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.EXPECTATION_FAILED);
}
}
@PutMapping("/tutorials/{id}")
public ResponseEntity updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
Optional tutorialData = tutorialRepository.findById(id);
if (tutorialData.isPresent()) {
Tutorial _tutorial = tutorialData.get();
_tutorial.setTitle(tutorial.getTitle());
_tutorial.setDescription(tutorial.getDescription());
_tutorial.setPublished(tutorial.isPublished());
return new ResponseEntity<>(tutorialRepository.save(_tutorial), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@DeleteMapping("/tutorials/{id}")
public ResponseEntity deleteTutorial(@PathVariable("id") long id) {
try {
tutorialRepository.deleteById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.EXPECTATION_FAILED);
}
}
@DeleteMapping("/tutorials")
public ResponseEntity deleteAllTutorials() {
try {
tutorialRepository.deleteAll();
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.EXPECTATION_FAILED);
}
}
@GetMapping("/tutorials/published")
public ResponseEntity> findByPublished() {
try {
List tutorials = tutorialRepository.findByPublished(true);
if (tutorials.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(tutorials, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.EXPECTATION_FAILED);
}
}
}
–@CrossOrigin用于配置允许的来源。
–@RestController注释用于定义控制器并指示方法的返回值应绑定到 Web 响应体。
–@RequestMapping("/api")声明控制器中所有 APIs 的 url 都以/api.
– 我们使用@Autowired注入TutorialRepositorybean 到局部变量。
使用命令运行 Spring Boot 应用程序:mvn spring-boot:run。
教程表将在数据库中自动生成。
例如,如果您检查 MySQL,您会看到如下内容:
mysql> describe tutorials; +--------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+-------+ | id | bigint(20) | NO | PRI | NULL | | | description | varchar(255) | YES | | NULL | | | is_published | bit(1) | YES | | NULL | | | title | varchar(255) | YES | | NULL | | +--------------+--------------+------+-----+---------+-------+
创建教程:
mysql> select * from tutorials; +----+-----------------------+--------------+--------+ | id | description | is_published | title | +----+-----------------------+--------------+--------+ | 1 | Tut#1 Description | 0 | Tut #1 | | 2 | Tut#2 Description | 0 | Tut #2 | | 3 | Tut#3 Description | 0 | Tut #3 | | 4 | Description for Tut#4 | 0 | Tut #4 | | 5 | Description for Tut#5 | 0 | Tut #5 | +----+-----------------------+--------------+--------+
获取所有教程:
按 ID 获取教程:
更新一些教程:
mysql> select * from tutorials; +----+-----------------------+--------------+---------------------+ | id | description | is_published | title | +----+-----------------------+--------------+---------------------+ | 1 | Tut#1 Desc | 0 | bezkoder.com Tut #1 | | 2 | Tut#2 Description | 0 | Tut #2 | | 3 | Tut#3 Desc | 1 | bezkoder.com Tut #3 | | 4 | Description for Tut#4 | 0 | Tut #4 | | 5 | Tut#5 Desc | 1 | bezkoder.com Tut #5 | +----+-----------------------+--------------+---------------------+
查找所有已发布的教程:
查找标题包含“zkoder”的所有教程:
删除教程:
mysql> select * from tutorials; +----+-------------------+--------------+---------------------+ | id | description | is_published | title | +----+-------------------+--------------+---------------------+ | 1 | Tut#1 Desc | 0 | bezkoder.com Tut #1 | | 2 | Tut#2 Description | 0 | Tut #2 | | 3 | Tut#3 Desc | 1 | bezkoder.com Tut #3 | | 5 | Tut#5 Desc | 1 | bezkoder.com Tut #5 | +----+-------------------+--------------+---------------------+
使用 API 删除所有教程:DELETe http://localhost:8080/api/tutorials/
mysql> select * from tutorials; Empty set (0.00 sec)结论
今天我们构建了一个 Spring Boot Rest XML 示例,使用 Jackson XML 扩展来渲染 XML 和 Spring Data JPA 以与 MySQL/PostgreSQL 交互。您已经知道在请求正文中使用 XML 并返回 XML 响应的方法。
如果您想了解有关在请求和响应中处理 JSON 数据的 Spring Boot Webservice 的更多信息,请访问:
Spring Boot,Spring Data JPA – 构建 Rest CRUD API 示例
快乐学习!再见。
延伸阅读GitHub - FasterXML/jackson-dataformat-xml: Extension for Jackson JSON processor that adds support for serializing POJOs as XML (and deserializing from XML) as an alternative to JSON使用 Spring Security 和 JWT 身份验证保护 Spring Boot 应用程序Spring Data JPA 参考文档
部署:
–在 AWS 上部署 Spring Boot 应用程序 – Elastic Beanstalk
– Docker Compose:Spring Boot 和 MySQL 示例
您可以在Github上找到本教程的完整源代码。



