项目实践笔记(一)

136 阅读3分钟

项目实践笔记(一)

统一结果封装

在前后端分离项目中,为了使前后端的数据传输有一个统一的格式标准,我们一般会进行统一结果封装,约定结果返回的数据是正常的或者遇到异常了。

这里我们用到了一个Result的类,这个用于我们的异步统一返回的结果封装。一般来说,结果里面有几个要素必要的

  1. 是否成功,可用code表示(如200表示成功,400表示异常)\
  2. 结果消息,可用msg表示
  3. 结果数据,可用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…