前言
在开发 Web 应用程序时,异常处理是一个至关重要的部分。Spring Boot 提供了一套强大的异常处理机制,使得开发者能够轻松地处理和响应各种异常情况。本文将深入探讨 Spring Boot 中的异常处理机制,包括默认的错误处理规则、定制错误处理逻辑以及异常处理的自动配置原理。
一、默认错误处理规则
在默认情况下,Spring Boot 提供了 /error
路径来处理所有错误的映射。当应用程序发生异常时,Spring Boot 会自动将请求路由到这个默认的错误处理路径。
对于机器客户端(如 API 调用),Spring Boot 会生成一个 JSON 响应,其中包含错误的状态码(HTTP 状态)和异常消息的详细信息。以下是一个示例 JSON 响应:
{
"timestamp": "2024-07-19T08:22:25.669+00:00",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/asadada"
}
对于浏览器客户端,Spring Boot 会响应一个“whitelabel”错误视图,以 HTML 格式呈现相同的数据。这个默认的错误页面虽然简单,但能提供基本的错误信息。
二、定制错误处理逻辑
1. 自定义错误页
我们可以创建自定义的错误页面来替换默认的“whitelabel”错误视图。例如,创建 error/404.html
和 error/5xx.html
文件,Spring Boot 会根据不同的 HTTP 状态码自动选择对应的错误页面进行渲染。
2. 使用 @ControllerAdvice
和 @ExceptionHandler
通过实现 ErrorController
并注册该类型的 Bean 定义,或者添加 ErrorAttributes
类型的组件,我们可以完全替换默认的错误处理行为。更常见和灵活的方式是使用 @ControllerAdvice
和 @ExceptionHandler
注解。
以下是一个示例代码:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
// 可以在这里记录异常日志
String errorMessage = "An unexpected error occurred: " + ex.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<Object> handleNotFoundException(NotFoundException ex, WebRequest request) {
String errorMessage = "Resource not found: " + ex.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.NOT_FOUND);
}
}
在上述代码中,@ControllerAdvice
注解表示这是一个全局的异常处理器。@ExceptionHandler
注解用于指定处理特定类型异常的方法。当发生 Exception
类型的异常时,handleAllExceptions
方法会被调用;当发生 NotFoundException
类型的异常时,handleNotFoundException
方法会被调用。
3. 实现 HandlerExceptionResolver
我们还可以通过实现 HandlerExceptionResolver
接口来自定义异常处理逻辑。这个接口定义了一个 resolveException
方法,我们可以在这个方法中处理异常并返回一个 ModelAndView
对象。
以下是一个简单的示例:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
// 处理异常逻辑
ModelAndView modelAndView = new ModelAndView("error/500");
modelAndView.addObject("errorMessage", ex.getMessage());
return modelAndView;
}
}
三、异常处理自动配置原理
Spring Boot 通过 ErrorMvcAutoConfiguration
类自动配置异常处理规则。在这个配置类中,定义了多个组件:
DefaultErrorAttributes
:实现了ErrorAttributes
和HandlerExceptionResolver
接口,用于收集和提供错误属性信息。BasicErrorController
:处理/error
路径的请求,根据请求的类型(HTML 或 JSON)返回相应的错误响应。BeanNameViewResolver
:视图解析器,按照返回的视图名作为组件的 id 去容器中找视图对象。DefaultErrorViewResolver
:如果发生错误,会以 HTTP 的状态码作为视图页地址(viewName),找到真正的页面。
以下是 ErrorMvcAutoConfiguration
类中部分组件的定义示例:
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)
@ConditionalOnClass(EmbeddedWebApplication.class)
public class ErrorMvcAutoConfiguration {
// 定义 DefaultErrorAttributes
@Bean
@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
public DefaultErrorAttributes errorAttributes() {
return new DefaultErrorAttributes();
}
// 定义 BasicErrorController
@Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes,
ObjectProvider<ErrorViewResolver> errorViewResolvers) {
return new BasicErrorController(errorAttributes, errorViewResolvers.orderedStream().collect(Collectors.toList()));
}
// 其他组件定义...
}
四、异常处理步骤流程
- 执行目标方法:当目标方法运行期间发生任何异常时,会被
catch
,并且标志当前请求结束,使用dispatchException
进入视图解析流程(页面渲染?)。 - 调用
processDispatchResult
方法:该方法处理派发结果,包括处理异常。 - 处理
HandlerException
:遍历所有的handlerExceptionResolvers
,看谁能处理当前异常。
系统默认的异常解析器包括 DefaultErrorAttributes
、HandlerExceptionResolverComposite
等。DefaultErrorAttributes
先来处理异常,把异常信息保存到 request
域,并且返回 null
。如果没有任何人能处理异常,异常会被抛出,最终由底层的 BasicErrorController
处理,解析错误视图。
总结
Spring Boot 的异常处理机制提供了灵活且强大的方式来处理应用程序中的各种异常情况。通过默认的错误处理规则、定制错误处理逻辑以及理解异常处理的自动配置原理,我们可以更好地构建健壮的 Web 应用程序。在实际开发中,根据具体的需求选择合适的异常处理方式,能够提高应用程序的稳定性和用户体验。