服务端对外暴露的接口不可避免的会出现异常,无论是系统异常还是业务异常,出现异常后如何处理对用户提供友好的提示信息是我们所必须处理的。以下提供借助spring注解
@ControllerAdvice
实现对控制层、业务层异常的统一处理。
(1)在前后端分离的开发模式中,后端不再作视图跳转,仅用作为前端返回数据,我们多使用
@Controller + @ResponseBody
或直接使用@RestController
注解的方式实现将数据转换为json
格式返回,通常我们都会定义一个通用的返回类用于对返回数据的封装:
@Data
public class BaseResult {
/**
* 状态码
*/
private int code;
/**
* 返回数据
*/
private Object data;
/**
* 返回信息
*/
private String message;
public BaseResult() {
}
public BaseResult(Object data) {
this.data = data;
}
public BaseResult(int code, Object data) {
this.code = code;
this.data = data;
}
public BaseResult(int code, Object data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
public BaseResult success(){
this.code = HttpStatus.OK.value();
this.data = true;
this.message = "请求成功";
return this;
}
public BaseResult success(Object data){
this.code = HttpStatus.OK.value();
this.data = data;
this.message = "请求成功";
return this;
}
public BaseResult error(){
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.data = false;
this.message = "请求失败";
return this;
}
public BaseResult error(Object data,String message){
this.code = 500;
this.data = data;
this.message = message;
return this;
}
}
(2) 自定义业务异常类:
public class CustomUserException extends RuntimeException {
private Integer code;
public CustomUserException(UserResponseEnum userResponseEnum){
super(userResponseEnum.getDescription());
this.code = userResponseEnum.getCode();
}
public Integer getCode() {
return code;
}
}
---------------------------
在构造自定义业务异常对象时使用了 枚举 的方式,将常见的业务错误提示语对应的错误代码进行
映射,枚举类如下所示:
public enum UserResponseEnum {
USER_NOT_FOUND(50001,"用户不存在"),
USER_AUTHENTICATION_ERROR(50002,"用户密码不正确");
private Integer code;
private String description;
UserResponseEnum(Integer code, String description) {
this.code = code;
this.description = description;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
(3)通过
@ControllerAdvice
注解,实现统一异常捕获:
@RestController
@ControllerAdvice(basePackages = {"com.blade.system.controller"})
public class CustomExceptionAdvice {
private static final Logger logger = LoggerFactory.getLogger(CustomExceptionAdvice.class);
/**
* 处理与用户相关的业务异常
* @return
*/
@ExceptionHandler(CustomUserException.class)
public BaseResult UserExceptionHandler(HttpServletRequest request,CustomUserException e){
logger.error("用户信息异常:Host:{} invoke URL:{},错误信息:{}",request.getRemoteHost(),request.getRequestURL(),e.getMessage());
return new BaseResult(e.getCode(),false,e.getMessage());
}
}
(4)在业务代码中在需要抛出异常的地方抛出对应的异常即可:
/**
* 根据主键获取用户实体
* @param id
* @return
*/
public User selectByKey(String id) {
User user = userMapper.selectByPrimaryKey(id);
if (user == null) {
throw new CustomUserException(UserResponseEnum.USER_NOT_FOUND);
}
return user;
}
--------------------------------------
返回信息如下:
{
"code": 50001,
"data": false,
"message": "用户不存在"
}
前端即可根据返回信息对用户进行友好的提示。