0%

初探返回类

初探返回类

为什么要对SpringBoot返回统一的标准格式

默认情况下,SpringBoot的返回格式常见的有三种:

  • 返回String
1
2
3
4
@GetMapping("/hello")
public String getStr(){
return "hello,javadaily";
}

此时调用接口的返回值:

1
hello,javadaily
  • 返回自定义对象
1
2
3
4
5
@GetMapping("/aniaml")
public Aniaml getAniaml(){
Aniaml aniaml = new Aniaml(1,"pig");
return aniaml;
}

此时调用接口的返回值:

1
2
3
4
{
"id": 1,
"name": "pig"
}
  • 接口异常
1
2
3
4
5
@GetMapping("/error")
public int error(){
int i = 9/0;
return i;
}

此时调用接口的返回值:

1
2
3
4
5
6
{
"timestamp": "2021-07-08T08:05:15.423+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/wrong"
}

基于上述情况,如果和前端开发人员联调接口,前端人员就会一脸懵逼;由于我们没有给他统一的格式,所以无法处理这些返回值

或者,不同的人对结果进行封装,小明用Result对象,小张用Response对象,这样也是会抓狂的 ╭(°A°`)╮

所以项目需要一个统一返回格式标准,一般公司开发都或有统一的格式要求

定义返回标准格式

一个标准的返回格式包括三个部分:

  1. status 状态值:由后端统一定义各种返回结果的状态码
  2. message 描述:本次接口调用的结果描述
  3. data 数据:本次返回的数据
1
2
3
4
5
{
"status":"100",
"message":"操作成功",
"data":"hello,javadaily"
}

也可以按照需要添加需要的信息

一种方式是可以直接在controller中返回成功的信息,但比较蠢,还会重复很多相同的动作,所以我们用一种更加便捷的方式来调用它

创建一个枚举类 BackEnum 来存放所有的返回值结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/** 枚举类 */
public enum BackEnum {
/** 请求数据成功,无异常情况 */
REQUEST_SUCCESS(200,"success"),

/** 服务器异常 */
UNKNOWN_ERROR(500,"未知错误"),

/** 无法获得用户session信息,或用户session信息不存在 */
UNAUTHORIZED(401,"请先登陆"),

/** 前端数据参数错误 */
PARAM_ERROR(400,"参数错误"),

/** 数据不符合要求 */
DATA_ERROR(400,"数据错误"),

/** 请求方式错误,get/post等 */
REQUEST_METHOD_ERROR(405,"请求方式错误"),

/** 密码错误 */
PWD_ERROR(2,"密码错误"),

/** 用户名不存在 */
NO_USER(3,"用户不存在"),

/** 账号长度过短,一般用于注册 */
ACCOUNT_LESS(4,"账号小于6位"),

/** 密码长度过短,一般用于注册 */
PASSWORD_LESS(5,"密码过短"),

/** 数据库已存在该数据 */
REPETITION(7, "数据重复添加"),
;
//注意语句间“逗号”隔开,语句最后“分号”结束

private Integer code;
private String message;

//枚举的构造函数是缺省的
BackEnum(Integer code, String message){
this.code = code;
this.message = message;
}

public int getCode() { return code; }

public String getMessage() { return message; }

//不用生成 set 方法,因为ORDER_CREATE_FAIL已经吧code和message赋值了
}

创建返回类 BackMessage 执行刚才的枚举类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import com.example.first_demo3.back.BackEnum;

public class BackMessage {
//标识返回状态
private Integer code;
//返回成功或失败的一个消息
private String message;
//返回的数据类型,Object 在开发中返回的数据类型不确定
//后续可以用泛型来解决
private Object data;


//如何为属性赋值:一个构造函数,set方法
//构造函数
public BackMessage(BackEnum backEnum){
this.code=backEnum.getCode();
this.message=backEnum.getMessage();
}

public BackMessage(BackEnum backEnum, Object t){
this.code=backEnum.getCode();
this.message=backEnum.getMessage();
this.data=t;
}

public BackMessage(Integer code,String message){
this.code = code;
this.message = message;
}
//重要的是上面3个构造函数,可以重载,通过参数来确定调用哪个
public Integer getCode() { return code; }

public void setCode(Integer code) { this.code = code;}

public String getMessage() {return message; }

public void setMessage(String message) {
this.message = message;
}

public Object getData() { return data; }

public void setData(Object data) { this.data = data; }
}
  • 这里返回中的data数据我使用的是 Object 类型,后续可以使用泛型来定义

测试测试!!! (ง •̀_•́)ง

数据库信息:表名为check

image-20210805181202470

实体类就不贴出来了,就这些信息

dao层的CheckMapper

1
2
3
4
5
@Mapper
public interface CheckMapper {
String get(String number);
void updateCheck(Check check);
}

CheckMapper.xml

1
2
3
4
5
6
7
8
9
10
11
<select id="get" resultType="java.lang.String">
SELECT n
FROM `check`
WHERE picture = #{picture}
</select>

<update id="updateCheck" parameterType="com.example.first_demo3.entity.Check">
update `check`
set n = #{n,jdbcType=VARCHAR}
where picture = #{picture}
</update>

重头重头!!!

service层CheckService

1
2
3
4
public interface CheckService {
BackMessage get(String number);
BackMessage updateCheck(Check check);
}

CheckServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Service
public class CheckServiceImpl implements CheckService {
@Autowired
CheckMapper checkMapper;

@Override
public BackMessage get(String number) {
String p = checkMapper.get(number);
return new BackMessage
(BackEnum.REQUEST_SUCCESS,p);
}

@Override
public BackMessage updateCheck(Check check) {
checkMapper.updateCheck(check);
return new BackMessage
(BackEnum.REQUEST_SUCCESS,"修改成功");
}
}

controller层CheckController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@RequestMapping("/check")
public class CheckController {
@Autowired
CheckService checkService;

//返回
@PostMapping("/get/{picture}")
public BackMessage get(@PathVariable String picture){
return checkService.get(picture);
}

//修改
@PostMapping("/update")
public void updateCheck(@RequestBody Check check){
checkService.updateCheck(check);
}
}

postman测试

获取值接口:

1
localhost:8081/check/get/1

返回:

1
2
3
4
5
{
"code": 200,
"message": "success",
"data": "111"
}

修改接口:

1
localhost:8081/update

输入:

1
2
3
4
{
"picture":"1",
"n":"0"
}

返回:

1
2
3
4
5
{
"code": 200,
"message": "success",
"data": "修改成功"
}

到此返回类成功写成,其余返回值大同小异

返回类的具体内容还可参照:

SpringBoot 如何统一后端返回格式?老鸟们都是这样玩的! - 知乎 (zhihu.com)

1
2
3
4
5
6
7
8
/*
** The author disclaims copyright to this source code.
** In place of a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
*/