Spring Boot 统一响应
文章目录
- Spring Boot 统一响应
- 一. 前言
- 二. 统一响应
- 2.1 字段
- 2.2 错误码
- 2.3 统一响应类
- 三. 调用测试
- 3.1 接口层代码
- 3.2 UT测试用例
一. 前言
前后端交互时,后端会提供RESTful API接口供前端调用,前端调用后,需要响应前端该接口是否调用成功:
- 成功:数据回显到前端,并渲染给客户
- 失败:失败的信息提示回显给前端,并给用户提示
但响应的同时,各个接口若返回的格式参次不一的话,前端会根据不同接口自定义其不同的回显,时间成本会显著提高,由此后端规范统一响应
的重要性由之体现而来,统一响应返回信息如下:
- 成功:状态码 + 数据
- 失败:状态码 + 错误信息提示
标准的RESTful API定义中,更推荐使用HTTP响应状态码为标准,但由于其信息提示不满足于更多场景的业务需求,所以一般采取自定义个性所需的状态码
二. 统一响应
2.1 字段
字段 | 解析 |
code | 自定义状态码 |
msg | 自定义响应信息 |
data | 自定义数据 |
2.2 错误码
📌GlobalErrorCOdeConstants
对
ErrorCode
封装,自定义错误码
+错误信息
,方便错误响应时调用
/**
* 错误码常量定义
*
* @author zhanghp
* @date 2022-07-22 14:37
*/
public interface GlobalErrorCodeConstants {
ErrorCode SUCCESS = new ErrorCode(0, "成功");
ErrorCode BAD_REQUEST = new ErrorCode(400, "请求参数不正确");
ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "请求过于频繁,请稍后再试");
}
📌ErrorCode
code
:错误码
msg
:错误信息
/**
* 错误码
*
* @author zhanghp
* @date 2022-07-22 14:37
*/
@Data
public class ErrorCode {
private final Integer code;
private final String msg;
public ErrorCode(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
2.3 统一响应类
⭐️字段
字段 | 解析 |
code | 自定义状态码 |
msg | 自定义响应信息 |
data | 自定义数据 |
⭐️代码
统一响应方法
中分为:成功响应
- 状态码200 + 固定成功信息提示(’success‘)
- 状态码200 + 固定成功信息提示(’success‘)+ 自定义数据
失败响应
- 状态码500 + 固定错误信息提示(‘fail’)的失败响应
- 状态码500 + 自定义错误信息的失败响应
- 状态码自定义 + 错误信息自定义的失败响应
- 自定义错误类封装的失败响应
/**
* 统一响应结果封装类
*
* @author zhanghp
* @date 2022-07-21 9:54
*/
@Data
@Accessors(chain = true)
@SuppressWarnings("all")
public class R<T> {
/**
* 状态码
*/
private Integer code;
/**
* 响应信息
*/
private String msg;
/**
* 数据
*/
private T data;
/**
* 状态码200 + 固定成功信息提示(’success‘)
*
* @return 实例R
*/
public static R success() {
return new R()
.setCode(HttpStatus.OK.value())
.setMsg("success");
}
/**
* 状态码200 + 固定成功信息提示(’success‘)+ 自定义数据
*
* @param data 数据
* @param <T> 回显数据泛型
* @return 实例R
*/
public static <T> R success(T data) {
return success().setData(data);
}
/**
* 状态码500 + 固定错误信息提示('fail')的失败响应
*
* @return 实例R
*/
public static R fail() {
return new R()
.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value())
.setMsg("fail");
}
/**
* 状态码500 + 自定义错误信息的失败响应
*
* @param msg 错误信息
* @return 实例R
*/
public static <T> R fail(String msg) {
return new R()
.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value())
.setMsg(msg);
}
/**
* 状态码自定义 + 错误信息自定义的失败响应
* {@link GlobalErrorCodeConstants}
*
* @param data 数据
* @param msg 错误信息
* @return 实例R
*/
public static R fail(Integer errorCode, String msg) {
return fail()
.setCode(errorCode)
.setMsg(msg);
}
/**
* 自定义错误类封装的失败响应
*
* @param error 自定义错误类
* @return 实例R
* @see ErrorCode
*/
public static R fail(ErrorCode error) {
return fail()
.setCode(error.getCode())
.setMsg(error.getMsg());
}
}
三. 调用测试
3.1 接口层代码
/**
* 统一响应实体类封装controller
*
* @author zhanghp
* @date 2022-07-21 10:03
*/
@RestController
@SuppressWarnings({"rawtypes"})
public class UnifiedResponseController {
/**
* 状态码200 + 固定成功信息提示(’success‘)
*
* @return R
*/
@GetMapping("/success")
public R successNoArgs(){
return success();
}
/**
* 状态码200 + 固定成功信息提示(’success‘)+ 自定义数据
*
* @return R
*/
@GetMapping(value = "/success2", produces = "application/json; charset=utf-8")
public R successWithArgs(){
return success("响应成功");
}
/**
* 状态码500 + 固定错误信息提示('fail')的失败响应
*
* @return R
*/
@GetMapping("/fail")
public R failNoArgs(){
return fail();
}
/**
* 状态码500 + 自定义错误信息的失败响应
*
* @return R
*/
@GetMapping(value = "/fail2", produces = "application/json; charset=utf-8")
public R<String> failWithArgs(){
return fail("响应失败");
}
/**
* 状态码500 + 自定义错误信息的失败响应
*
* @return R
*/
@GetMapping(value = "/fail3", produces = "application/json; charset=utf-8")
public R<String> failCustom(){
return fail("响应失败");
}
/**
* 自定义错误类封装的失败响应
*
* @return R
*/
@GetMapping(value = "/fail4", produces = "application/json; charset=utf-8")
public R<String> failCustom2(){
return fail(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
}
}
3.2 UT测试用例
采用Spring boot test的单元测试
mockMvc类用法
/**
* 统一响应UT
*
* https://www.iocoder.cn/Spring-Boot/SpringMVC/?yudao
*/
@SpringBootTest
@AutoConfigureMockMvc
class UnifiedResponseTests {
@Autowired
private static MockMvc mockMvc;
@BeforeAll
static void init(){
// 初始化mockMvc
mockMvc = MockMvcBuilders.standaloneSetup(new UnifiedResponseController()).build();
}
@Test
void successNoArgs() throws Exception {
// 请求
ResultActions perform = mockMvc.perform(MockMvcRequestBuilders.get("/success"));
// 响应
String contentAsString = perform.andReturn().getResponse().getContentAsString();
// 打印
System.out.println(contentAsString);
}
@Test
void successWithArgs() throws Exception {
// 请求
ResultActions perform = mockMvc.perform(MockMvcRequestBuilders.get("/success2"));
// 响应
String contentAsString = perform.andReturn().getResponse().getContentAsString();
// 打印
System.out.println(contentAsString);
}
@Test
void failNoArgs() throws Exception {
// 请求
ResultActions perform = mockMvc.perform(MockMvcRequestBuilders.get("/fail"));
// 响应
String contentAsString = perform.andReturn().getResponse().getContentAsString();
// 打印
System.out.println(contentAsString);
}
@Test
void failWithArgs() throws Exception {
// 请求
ResultActions perform = mockMvc.perform(MockMvcRequestBuilders.get("/fail2"));
// 响应
String contentAsString = perform.andReturn().getResponse().getContentAsString();
// 打印
System.out.println(contentAsString);
}
@Test
void failCustom() throws Exception {
// 请求
ResultActions perform = mockMvc.perform(MockMvcRequestBuilders.get("/fail3"));
// 响应
String contentAsString = perform.andReturn().getResponse().getContentAsString();
// 打印
System.out.println(contentAsString);
}
@Test
void failCustom2() throws Exception {
// 请求
ResultActions perform = mockMvc.perform(MockMvcRequestBuilders.get("/fail4"));
// 响应
String contentAsString = perform.andReturn().getResponse().getContentAsString();
// 打印
System.out.println(contentAsString);
}
}