我们希望能在Postman中返回操作的异常或信息
在domain package中新建Result class
public class Result {
private Integer code;
private String msg;
private T data;//将data设定为泛型,用来存储返回的具体信息
public Integer getCode() {return code;}
public void setCode(Integer code) {this.code = code;}
public String getMsg() {return msg;}
public void setMsg(String msg) {this.msg = msg;}
public T getData() {return data;}
public void setData(T data) {this.data = data;}
}
用Result来固定返回的信息,就返回code,msg,data三个信息
在控制器添加对Result的使用
/**
* 添加一个女生
* @return
*/
@PostMapping(value = "/girls")
public Result girlAdd(@Valid Gril girl, BindingResult bindingResult){//Result存储信息数据
if(bindingResult.hasErrors()){
Result result = new Result();
result.setCode(1);//随便设定
result.setMsg(bindingResult.getFieldError().getDefaultMessage());
result.setData("出错了0");
return result;
}
girl.setCupSize(girl.getCupSzie());
girl.setAge(girl.getAge());
Result result = new Result();
result.setCode(0);
result.setMsg("成功了!");
result.setData(girlRepository.save(girl));
return result;
}
返回信息:
{
"code": 0,
"msg": "成功了!",
"data": {
"id": 11,
"age": 18,
"cupSzie": "B"
}
}
或者
{
"code": 1,
"msg": "未成年禁止入内",
"data": "出错了0"
}
整合一下重复代码:新建一个Utils Package,建一个 ResultUtil class
public class ResultUtil {
public static Result success(Object object){
Result result = new Result();
result.setCode(0);
result.setMsg("成功!");
result.setData(object);
return result;
}
public static Result success(){
return success(null);
}
public static Result error(Integer code,String msg){
Result result = new Result();
result.setCode(code);
result.setMsg(msg);
return result;
}
}
通过调用类来输出信息
/**
* 添加一个女生
* @return
*/
@PostMapping(value = "/girls")
public Result girlAdd(@Valid Gril girl, BindingResult bindingResult){
if(bindingResult.hasErrors()){
//调用 ResultUtil
return ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage());
}
girl.setCupSize(girl.getCupSzie());
girl.setAge(girl.getAge());
//调用 ResultUtil
return ResultUtil.success(girlRepository.save(girl));
}
我们通过这个信息返回,可以反馈给我们信息提示,比如根据提交的年龄反馈学籍
先建一个服务类
@Service
public class GirlService {
@Autowired
private GirlRepository girlRepository;//查询的接口
@Autowired
private GirlService girlService;//调用服务类
public void getAge(Integer id){
Gril gril = girlRepository.findById(id).get();
Integer age = gril.getAge();
if(age<10){
//返回“你可能上小学”
}else if (age>10&&age<16){
//返回“你可能在上初中”
}
}
}
通过服务类来控制逻辑的判断
再在控制器新建一个判断年龄的方法
@GetMapping(value = "/age")
public void getAge(@PathVariable("id") Integer id){
girlService.getAge(id);
}
但是这样判断的方式太低效,我们通过抛异常的方式来解决
public void getAge(Integer id) throws Exception{//抛出异常
Gril gril = girlRepository.findById(id).get();
Integer age = gril.getAge();
if(age<10){
//返回“你孩子啊上小学”
throw new Exception("你就是个小屁孩");
}else if (age>10&&age<16){
//返回“你可能在上初中”
throw new Exception("你就是个小姑娘");
}
}
在控制器中继续抛出异常
@GetMapping(value = "/age")
public void getAge(@PathVariable("id") Integer id) throws Exception{
girlService.getAge(id);
}
就可以收集到如下的异常
{
"timestamp": "2018-06-23T06:56:59.466+0000",
"status": 500,
"error": "Internal Server Error",
"message": "你就是个小屁孩",
"path": "/girls/getAge/1"
}
那我们要拦截异常信息并且对信息进行封装,建 handle 包,建 ExceptionHandle 类
@ControllerAdvice
public class ExceptionHandle {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handle(Exception e){
return ResultUtil.error(100,e.getMessage());
}
}
这样就可以实现只输出 Message 但是我们要想输出多个值怎么办? Exception 只能输出 e呀?我们自己写一个抛出类
Package excption -> Class GrilExcption
public class GirlException extends RuntimeException {
private Integer code;
public GirlException(Integer code,String message) {
super(message.toString());
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
GrilExcption类可以传进一个code参数(用来简易标记异常)和一个message参数(用来显示异常内容)我们在拦截异常信息的class ExceptionHandle中使用它
@ExceptionHandler(value = Exception.class)//拦截异常信息
@ResponseBody
public Result handle(Exception e){
if(e instanceof GirlException){//判断异常是否由自己定义
GirlException girlException = (GirlException)e;//转换异常格式
return ResultUtil.error(girlException.getCode(),girlException.getMessage());//完成信息的发送
}else {
return ResultUtil.error(-1,"未知错误");
}
}
那我们打出未知错误怎么知道出什么错了?拿就来做一个日志吧
@ControllerAdvice
public class ExceptionHandle {
private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
@ExceptionHandler(value = Exception.class)//拦截异常信息
@ResponseBody
public Result handle(Exception e){
if(e instanceof GirlException){//判断异常是否由自己定义
GirlException girlException = (GirlException)e;//转换异常格式
return ResultUtil.error(girlException.getCode(),girlException.getMessage());//完成信息的发送
}else {
logger.error("【系统异常】{}",e);//打印异常信息
return ResultUtil.error(-1,"未知错误");
}
}
}
其实我们可以将GrilExcption类中的参数统一起来,利用枚举类型
Package enums -> Class ResultEnum
public enum ResultEnum {
//建立一些枚举,替代参数
UNKNOWN_ERROR(-1,"未知错误"),
SUCCESS(0,"成功"),
PRIMARY_SCHOOL(100,"你可能还在小学"),
MIODLE_SCHOOL(101,"你可能还在上初中");
private Integer code;
private String msg;
ResultEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {return code;}
public String getMsg() {return msg;}
}
然后我们就可以修改getAge方法的参数
public void getAge(Integer id) throws Exception{
Gril girl = grilRepository.findById(id).get();
Integer age = girl.getAge();
if (age < 10) {
//返回"你还在上小学吧" code=100
throw new GirlException(ResultEnum.PRIMARY_SCHOOL);//替换成了枚举类型
}else if (age > 10 && age < 16) {
//返回"你可能在上初中" code=101
throw new GirlException(ResultEnum.MIODLE_SCHOOL);
}
}
别忘了我们把枚举值转给GrilExcption类后要修改实参
public GirlException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
}
然后负责封装异常信息的ExceptionHandle类就可以获取GrilExcption的信息输出啦