您的位置:

如何正确利用ExceptionHandler注解进行错误处理

异常处理是很常见的一个程序设计需求,无论是在处理本地还是远程的异常都需要谨慎处理。在 Java 编程语言中,异常是非常重要的一部分,合理的使用异常处理能够提高代码的可读性和可维护性。使用 Java 异常机制可以让代码更加优雅,在遇到异常的情况下使程序更加健壮。而 ExceptionHandler 注解则是用于在 Spring 应用程序中处理异常的一种方式。接下来,本文将通过多个方面来讲解如何正确利用 ExceptionHandler 注解来进行错误处理。

一、 合理地抛出异常

合理地抛出异常是一个程序员应该掌握的基本技能。在 Java 编程语言中,我们通常是使用 try-catch 块来处理异常。在编写代码时,应该遵循这样的原则:只有应该被捕获的异常才会被捕获。此外,异常应尽可能地清晰明了地描述问题。在抛出异常时,应该将异常对象和相关信息一同传递。 以下是一个示例程序代码,用来展示合理地抛出异常所涉及的要点。
public class Demo {
    public void save(String name, String password) throws UserException {
        // 名称为空 或 密码为空时,应该抛出异常
        if (StringUtils.isBlank(name) || StringUtils.isBlank(password)) {
            throw new UserException("用户名或密码不能为空");
        }
        // 其他操作
    }
}
在代码中,StringUtils.isBlank() 方法用来判断传入的字符串是否为空,如果为空,则该异常就会被抛出。如果有多个异常需要处理,可以把异常信息打包成不同的异常并在 API 中声明。

二、使用@ControllerAdvice和@ExceptionHandler注解

Spring 框架提供了一个更好的方式,使用 @ControllerAdvice 和 @ExceptionHandler 注解。使用这些注解,可以将异常处理结构和原代码分离,同时保留异常处理器的弹性。具体来说, @ControllerAdvice 是一个带有 @ExceptionHandler 注解的 Spring Bean,它可以处理基于控制器的异常。 以下是一个示例代码,用来展示如何正确使用 @ControllerAdvice 和 @ExceptionHandler 注解。
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(HttpServletRequest request, Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("exception", e);
        mv.addObject("url", request.getRequestURL());
        mv.setViewName("error/error");
        return mv;
    }
}
在使用过程中,我们需要在定义中指定我们要处理的异常。这里我们处理 Exception 类的异常。在方法中,我们使用 ModelAndView 对象来封装异常信息,并指定要返回的页面。在这个例子中,我们将异常信息和请求 URL 一起交给 view page 渲染。

三、处理特定的异常

Spring 还允许我们在 @ExceptionHandler 注解中指定异常类型,以处理特定的异常。如果你不指定异常类型,则默认捕获所有异常。 以下是一个实例代码,用来展示如何处理特定的异常。
@ControllerAdvice
public class CustomExceptionHandler {
    @ExceptionHandler(DataAccessException.class)
    public ModelAndView handleDataAccessException(HttpServletRequest request, Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("exception", e);
        mv.addObject("url", request.getRequestURL());
        mv.addObject("message", "数据访问异常");
        mv.setViewName("error/error");
        return mv;
    }
}
在这个实例代码中,我们定义了一个专门的异常处理器来处理 DataAccessException 异常。在方法中,除了设置 View 和封装原始异常信息外,我们还增加了一个 message 参数,这个参数可以包含关于异常类型的有用信息,以便后续调试。通过这种方式,我们可以更加细致地处理特定的异常情况。

四、降低日志级别

在异常处理时,错误信息在控制台或日志中的重要性可能会因为过于频繁而被低估。异常日志需要很好地处理,其中之一便是通过适当的日志级别来降低日志信息的量。 以下是一段示例代码,用来降低日志级别。
@ControllerAdvice
public class CustomExceptionHandler {
    private static final logger LOGGER = LoggerFactory.getLogger(String.class.getName());
    @ExceptionHandler(DataAccessException.class)
    public ModelAndView handleDataAccessException(HttpServletRequest request, Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("exception", e);
        mv.addObject("url", request.getRequestURL());
        mv.addObject("message", "数据访问异常");
        mv.setViewName("error/error");
        LOGGER.info("error", e); // 使用 info 级别
        return mv;
    }
}
在这个代码中,我们降低了日志级别,使用 INFO 级别让错误信息并不会在控制台或日志中被打印过多次数,避免过度引起注意,同时保留错误信息的必要性。

总结

本文通过多个方面介绍了如何正确利用 ExceptionHandler 注解进行错误处理,包括合理地抛出异常、使用 @ControllerAdvice 和 @ExceptionHandler 注解、处理特定的异常、以及降低日志级别。这些技术将会使以后的异常处理更加优雅,也更有可读性和可维护性。 参考链接:https://www.baeldung.com/exception-handling-for-rest-with-spring