在Spring Boot中,返回JSON数据非常简单,spring-boot-starter-web依赖自带了Jackson库,它可以自动将Java对象序列化为JSON格式。
Jackson支持将各种Java对象序列化为JSON,包括列表(List)、映射(Map)、集合(Set)、基本数据类型及其包装类等。
当使用@RestController注解时,Spring Boot会自动使用Jackson库来完成这些对象的序列化。例如,基于2.2.2节创建的Book类,在控制器中返回数据信息,代码如下。
@RestController @RequestMapping("/books") public class BookController { @GetMapping("/{id}") public Book getBookById(@PathVariable Long id) { // 实际应用中,可能会返回从数据库中查询的数据 return new Book("The Great Gatsby", "F. Scott Fitzgerald"); } }
需要修改Book类,为其添加构造器,代码如下。
public Book(String title, String author) { this.title = title; this.author = author; }
当访问/books/1(或任何ID)时,会得到以下JSON响应。
{ "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" }
上述只是返回JSON数据的基本示例。实际应用中,可能还需要处理更复杂的数据结构,如错误处理、HTTP状态码等,为了保持API的一致性和可读性,许多项目都会封装一个公共的结果类来标准化响应的结构。这样,不管请求是成功还是失败,返回给客户端的格式都是一致的。这种模式不仅使前端开发更简单,还使后端代码更具组织性。
以下是一个简单的公共结果类示例。
public class ApiResponse<T> { private boolean success; // 请求是否成功 private String message; // 错误消息 private T data; // 返回的数据 private int code; // 自定义状态码 // 省略构造函数、Getter和Setter方法 // 成功时的静态工厂方法 public static <T> ApiResponse<T> success(T data) { ApiResponse<T> response = new ApiResponse<>(); response.setSuccess(true); response.setData(data); response.setCode(20000); // 自定义成功码 return response; } // 失败时的静态工厂方法 public static <T> ApiResponse<T> error(String message, int errorCode) { ApiResponse<T> response = new ApiResponse<>(); response.setSuccess(false); response.setMessage(message); response.setCode(errorCode); // 自定义错误码 return response; } }
ApiResponse<T>是一个用于Spring Boot应用程序的通用响应结果类,旨在标准化API响应。该类使用Java泛型,允许不同类型的数据作为响应返回,如String、List<Book>或其他自定义对象。
ApiResponse<T>的成员变量用于封装数据及表示请求成功或失败的信息。
success:布尔值,表示API请求是否成功。通常成功执行的业务逻辑设置为true,否则为false。
message:存储请求失败时的错误消息,如“资源未找到”等。
data:泛型字段,用于存储请求成功时返回的数据。
code:整数值,表示自定义的状态码。例如,可以用20000表示成功的状态,其他数字表示不同类型的错误或状态。
类中提供了两个静态工厂方法用于创建ApiResponse对象,其中:
success(T data):用于创建表示成功响应的对象。设置success为true,并将数据设置为data字段。
error(String message, int errorCode):创建表示失败响应的对象。设置success为false,message字段为错误消息,code为传入的自定义错误码。
在控制器中,使用ApiResponse<T>类可以返回结构化的响应,包括成功和失败的场景,代码如下。
@RestController @RestController @RequestMapping("/books") public class BookController { @GetMapping("/{id}") public ApiResponse<Book> getBookById(@PathVariable Long id) { // 假设查找书籍,这里只是模拟 Book book = findBookById(id); if (book != null) { return ApiResponse.success(book); } else { return ApiResponse.error("Book not found", 40000); // 使用自定义 错误码 } } }
对于成功的请求,响应可能是:
{ "success": true, "data": { "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" }, "code": 20000 }
对于失败的请求,响应可能是:
{ "success": false, "message": "Book not found", "code": 40000 }
通过这种方式,ApiResponse<T>类不仅提供了操作结果的信息(成功或失败),还通过code字段提供了更具体的状态描述,使得API的使用者能够更清晰地理解响应的含义。
需要注意的是,在上述案例中,无论请求成功还是失败,HTTP状态码始终保持为200。这意味着从HTTP的角度看,所有请求都被视为成功。
然而,具体的业务逻辑结果是通过自定义状态码传达的。此种方式可以减少由于不同HTTP状态码引起的潜在混淆,特别是在复杂的应用程序中,其中业务逻辑可能比HTTP协议提供的状态更为复杂。