1、定义返回结构
/**
* 返回结果实体类
*/
@Getter
public class R implements Serializable {
private int code;
private String message;
private Object data;
private R setResult(int code, String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
return this;
}
public static final int SUCCESS_CODE = ResponseCode.SUCCESS.getCode();
public static final String SUCCESS_MESSAGE = ResponseCode.SUCCESS.getMessage();
public static final int ERROR_CODE = ResponseCode.ERROR.getCode();
public static final String ERROR_MESSAGE = ResponseCode.ERROR.getMessage();
public R result(int code, String message, Object data) {
return setResult(code, message, data);
}
public static R ok() {
return new R().result(SUCCESS_CODE, SUCCESS_MESSAGE, new JSONObject());
}
public static R ok(Object data) {
return new R().result(SUCCESS_CODE, SUCCESS_MESSAGE, data);
}
public static R okList(Object data) {
JSONObject result = new JSONObject();
result.put("list", data);
return new R().result(SUCCESS_CODE, SUCCESS_MESSAGE, result);
}
public static R error() {
return new R().result(ERROR_CODE, ERROR_MESSAGE, new JSONObject());
}
public static R error(ResponseCode resultEnum) {
return new R().result(resultEnum.getCode(), resultEnum.getMessage(), new JSONObject());
}
public static R error(String message, Object data) {
return new R().result(ERROR_CODE, message, data);
}
public static R error(int code, String message, Object data) {
return new R().result(code, message, data);
}
public static R error(int code, String message) {
return new R().result(code, message, new JSONObject());
}
public static R error(String message) {
return new R().result(ResponseCode.ERROR.getCode(), message, new JSONObject());
}
}
2、定义响应结果枚举类
/**
* @Author: zhang
* @Date: 2019/8/2 10:33
* @Description: 响应结果枚举类
*/
public enum ResponseCode {
SUCCESS(0, "success"),
ERROR(500, "服务出错,请联系管理员"),
USER_NOT_EXIST(101, "该用户不存在!"),
USER_DISABLE(102, "该用户已停用!"),
TOKEN_AUTHENTICATION_FAILED(201, "Token认证失败!"),
TOKEN_EMPTY(202, "Token为空!"),
MISS_HEADER(400, "请求header出错:"),
NO_PERMISSION(401, "您没有权限访问!"),
PARAMETER_ERROR(403, "参数异常:"),
NOT_FOUND(404, "路径出错:"),
METHOD_NOT_SUPPORTED(405, "请求方法不支持:");
private int code;
private String message;
ResponseCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
3、自定义异常类
/**
* 服务异常类
*
*/
@Getter
public class ServiceException extends RuntimeException {
private int code;
private String message;
private Object data;
public ServiceException(Object data, String message) {
this.code = 500;
this.message = message;
this.data = data;
}
public ServiceException(Object data, String message, int code) {
this.code = code;
this.message = message;
this.data = data;
}
public ServiceException(String message) {
this.code = 500;
this.message = message;
}
public ServiceException(String message, int code) {
this.code = code;
this.message = message;
}
public ServiceException(ResponseCode response) {
this.code = response.getCode();
this.message = response.getMessage();
}
}
4、全局异常捕获
/**
* @Author: zhang
* @Date: 2019/3/8 18:22
* @Description:
* 当我们写的接口拥有@RequiresRoles, @RequiresPermissions注解时,
* 如果请求没有带有 token 或者带了 token 但权限认证不通过,
* 则会报 UnauthenticatedException 异常,
* ExceptionController 类对这些异常进行了集中处理
*/
@Slf4j
@RestControllerAdvice
public class ExceptionsHandler {
/**
* 捕捉shiro的异常
*
* @return
*/
@ExceptionHandler(ShiroException.class)
public R handle401() {
return R.error(ResponseCode.NO_PERMISSION.getCode(),
ResponseCode.NO_PERMISSION.getMessage());
}
/**
* header错误
*
* @param ex
* @return
*/
@ExceptionHandler(MissingRequestHeaderException.class)
public R noHeaher(Throwable ex) {
return R.error(ResponseCode.MISS_HEADER.getCode(),
ResponseCode.MISS_HEADER.getMessage() + ex.getMessage());
}
/**
* 请求参数异常
*/
@ExceptionHandler({HttpMessageNotReadableException.class,
MissingServletRequestParameterException.class,
MissingServletRequestPartException.class, BindException.class})
public R parameterException(Throwable ex) {
return R.error(ResponseCode.PARAMETER_ERROR.getCode(),
ResponseCode.PARAMETER_ERROR.getMessage() + ex.getMessage());
}
/**
* 请求路径无法找到异常
*
* @return
*/
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoHandlerFoundException.class)
public R notFoundException(Throwable ex) {
return R.error(ResponseCode.NOT_FOUND.getCode(),
ResponseCode.NOT_FOUND.getMessage() + ex.getMessage());
}
/**
* 请求方法不支持异常
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public R httpRequestMethodNotSupportedException(Throwable ex) {
return R.error(ResponseCode.METHOD_NOT_SUPPORTED.getCode(),
ResponseCode.METHOD_NOT_SUPPORTED.getMessage() + ex.getMessage());
}
/**
* 方法参数校验
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
return R.error(ResponseCode.PARAMETER_ERROR.getCode(),
e.getBindingResult().getFieldError().getDefaultMessage());
}
/**
* 捕捉其他所有异常
*
* @param request
* @return
*/
@ExceptionHandler(Exception.class)
public R globalException(HttpServletRequest request, Throwable ex) {
log.error("系统异常:", ex);
System.out.println("系统异常 = " + ex);
return R.error(getStatus(request).value(), ex.getMessage());
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
/**
* 自定义服务异常
*/
@ExceptionHandler(ServiceException.class)
public R serviceException(ServiceException e) {
log.error("发生业务异常!原因是:{}",e);
return R.error(e.getCode(), e.getMessage(), e.getData());
}
}
5、测试异常
@GetMapping("/test/{num}")
public R test(@PathVariable int num) {
if (num == 10){
throw new ServiceException(ResponseCode.ERROR);
}
int result = 10 / num;
return R.ok(result);
}
传入2,正常返回 `{"code":0,"message":"success","data":5}`
传入0,异常拦截,返回 `{"code":500,"message":"/ by zero","data":{}}`
传入10,抛出自定义异常,返回 `{"code":500,"message":"服务出错,请联系管理员","data":null}`
参考
SpringBoot优雅的全局异常处理
Spring Boot @RestControllerAdvice 统一异常处理
本文链接:
https://jianz.xyz/index.php/archives/82/