从零开始 Spring Boot 11:返回数据
在之前文章中,已经展示了如何在前后端分离的Web应用中封装并返回统一格式的返回值,但之前展示的返回值封装的相当简单,只能用于简单示例,今天对返回值进行进一步封装和重构。
本篇文章会在从零开始 Spring Boot 9:Shiro - 魔芋红茶’s blog (icexmoon.cn)中最终代码的基础上进行修改。你可以从下面的链接获取对应的示例代码:
为了说明之前设计的一些缺陷,这里为这个示例代码添加上Swagger文档支持,具体方法见从零开始 Spring Boot 8:Swagger - 魔芋红茶’s blog (icexmoon.cn),这里不再详细说明。
因为这个示例程序使用Shiro做权限验证,所以需要将Swagger相关路径添加为例外,不经过Shiro验证:
// 配置不会被拦截的链接 顺序判断
map.put("/swagger-ui/**", "anon");
map.put("/swagger-resources/**", "anon");
map.put("/v3/api-docs/**", "anon");
map.put("/static/**", "anon");
关于Shiro可以阅读从零开始 Spring Boot 9:Shiro - 魔芋红茶’s blog (icexmoon.cn)。
现在查看Swagger你就会发现一个问题:
所有接口的返回值都是String
类型,所以无法通过Swagger
文档查看具体的返回值格式,也就谈不上前后端分离开发时让前端通过Swagger文档来协同开发。
之所以这样,是因为我们在Controller
中返回的是String
类型:
@RequiresRoles(value = {
"guest", "manager"}, logical = Logical.OR)
@GetMapping("/book")
@ApiOperation("获取所有图书列表")
public String listAllBooks() {
Result result = new Result();
List<Book> books = bookService.list();
result.setData(books);
return result.toString();
}
而Swagger
正是通过展示Controller
中方法的返回值类型来阐述具体接口的返回值格式。
所以,我们需要让接口能直接返回具体类型而非String
。
但是这样会产生另一个问题,如果返回的是具体的业务类型,那如何将其封装为统一的返回值格式?
其实可以利用Spring的拦截器来实现这点。
处理返回值
我们先看新封装的统一返回值类型:
package cn.icexmoon.demo.books.system.result;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class Result {
public enum ErrorCode {
SUCCESS(200, "成功"),
DB_NO_DATA(500, "数据库数据缺失"),
PARAM_CHECK(400, "没有通过参数校验"),
LOGIN_ERROR(400, "登录失败"),
NO_PRIORITY(401, "缺少操作的相关权限"),
REQUEST_PARSE(402, "HTTP请求解析错误"),
TIME_PARSE(403, "时间解析出错"),
NEED_LOGIN(404, "需要登录"),
DEFAULT_ERROR(501, "默认错误"),
NETWORK_ERROR(502, "网络错误");
private Integer code;
private String desc;
private ErrorCode(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return code;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return this.code.toString();
}
}
@ApiModelProperty("调用成功/失败"