前言
本篇主要要介绍的就是controller
层的处理,一个完整的后端请求由4部分组成:
-
接口地址
(也就是URL地址) -
请求方式
(一般就是get、set,当然还有put、delete) -
请求数据
(request,有head跟body) -
响应数据
(response)
本篇将解决以下3个问题:
-
当接收到请求时,如何优雅的校验参数
-
返回响应数据该如何统一的进行处理
-
接收到请求,处理业务逻辑时抛出了异常又该如何处理
一、Controller层参数接收(太基础了,可以跳过)
常见的请求就分为get
跟post
2种
@RestController
@RequestMapping("/product/product-info")
public class ProductInfoController {
@Autowired
ProductInfoService productInfoService;
@GetMapping("/findById")
public ProductInfoQueryVo findById(Integer id) {
...
}
@PostMapping("/page")
public IPage findPage(Page page, ProductInfoQueryVo vo) {
...
}
}
1、@RestController
:之前解释过,@RestController
= @Controller
+ ResponseBody
。加上这个注解,springboot就会吧这个类当成controller
进行处理,然后把所有返回的参数放到ResponseBody
中
推荐一个 Spring Boot 基础实战教程:
https://github.com/javastacks/spring-boot-best-practice
2、@RequestMapping
:请求的前缀,也就是所有该Controller
下的请求都需要加上/product/product-info
的前缀
3、@GetMapping("/findById")
:标志这是一个get
请求,并且需要通过/findById
地址才可以访问到
4、@PostMapping("/page")
:同理,表示是个post
请求
5、参数
:至于参数部分,只需要写上ProductInfoQueryVo
,前端过来的json
请求便会通过映射赋值到对应的对象中,例如请求这么写,productId
就会自动被映射到vo
对应的属性当中
size : 1
current : 1
productId : 1
productName : 泡脚
二、统一状态码
1. 返回格式
为了跟前端妹妹
打好关系,我们通常需要对后端返回的数据进行包装一下,增加一下状态码
,状态信息
,这样前端妹妹接收到数据就可以根据不同的状态码
,判断响应数据状态
,是否成功是否异常进行不同的显示。
当然这让你拥有了更多跟前端妹妹的交流机会,假设我们约定了1000
就是成功的意思
如果你不封装,那么返回的数据是这样子的
{
"productId": 1,
"productName": "泡脚",
"productPrice": 100.00,
"productDescription": "中药泡脚加按摩",
"productStatus": 0,
}
经过封装以后时这样子的
{
"code": 1000,
"msg": "请求成功",
"data": {
"productId": 1,
"productName": "泡脚",
"productPrice": 100.00,
"productDescription": "中药泡脚加按摩",
"productStatus": 0,
}
}
2. 封装ResultVo
这些状态码肯定都是要预先编好的,怎么编呢?写个常量1000
?还是直接写死1000
?要这么写就真的书白读的了,写状态码
当然是用枚举拉
1、首先先定义一个状态码
的接口,所有状态码
都需要实现它,有了标准才好做事
public interface StatusCode {
public int getCode();
public String getMsg();
}
2、然后去找前端妹妹,跟他约定好状态码(这可能是你们唯一的约定了)枚举类嘛,当然不能有setter
方法了,因此我们不能在用@Data
注解了,我们要用@Getter
@Getter
public enum ResultCode implements StatusCode{
SUCCESS(1000, "请求成功"),
FAILED(1001, "请求失败"),
VALIDATE_ERROR(1002, "参数校验失败"),
RESPONSE_PACK_ERROR(1003, "response返回包装失败");
private int code;
private String msg;
ResultCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
3、写好枚举类,就开始写ResultVo
包装类了,我们预设了几种默认的方法,比如成功的话就默认传入object
就可以了,我们自动包装成success
@Data
public class ResultVo {
// 状态码
private int code;
// 状态信息
private String msg;
// 返回对象
private Object data;
// 手动设置返回vo
public ResultVo(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
// 默认返回成功状态码,数据对象
public ResultVo(Object data) {
this.code = ResultCode.SUCCESS.getCode();
this.msg = ResultCode.SUCCESS.getMsg();
this.data = data;
}
// 返回指定状态码,数据对象
public ResultVo(StatusCode statusCode, Object data) {
this.code = statusCode.getCode();
this.msg = statusCode.getMsg();
this.data = data;
}
// 只返回状态码
public ResultVo(StatusCode statusCode) {
this.code = statusCode.getCode();
this.msg = statusCode.getMsg();
this.data = null;
}
}
4、使用,现在的返回肯定就不是return data;
这么简单了,而是需要new ResultVo(data);
@PostMapping("/findByVo")
public Resu