项目实践笔记(一)
统一结果封装
在前后端分离项目中,为了使前后端的数据传输有一个统一的格式标准,我们一般会进行统一结果封装,约定结果返回的数据是正常的或者遇到异常了。
这里我们用到了一个Result的类,这个用于我们的异步统一返回的结果封装。一般来说,结果里面有几个要素必要的
- 是否成功,可用code表示(如200表示成功,400表示异常)\
- 结果消息,可用msg表示
- 结果数据,可用data表示
下面是一个实际封装案例: com.example.common.lang.Result,包含最基本的4种返回结果,全都是静态方法:
@Data
public class Result implements Serializable {
private int code; // 200是正常,非200表示异常
private String msg;
private Object data;
public static Result succ(Object data) {
return succ(200, "操作成功", data);
}
public static Result succ(int code, String msg, Object data) {
Result r = new Result();
r.setCode(code);
r.setMsg(msg);
r.setData(data);
return r;
}
public static Result fail(String msg) {
return fail(400, msg, null);
}
public static Result fail(int code, String msg, Object data) {
Result r = new Result();
r.setCode(code);
r.setMsg(msg);
r.setData(data);
return r;
}
}
全局异常处理
全局异常处理的核心就是,使用AOP定义一个全局的异常处理类:
- 在 SpringMVC / SpringBoot 项目中, 只需要使用
AOP编写一个全局的异常处理切面类, 用它来统一处理所有的异常.在类上添加@ControllerAdvice+@ExceptionHandler注解, 同时需要使用 @ResponseBody 注解表示返回值为 JSON 字符串.
如果做的规范的话,需要以下几个部分:
① 统一的返回结果
就像第一部分那样,所有的方法都会返回一个Result的结果封装实体类。
② 全局异常错误
还编写一个 CodeMsg 全局异常错误码实体类. 将错误码集中管理, 然后通过 Result.error(CodeMsg codeMsg) 这种方式调用, 将业务错误码直接传回前端. 并且错误码可以随意扩展.
③ 自定义异常类
CaptchaException 是一个自定义的验证码异常类. 在业务层对异常进行实例化并抛出, 让切面 GlobalExceptionHandler 捕获处理 CaptchaException
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CaptchaException extends RuntimeException { //记得继承一个异常类型
public CaptchaException(String msg){
super(msg);
}
public CaptchaException(CodeMsg codeMsg){
super(codeMsg.getMsg());
}
}
④全局异常处理类
编写 GlobalExceptionHandler 全局异常处理类. 对业务层传输来的异常做判断, 通过 Result.error(ex.getCodeMsg()) 对不同类型的异常统一返回.
@ControllerAdvice注解, 在类上使用, 表示该类为全局异常处理类, 当 Controller 层抛出异常时调用.@ExceptionHandler注解, 在方法上使用, 表示该方法在发生何种类型异常时会被调用. 由该注解的 value 属性决定.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.FORBIDDEN)
@ExceptionHandler(value = AccessDeniedException.class)
public Result handler(AccessDeniedException e) {
log.info("security权限不足:----------------{}", e.getMessage());
return Result.fail(CodeMsg.NO_PERMISSION);
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = CaptchaException.class)
public Result handler(MethodArgumentNotValidException e) {
log.info("验证码错误异常:----------------{}", e.getMessage());
return Result.fail(CodeMsg.CAPTCHA_ERROR);
}
//其他异常处理
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = RuntimeException.class)
public Result handler(RuntimeException e) {
log.error("运行时异常:----------------{}", e);
return Result.fail(e.getMessage());
}
}
⑤ 在service层或者controller层抛出异常
@GetMapping("/captcha")
public boolean verifyCaptcha(String captcha) {
//验证码为空就抛出验证码异常!
if(user.getName()==null){
throw new CaptchaException(CodeMsg.CAPTCHA_ERROR);
}
return true;
}
参考
全局异常处理部分可以去看“昨天的风”大佬的文章:juejin.cn/post/713416…