Java全局异常处理

技术漫步 2023-11-17 AM 162℃ 0条

一、RestControllerAdvice注解与全局异常处理

这是一个与切面有关的注解,切面的注解肯定都有个作用范围,切面类的注解只能对其作用范围内的操作,实现切面操作。

RestControllerAdvice的作用范围是:单个项目中所有使用了RequestMapping(像PostMapping底层是使用了RequestMapping注解的也支持)的类都归他管,该注解还需要与其他注解配合使用才有意义,单独的使用该注解是没有任何意义的。

二、ExceptionHandler注解

RestControllerAdvice+ExceptionHandler这两个注解的组合,被用作项目的全局异常处理,一旦项目中发生了异常,就会进入使用了RestControllerAdvice注解类中使用了ExceptionHandler注解的方法,我们可以在这里处理全局异常,将异常信息输出到指定的位置。并对所有的错误信息进行归置。

三、用法

@RestControllerAdvice:处理全局范围内的异常

@RestControllerAdvice("com.example.demo"):指定了一个特定的包,表示该类只处理来自com.example.demo包下的控制器的异常

@RestControllerAdvice(basePackageClasses = UserController.class):指定了一个特定的类,表示该类只处理 UserController 类所在的包下的控制器的异常

@RestControllerAdvice(value = "com.example.demo"):用法同 @RestControllerAdvice("com.example.demo")

@RestControllerAdvice(annotations = Annotation.class):用于处理带有特定注解的控制器的异常。只有带有 Annotation 注解的控制器产生的异常会被这个类处理

四、示例代码

/**
 * 全局异常处理
 **/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler{

/**
 * <1> 处理 form data方式调用接口校验失败抛出的异常
 *
 * @param e
 * @return
 */
@ExceptionHandler(BindException.class)
public R bindExceptionHandler(BindException e) {
    List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
    Map<String, String> errorMap = new HashMap<>();
    fieldErrors.forEach((fieldError) -> errorMap.put(fieldError.getField(), fieldError.getDefaultMessage()));
    log.info("ExceptionControllerAdvice.exceptionHandler.bindExceptionHandler==================");
    return R.error(BusinessCodeEnum.VALID_EXCEPTION).setData(errorMap);
}

/**
 * <2>数据校验异常拦截
 *
 * @param e
 * @return
 */
@ExceptionHandler(MethodArgumentNotValidException.class)
public R exceptionHandle(MethodArgumentNotValidException e) {
    BindingResult bindingResult = e.getBindingResult();
    List<FieldError> fieldErrors = bindingResult.getFieldErrors();
    Map<String, String> errorMap = new HashMap<>();
    fieldErrors.forEach((fieldError) -> errorMap.put(fieldError.getField(), fieldError.getDefaultMessage()));
    log.info("ExceptionControllerAdvice.exceptionHandler.exceptionHandle==================");
    return R.error(BusinessCodeEnum.VALID_EXCEPTION).setData(errorMap);
}

/**
 * <3> 处理单个参数校验失败抛出的异常
 *
 * @param e
 * @return
 */
@ExceptionHandler(ConstraintViolationException.class)
public R constraintViolationExceptionHandler(ConstraintViolationException e) {
    Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
    Map<String, String> errorMap = new HashMap<>();
    for (ConstraintViolation<?> constraintViolation : constraintViolations) {
        PathImpl pathimpl = (PathImpl) constraintViolation.getPropertyPath();
        errorMap.put(pathimpl.getLeafNode().getName(), constraintViolation.getMessage());
    }
    log.info("ExceptionControllerAdvice.exceptionHandler.constraintViolationExceptionHandler==================");
    return R.error(BusinessCodeEnum.VALID_EXCEPTION).setData(errorMap);
}

/**
 * <4> 自定义异常处理
 *
 * @param businessException
 * @return
 */
@ExceptionHandler(value = BusinessException.class)
public R customHandler(BusinessException businessException) {
    log.info("ExceptionControllerAdvice.exceptionHandler.customHandler==================");
    return R.error(businessException.getCode(), businessException.getMsg());
}

/**
 * <5> 其他所有异常处理
 *
 * @param e
 * @return
 */
@ExceptionHandler(value = Exception.class)
public R exceptionHandler(Exception e) {
    log.info("ExceptionControllerAdvice.exceptionHandler.exceptionHandler==================");
    return R.error(BusinessCodeEnum.OPERATION_FAILED);
}

五、其他

除了全局异常处理的功能外,还可以实现全局数据绑定和全局数据预处理,分别是 @ModelAttribute 和 @InitBinder
这两个注解也是可以与RestControllerAdvice配合使用的

  • InitBinder注解:用于将前端传递的参数进行分别绑定
  • ModelAttribute注解:获取InitBinder绑定的参数,对他进行属性绑定
@Controller  
@RequestMapping("/test")  
public class TestController {  
// 绑定变量名字和属性,参数封装进类  
@InitBinder("user")  
public void initBinderUser(WebDataBinder binder) {  
    binder.setFieldDefaultPrefix("user.");  
}  
// 绑定变量名字和属性,参数封装进类  
@InitBinder("addr")  
public void initBinderAddr(WebDataBinder binder) {  
    binder.setFieldDefaultPrefix("addr.");  
}  
  
  
@RequestMapping("/test")  
@ResponseBody  
public Map<String,Object> test(HttpServletRequest request,
                               @ModelAttribute("user") User user,@ModelAttribute("addr") Addr addr){  
    Map<String,Object> map=new HashMap<String,Object>();  
    map.put("user", user);  
    map.put("addr", addr);  
    return map;  
} 
标签: 全局异常处理

非特殊说明,本博所有文章均为博主原创。

评论啦~