SpringBoot接口 - 如何优雅的对接口返回内容统一封装?
在以SpringBoot开发Restful接口时,统一返回方便前端进行开发和封装,以及出现时给出响应编码和信息。@pdai
RESTful API接口?
- 什么是 REST?
Representational State Transfer,翻译是“表现层状态转化”。可以总结为一句话:REST 是所有 Web 应用都应该遵守的架构设计指导原则。
面向资源是 REST 最明显的特征,对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。REST 要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。
- 什么是 RESTful API?
符合 REST 设计标准的 API,即 RESTful API。REST 架构设计,遵循的各项标准和准则,就是 HTTP 协议的表现,换句话说,HTTP 协议就是属于 REST 架构的设计模式。比如,无状态,请求-响应。
Restful相关文档可以参考 https://restfulapi.net/
为什么要统一封装接口
现在大多数项目采用前后分离的模式进行开发,统一返回方便前端进行开发和封装,以及出现时给出响应编码和信息。
以查询某个用户接口而言,如果没有封装, 返回结果如下
{
"userId": 1,
"userName": "赵一"
}
如果封装了,返回正常的结果如下:
{
"timestamp": 11111111111,
"status": 200,
"message": "success",
"data": {
"userId": 1,
"userName": "赵一"
}
}
异常返回结果如下:
{
"timestamp": 11111111111,
"status": 10001,
"message": "User not exist",
"data": null
}
实现案例
如何实现上面的封装呢?
状态码封装
这里以常见的状态码为例,包含responseCode 和 description两个属性。
如果还有其它业务状态码,也可以放到这个类中。
/**
* @author pdai
*/
@Getter
@AllArgsConstructor
public enum ResponseStatus {
SUCCESS("200", "success"),
FAIL("500", "failed"),
HTTP_STATUS_200("200", "ok"),
HTTP_STATUS_400("400", "request error"),
HTTP_STATUS_401("401", "no authentication"),
HTTP_STATUS_403("403", "no authorities"),
HTTP_STATUS_500("500", "server error");
public static final List<ResponseStatus> HTTP_STATUS_ALL = Collections.unmodifiableList(
Arrays.asList(HTTP_STATUS_200, HTTP_STATUS_400, HTTP_STATUS_401, HTTP_STATUS_403, HTTP_STATUS_500
));
/**
* response code
*/
private final String responseCode;
/**
* description.
*/
private final String description;
}
返回内容封装
包含公共的接口返回时间,状态status, 消息message, 以及数据data。
考虑到数据的序列化(比如在网络上传输),这里data有时候还会extends Serializable。
@Data
@Builder
public class ResponseResult<T> {
/**
* response timestamp.
*/
private long timestamp;
/**
* response code, 200 -> OK.
*/
private String status;
/**
* response message.
*/
private String message;
/**
* response data.
*/
private T data;
/**
* response success result wrapper.
*
* @param <T> type of data class
* @return response result
*/
public static <T> ResponseResult<T> success() {
return success(null);
}
/**
* response success result wrapper.
*
* @param data response data
* @param <T> type of data class
* @return response result
*/
public static <T> ResponseResult<T> success(T data) {
return ResponseResult.<T>builder().data(data)
.message(ResponseStatus.SUCCESS.getDescription())
.status(ResponseStatus.SUCCESS.getResponseCode())
.timestamp(System.currentTimeMillis())
.build();
}
/**
* response error result wrapper.
*
* @param message error message
* @param <T> type of data class
* @return response result
*/
public static <T extends Serializable> ResponseResult<T> fail(String message) {
return fail(null, message);
}
/**
* response error result wrapper.
*
* @param data response data
* @param message error message
* @param <T> type of data class
* @return response result
*/
public static <T> ResponseResult<T> fail(T data, String message) {
return ResponseResult.<T>builder().data(data)
.message(message)
.status(ResponseStatus.FAIL.getResponseCode())
.timestamp(System.currentTimeMillis())
.build();
}
}
接口返回时调用
在接口返回时调用, 以用户接口为例
/**
* @author pdai
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
/**
* @param user user param
* @return user
*/
@ApiOperation("Add/Edit User")
@PostMapping("add")
public ResponseResult<User> add(User user) {
if (user.getId()==null || !userService.exists(user.getId())) {
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userService.save(user);
} else {
user.setUpdateTime(LocalDateTime.now());
userService.update(user);
}
return ResponseResult.success(userService.find(user.getId()));
}
/**
* @return user list
*/
@ApiOperation("Query User One")
@GetMapping("edit/{userId}")
public ResponseResult<User> edit(@PathVariable("userId") Long userId) {
return ResponseResult.success(userService.find(userId));
}
}
示例源码
https://github.com/realpdai/tech-pdai-spring-demos
更多内容
告别碎片化学习,无套路一站式体系化学习后端开发: Java 全栈知识体系(https://pdai.tech)
SpringBoot接口 - 如何优雅的对接口返回内容统一封装?的更多相关文章
- SpringBoot接口 - 如何优雅的写Controller并统一异常处理?
SpringBoot接口如何对异常进行统一封装,并统一返回呢?以上文的参数校验为例,如何优雅的将参数校验的错误信息统一处理并封装返回呢?@pdai 为什么要优雅的处理异常 如果我们不统一的处理异常,经 ...
- SpringBoot接口 - 如何优雅的对参数进行校验?
在以SpringBoot开发Restful接口时, 对于接口的查询参数后台也是要进行校验的,同时还需要给出校验的返回信息放到上文我们统一封装的结构中.那么如何优雅的进行参数的统一校验呢? @pdai ...
- SpringBoot接口 - API接口有哪些不安全的因素?如何对接口进行签名?
在以SpringBoot开发后台API接口时,会存在哪些接口不安全的因素呢?通常如何去解决的呢?本文主要介绍API接口有不安全的因素以及常见的保证接口安全的方式,重点实践如何对接口进行签名.@pdai ...
- 2、SpringBoot接口Http协议开发实战8节课(1-6)
1.SpringBoot2.xHTTP请求配置讲解 简介:SpringBoot2.xHTTP请求注解讲解和简化注解配置技巧 1.@RestController and @RequestMapping是 ...
- 【接口】SpringBoot+接口开发(一)
一.接口的简单介绍 1.什么是接口:接口及服务: 2.接口的分类:(1)系统的内部接口;(2)第三方的外部接口; 3.简述接口原理图: 4.接口协议:是指客户端跟服务器之间或者接口与接口间进行的通讯时 ...
- SpringBoot接口 - 如何生成接口文档之非侵入方式(通过注释生成)Smart-Doc?
通过Swagger系列可以快速生成API文档,但是这种API文档生成是需要在接口上添加注解等,这表明这是一种侵入式方式: 那么有没有非侵入式方式呢, 比如通过注释生成文档? 本文主要介绍非侵入式的方式 ...
- 一个注解搞定SpringBoot接口定制属性加解密
前言 上个月公司另一个团队做的新项目上线后大体上运行稳定,但包括研发负责人在内的两个人在项目上线后立马就跳槽了,然后又交接给了我这个「垃圾回收人员」. 本周甲方另一个厂家的监控平台扫描到我们这个项目某 ...
- SpringBoot接口服务处理Whitelabel Error Page(转)
To switch it off you can set server.error.whitelabel.enabled=false http://stackoverflow.com/question ...
- Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API
不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...
随机推荐
- 【图解】面试题:ConcurrentHashMap是如何保证线程安全的
注意:JDK1.7与JDK1.8中的ConcurrentHashMap主要延续HashMap的设计与思想,是在其基础上进行的相应优化 1.JDK1.7中的底层实现原理 (1)JDK1.7Concurr ...
- 一篇讲清楚String、StringBuffer和StringBuild
一.String篇 1.String基本介绍? (jdk文档原文)String类代表字符串. Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例. 说人 ...
- Bootstrap Blazor Table 组件(四)自定义列生成
原文链接:https://www.cnblogs.com/ysmc/p/16223154.html Bootstrap Blazor 官方链接:https://www.blazor.zone/tabl ...
- 通过Go实现AES加密和解密工具
本文包含如下两个内容: AES加密介绍及实现原理 Go实现AES加密和解密工具 AES加密介绍及实现原理 AES( advanced encryption standard)使用相同密钥进行加密和解密 ...
- 用python实现自动化登录禅道系统 设置定时器自动执行脚本
由于各种原因,我想试下用python实现自动登录禅道系统,并且每天定时执行.(本人第一次接触自动化,在大佬眼中门槛都没摸到的类型) 首先缕清思路: 1.实现自动登录禅道系统,用selenium实现2. ...
- CIAGAN: Conditional Identity Anonymization Generative Adversarial Networks阅读笔记
CIAGAN: Conditional Identity Anonymization Generative Adversarial Networks 2020 CVPR 2005.09544.pdf ...
- typora的下载和基本的使用
目录 typora的下载和基本的使用 typora的下载 typora基本的使用 选择自己喜爱的主题 创建标题 进入编程环境 改变文本样式 插入链接 插入图片 有序列表 无序列表 创建表格 单选框 表 ...
- .net 获取IP地址的几种方式
1.获取服务器IP地址: 1) Local_Addr var Local_Addr = Request.ServerVariables.Get("Local_Addr").ToSt ...
- 向sqlserver 数据库插入emoji 表情包
1.emoji 属于特殊字符 所以我们必须使用utf-8 的编码格式进行保存 不过好在sqlserver 默认支持utf-8 2.将需要存储emoji的字段必须设置为nvarchar 类型 因为v ...
- resttemplate 请求方式详解
get 普通请求: restemplate.getForEntity(url,String.class).getBody(); get 导出请求: restemplate.getForEntity(u ...