在以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接口 - 如何优雅的对接口返回内容统一封装?的更多相关文章

  1. SpringBoot接口 - 如何优雅的写Controller并统一异常处理?

    SpringBoot接口如何对异常进行统一封装,并统一返回呢?以上文的参数校验为例,如何优雅的将参数校验的错误信息统一处理并封装返回呢?@pdai 为什么要优雅的处理异常 如果我们不统一的处理异常,经 ...

  2. SpringBoot接口 - 如何优雅的对参数进行校验?

    在以SpringBoot开发Restful接口时, 对于接口的查询参数后台也是要进行校验的,同时还需要给出校验的返回信息放到上文我们统一封装的结构中.那么如何优雅的进行参数的统一校验呢? @pdai ...

  3. SpringBoot接口 - API接口有哪些不安全的因素?如何对接口进行签名?

    在以SpringBoot开发后台API接口时,会存在哪些接口不安全的因素呢?通常如何去解决的呢?本文主要介绍API接口有不安全的因素以及常见的保证接口安全的方式,重点实践如何对接口进行签名.@pdai ...

  4. 2、SpringBoot接口Http协议开发实战8节课(1-6)

    1.SpringBoot2.xHTTP请求配置讲解 简介:SpringBoot2.xHTTP请求注解讲解和简化注解配置技巧 1.@RestController and @RequestMapping是 ...

  5. 【接口】SpringBoot+接口开发(一)

    一.接口的简单介绍 1.什么是接口:接口及服务: 2.接口的分类:(1)系统的内部接口;(2)第三方的外部接口; 3.简述接口原理图: 4.接口协议:是指客户端跟服务器之间或者接口与接口间进行的通讯时 ...

  6. SpringBoot接口 - 如何生成接口文档之非侵入方式(通过注释生成)Smart-Doc?

    通过Swagger系列可以快速生成API文档,但是这种API文档生成是需要在接口上添加注解等,这表明这是一种侵入式方式: 那么有没有非侵入式方式呢, 比如通过注释生成文档? 本文主要介绍非侵入式的方式 ...

  7. 一个注解搞定SpringBoot接口定制属性加解密

    前言 上个月公司另一个团队做的新项目上线后大体上运行稳定,但包括研发负责人在内的两个人在项目上线后立马就跳槽了,然后又交接给了我这个「垃圾回收人员」. 本周甲方另一个厂家的监控平台扫描到我们这个项目某 ...

  8. SpringBoot接口服务处理Whitelabel Error Page(转)

    To switch it off you can set server.error.whitelabel.enabled=false http://stackoverflow.com/question ...

  9. Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API

    不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...

随机推荐

  1. redis中的字典结构是怎样的?

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 基础概念 redis支持的5种数据类型中,有hash类型,hash类型的 ...

  2. 攻防世界-MISC:pure_color

    这是攻防世界高手进阶区的第六题,题目如下: 点击下载附件一,得到一张空白的png图片 用StegSolve打开,然后点击箭头(如下图所示) 多点击几次,即可得到flag 所以,这道题的flag如下: ...

  3. php错误异常及其排错

    错误和异常 错误 php程序自身的问题,一般是由非法的语法,环境问题导致 异常 一般是业务逻辑上出现的不合预期.与正常流程不同的状况,不是语法错误 错误异常继承关系 小括号表示php版本 php7下的 ...

  4. JS 一些概念

    JS 内存机制 基本类型: String | Boolean | Undefined | Number | Nll | Symbol 数据保存在"栈"--先进后出. 数据类型: A ...

  5. java、selenium、图片滑块验证,底部附本地可测试代码

    准备 本地Chrome版本对应WebDriver驱动:http://chromedriver.storage.googleapis.com/index.html maven包 <!-- sele ...

  6. Swift初探02 数组、集合、元组、字典

    数组.集合.元组.字典 每一门语言基本都会有这些数据结构,swift也不例外,而作为一门现代的语言,swift提供了很多的现成的方法给我们选择. 一.数组 01 数组的定义 // 三种声明方式 var ...

  7. Java多线程编程实战02:多线程编程模型

    多线程编程模型 线程安全名词 串行.并发和并行 串行:一个人,将任务一个一个完成 并发:一个人,有策略地同时做多件事情 并行:多个人,每人做一个事情 竞态 名词 竞态:计算结果的正确性与时间有关的现象 ...

  8. 299. Bulls and Cows - LeetCode

    Question 299. Bulls and Cows Solution 题目大意:有一串隐藏的号码,另一个人会猜一串号码(数目相同),如果号码数字与位置都对了,给一个bull,数字对但位置不对给一 ...

  9. NoClassDefFoundError问题

    问题: 遇到一个问题,报NoClassDefFoundError,如下图: NoClassDefFoundError和ClassNotFoundException区别 我们经常被java.lang.C ...

  10. 一文学完Linux常用命令

    一.Linux 终端命令格式 1.终端命令格式 完整版参考链接:Linux常用命令完整版 command [-options] [parameter] 说明: command : 命令名,相应功能的英 ...