在开发 SpringBoot Web 应用的过程中,异常处理就像给程序穿了一件盔甲,能让它在面对各种“意外”时稳如泰山。如果没有良好的异常处理机制,你的应用可能会像一个没有刹车的车,下坡的时候就只能听天由命了。本篇文章将带你轻松掌握 SpringBoot 全局异常处理的三种方式,助你从容应对开发中的各种“异常风暴”。
什么是全局异常处理?
简单来说,全局异常处理就是在应用发生错误时,统一处理这些错误,而不需要在每一个地方都写重复的代码去捕获和处理异常。就像一个万能的“保安”,只要程序“闯祸”了,它就能快速出手帮忙解决问题。
SpringBoot 提供了三种常用的全局异常处理方式:
使用 @ControllerAdvice
注解。使用 @ExceptionHandler
注解。实现 HandlerExceptionResolver
接口。
下面我们逐一来看这三种方式,并配上详细的代码示例和解释。
使用@ControllerAdvice
注解
@ControllerAdvice
是一个 Spring 提供的注解,用来定义全局异常处理器。它的作用范围是所有的控制器,一次定义,处处生效。就像一个全局的“急救中心”,任何地方出问题,它都能接到报警。
示例代码
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
public class GlobalExceptionHandler {
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Oops! Something went wrong: " + e.getMessage());
}
}
代码解析
@ControllerAdvice
:定义了一个全局异常处理类,所有控制器中的异常都会由它处理。@ExceptionHandler(Exception.class)
:指定要处理的异常类型为Exception
,也就是所有未被捕获的通用异常。返回值:通过 ResponseEntity
返回自定义的 HTTP 状态码(500)和错误信息。
实际效果
如果你的应用中某个地方抛出了一个 Exception
(如数据库连接失败),用户会收到一个 500 状态码和一个友好的提示信息,而不是看到一堆让人摸不着头脑的堆栈信息。
使用@ExceptionHandler
注解
@ExceptionHandler
注解可以直接写在控制器中,用于处理该控制器内部的异常。有点像“分区管理”,每个控制器都可以有自己的异常处理逻辑。
示例代码
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
public class UserController {
private UserService userService;
public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException e) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body("User error: " + e.getMessage());
}
public ResponseEntity<User> getUser( Long id) {
User user = userService.getUserById(id);
if (user == null) {
throw new UserNotFoundException("User with ID " + id + " not found");
}
return ResponseEntity.ok(user);
}
}
代码解析
@ExceptionHandler(UserNotFoundException.class)
:捕获UserNotFoundException
类型的异常,并返回一个自定义的 404 错误信息。getUser
方法:当用户 ID 不存在时,手动抛出一个UserNotFoundException
。返回值:通过 ResponseEntity
返回 404 状态码和详细的错误描述。
实际效果
当用户访问 /users/{id}
接口,而该用户 ID 不存在时,API 会返回 404 状态码和友好的错误信息:“User with ID X not found”。
实现HandlerExceptionResolver
接口
如果你需要更灵活的异常处理,比如返回自定义的页面,或者根据不同的异常类型执行不同的逻辑,可以通过实现HandlerExceptionResolver
接口来实现。
示例代码
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GlobalExceptionHandler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView mav = new ModelAndView();
mav.addObject("error", ex.getMessage());
mav.setViewName("error"); // 指向 error.html 页面
return mav;
}
}
代码解析
实现 HandlerExceptionResolver
接口:通过重写resolveException
方法来自定义异常处理逻辑。ModelAndView
:返回一个包含错误信息的视图(如error.html
)。灵活性:可以根据异常类型动态返回不同的页面或数据。
实际效果
当某个地方抛出异常时,用户会被引导到一个定制的错误页面,而不是看到默认的错误提示。
温馨提示
不要忽视小异常:一些看似无关紧要的异常(比如空指针异常)可能会导致整个程序崩溃,所以一定要养成良好的异常处理习惯。 优先级问题:如果同时使用了 @ControllerAdvice
和@ExceptionHandler
,局部的@ExceptionHandler
会优先执行。日志记录:在处理异常时,别忘了记录日志,这样可以方便后续排查问题。
总结
本文介绍了 SpringBoot 中三种全局异常处理方式:
@ControllerAdvice
:适用于全局统一的异常处理。@ExceptionHandler
:适用于控制器内部的局部异常处理。HandlerExceptionResolver
:适用于需要高度自定义的异常处理场景。
每种方式都有自己的特点和适用场景,你可以根据实际需求选择合适的方案。记住,优秀的异常处理不仅能让你的程序更健壮,还能提升用户体验。希望这篇文章能帮你轻松掌握 SpringBoot 的全局异常处理!