基于Springboot框架来处理。
能实现的有:自定义异常、自定义全局异常、自定义有条件的异常处理、自定义含业务参数的自定义异常
单个异常处理
基于框架,简单来说就是通过@ExceptionHandler注解就能实现需求,即自定义异常。注意,需要放在Controller类中(可以专门定义一个Controller类做自定义注解)。
//注解,参数是具体的异常类
@ExceptionHandler(MissingServletRequestParameterException.class)
//这里的参数,一般就是对应的异常类,还可以传递如HttpServletRequest来实现更加复杂的业务逻辑
//返回类也允许自己定义。也可以直接返回原来的异常。
public ResponseEntity<Map<String, Object>> handleMissingParams(MissingServletRequestParameterException ex,
HttpServletRequest request) {Map<String, Object> response = new HashMap<>();response.put("status", 400);response.put("message", "必需参数缺失: " + ex.getParameterName());return ResponseEntity.badRequest().body(response);
}
全局异常
定义一个@ControllerAdvice(@RestControllerAdvice)全局处理器类,在这个类里面进行大量的需要自己处理的异常封装,不需要处理的直接省略原样返回既可。
@ControllerAdvice
public class GlobalExceptionHandler {//允许自定义状态码,将一个方法或异常类标注一个应返回的HTTP状态码(code())和原因说明(reason()//@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(MissingServletRequestParameterException.class)public ErrorResult handleMissingParameter(MissingServletRequestParameterException e) {return new ErrorResult(400, "PARAM_MISSING", "缺少必要参数: " + e.getParameterName());}/*** 异常一*/public void uploadException(MaxUploadSizeExceededException e, HttpServletResponse resp) throws IOException{resp.setContentType("text/html;charset=utf-8");PrintWriter out = resp.getWriter();out.write("上传文件大小超出限制!");out.flush();out.close();}/*** 异常二*/@ExceptionHandler(MissingServletRequestParameterException.class)public ErrorResult handleMissingParameter(MissingServletRequestParameterException e) {return new ErrorResult(400, "PARAM_MISSING", "缺少必要参数: " + e.getParameterName());}/*** 异常三*/@ExceptionHandler(MissingServletRequestParameterException.class)public ErrorResult handleMissingParameter(MissingServletRequestParameterException e) {return new ErrorResult(400, "PARAM_MISSING", "缺少必要参数: " + e.getParameterName());}/*** 异常四*/@ExceptionHandler(MissingServletRequestParameterException.class)public ErrorResult handleMissingParameter(MissingServletRequestParameterException e) {return new ErrorResult(400, "PARAM_MISSING", "缺少必要参数: " + e.getParameterName());}
}
自定义特定条件异常处理
实现仅对特定URL进行处理,即只有某些url或者某种条件下的才进行处理,需要在自定义异常中做业务处理。
@ControllerAdvice
public class SelectiveExceptionHandler {private static final Set<String> TARGET_URLS = Set.of("/api/v1/validate", "/secure/check");@ExceptionHandler(MissingServletRequestParameterException.class)public ResponseEntity<?> handleMissingParam(MissingServletRequestParameterException ex, HttpServletRequest request) {// 仅处理指定URLif (TARGET_URLS.contains(request.getRequestURI())) {return ResponseEntity.badRequest().body(Map.of("error", "参数缺失", "param", ex.getParameterName()));}// 其他URL继续抛出原始异常throw ex;}
}
自定义业务参数全局实现类。
这个方法与上面的 自定义特定条件异常处理 可以混用,即先定义一个自定义异常,在自定义异常中封装所需要的数据,然后再全局异常中,处理自定义异常。
1.自定义异常
// 定义包含业务参数的异常类
public class BusinessException extends RuntimeException {private final String errorCode;private final Map<String, Object> businessData; // 业务参数容器public BusinessException(String code, String message, Map<String, Object> data) {super(message);this.errorCode = code;this.businessData = data;}// getters...
}
2.定义全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {//注意看这里的异常已经是自定义异常了,包括传参,这样就能在异常中通过这些业务数据进行逻辑处理@ExceptionHandler(BusinessException.class)@ResponseBodypublic ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex, HttpServletRequest request) {ErrorResponse response = new ErrorResponse(ex.getErrorCode(),ex.getMessage(),request.getRequestURI(),ex.getBusinessData() // 将业务参数封装到响应体);return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);}
}
3.业务实际使用
throw new BusinessException("VALID_001", "参数校验失败", Map.of("field", "age", "rejectedValue", "abc"));
throw new BusinessException("AUTH_003", "权限不足",Map.of("requiredRole", "ADMIN", "currentRole", "USER"));
注意的是,我们的异常处理可能很难包含到全部,所以我们只需要处理自己关注的,常规的一些已经被框架定义好了,如果当发现某些异常不好理解的时候,做一些封装定义既可。