为什么需要全局异常处理器?
默认情况下,Spring Boot会显示Whitelabel Error Page,但你可以通过自定义错误页面、使用@ControllerAdvice、实现ErrorController或配置ErrorViewResolver等方式来替换默认的错误处理逻辑,以满足你的需求。

- 统一处理异常:避免在每个控制器方法中重复编写异常处理逻辑。
- 标准化响应格式:确保所有异常都返回统一的 JSON 格式,便于客户端处理。
- 提升用户体验:隐藏具体的异常细节,只返回必要的错误信息,避免泄露敏感信息。

系统的Dao、Service、Controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理。
全局异常效果演示
假设你的应用中有一个控制器方法:
@GetMapping("/test")
public String test() {
throw new IllegalArgumentException("这是一个非法参数异常");
}
当访问 /test 时,会抛出 IllegalArgumentException。这个异常会被 CommonGlobalExceptionHandler 捕获,并处理如下:
- 检查异常类型:
-
- 因为
IllegalArgumentException不是ConditionException,所以进入else分支。
- 因为
- 返回一个
JsonResponse对象:
-
- 错误代码为
"500"。 - 错误信息为
"这是一个非法参数异常"。
- 错误代码为
最终返回的 JSON 数据可能是:
{
"code": "500",
"data": null,
"msg": "这是一个非法参数异常"
}
隐藏具体的异常细节,只返回必要的错误信息,避免泄露敏感信息。
自定义业务异常
自定义业务异常可以精准描述问题、控制业务流程、方便维护和提升用户体验。
自定义异常类ConditionException,继承RuntimeException。目的是在程序中抛出自定义的异常,同时携带一个错误代码code,方便后续的错误处理。
RuntimeException是Java中的一种未检查异常(unchecked exception)。未检查异常不需要在方法签名中显式声明(使用throws关键字),这使得使用起来更加灵活。
package org.example.model.exception;
public class ConditionException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String code;
public ConditionException(String code, String name) {
super(name);
this.code = code;
}
public ConditionException(String name) {
super(name);
code = "500";
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
如何实现全局异常处理?
1. 创建类
在 org.example.service.handler 包中创建一个类,命名为 CommonGlobalExceptionHandler。这个类将用于处理全局异常。
package org.example.service.handler;
public class CommonGlobalExceptionHandler {
}
2. 在类上添加必要的注解
为了让 Spring 框架识别这个类是一个全局异常处理器,我们需要添加一些注解。
步骤 1:添加 @ControllerAdvice 注解
@ControllerAdvice 注解用于标记这个类是一个全局异常处理器。它会告诉 Spring,这个类中的方法可以处理来自所有控制器的异常。
@ControllerAdvice
public class CommonGlobalExceptionHandler {
}
步骤 2:添加 @Order 注解
@Order 注解用于指定这个异常处理器的优先级。Ordered.HIGHEST_PRECEDENCE 表示这个处理器的优先级最高,确保它会优先处理异常。
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CommonGlobalExceptionHandler {
}
3. 定义异常处理方法
接下来,我们需要定义一个方法来处理异常。这个方法会捕获所有异常,并返回一个统一的 JSON 响应。
步骤 1:添加方法
我们定义一个方法 commonExceptionHandler,它会处理所有异常。方法的参数包括:
HttpServletRequest request:表示当前的 HTTP 请求。Exception e:表示捕获到的异常。
方法的返回类型是 JsonResponse<String>,这是一个自定义的类,用于封装 JSON 响应。
public JsonResponse<String> commonExceptionHandler(HttpServletRequest request, Exception e) {
}
步骤 2:添加注解
为了让 Spring 框架知道这个方法是用来处理异常的,我们需要添加两个注解:
@ExceptionHandler(value = Exception.class):指定这个方法可以处理所有类型的异常。@ResponseBody:表示这个方法的返回值将被直接写入 HTTP 响应体中。
@ExceptionHandler(value = Exception.class)
@ResponseBody
public JsonResponse<String> commonExceptionHandler(HttpServletRequest request, Exception e) {
}
4. 实现异常处理逻辑
在方法中,我们需要根据异常类型来生成不同的响应。
步骤 1:获取异常信息
首先,获取异常的错误信息。
String errorMsg = e.getMessage();
步骤 2:判断异常类型
我们自定义了一个异常类 ConditionException,它有一个 code 属性,用于表示错误代码。如果捕获到的异常是自定义业务异常 ConditionException,我们返回自定义的错误代码;否则,返回默认的错误代码 "500"。
if (e instanceof ConditionException) {
String errorCode = ((ConditionException) e).getCode();
return new JsonResponse<>(errorCode, errorMsg);
} else {
return new JsonResponse<>("500", errorMsg);
}
5. 完整代码
将上述步骤组合起来,完整的代码如下:
package org.example.service.handler;
import org.example.model.JsonResponse;
import org.example.model.exception.ConditionException;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CommonGlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public JsonResponse<String> commonExceptionHandler(HttpServletRequest request, Exception e) {
String errorMsg = e.getMessage();
if (e instanceof ConditionException) {
String errorCode = ((ConditionException) e).getCode();
return new JsonResponse<>(errorCode, errorMsg);
} else {
return new JsonResponse<>("500", errorMsg);
}
}
}
6. 使用场景
当用户触发异常时,这个全局异常处理器会捕获异常,并返回一个统一的 JSON 响应,例如:
{
"code": "500",
"message": "Internal Server Error"
}
或者,如果捕获到的是 自定义业务异常ConditionException:
{
"code": "400",
"message": "Invalid request"
}

5550

被折叠的 条评论
为什么被折叠?



