唐山市网站建设_网站建设公司_门户网站_seo优化
2026/3/1 15:34:30 网站建设 项目流程

在SpringBoot应用中,构建一套健壮、统一的异常处理机制是保障系统稳定性和提供友好API体验的关键。通常,有效的全局异常处理主要依赖于以下三种核心方案,它们分别适用于不同的层次和场景。下表清晰对比了其核心区别,可作为快速选型参考:

方案核心组件处理范围主要特点适用场景
方案一`@RestControllerAdvice`+`@ExceptionHandler`Controller层及由其调用的服务中抛出的异常声明式、集成度最高、配置简洁,是RESTAPI的首选方案。标准的WebMVC应用,需统一RESTAPI错误响应格式。
方案二自定义`BasicErrorController`SpringBoot默认`/error`端点捕获的所有异常(包括未进入Controller的异常,如404)。完全接管SpringBoot的默认白页错误处理,定制力强。需要深度定制默认错误页(HTML/JSON)结构,或处理非Controller流程的异常。
方案三实现`HandlerExceptionResolver`接口全局最广,可处理过滤器(`Filter`)、拦截器(`Interceptor`)等环节的异常。SpringMVC最底层的异常解析扩展点,优先级最低,常作为兜底。作为前两种方案的补充,用于捕获`@ControllerAdvice`无法覆盖的异常(如安全框架抛出的异常)。

方案一:@RestControllerAdvice+@ExceptionHandler(推荐首选)

此方案通过声明式注解集中处理控制器中抛出的异常,是目前最主流且优雅的RESTAPI异常处理方式。

核心机制

`@RestControllerAdvice`:一个组合注解,等价于`@ControllerAdvice`+`@ResponseBody`。它标识一个类为全局REST异常处理器,并确保其方法返回值自动通过`HttpMessageConverter`序列化为JSON。

`@ExceptionHandler`:标注于方法上,定义该方法负责处理的特定异常类型。SpringMVC的异常处理机制会按优先级匹配:先查找当前Controller内的`@ExceptionHandler`,若未找到,则在全局`@ControllerAdvice`类中查找。

执行流程:请求在`DispatcherServlet`调度过程中,于Controller内或其后抛出的异常,会被该机制拦截并路由到对应的处理方法。

完整实现示例

1.定义统一响应体(`Result`)

java

@Data

@NoArgsConstructor

@AllArgsConstructor

publicclassResult<T>{

privateIntegercode;//业务状态码,如200成功,4001业务异常

privateStringmsg;//提示信息

privateTdata;//响应数据

publicstatic<T>Result<T>success(Tdata){

returnnewResult<>(200,"操作成功",data);

}

publicstatic<T>Result<T>error(Integercode,Stringmsg){

returnnewResult<>(code,msg,null);

}

}

2.定义自定义业务异常(`BusinessException`)

java

publicclassBusinessExceptionextendsRuntimeException{

privatefinalIntegercode;

publicBusinessException(Integercode,Stringmessage){

super(message);

this.code=code;

}

//Getter...

}

3.实现全局异常处理器(`GlobalExceptionHandler`)

java

@Slf4j

@RestControllerAdvice

publicclassGlobalExceptionHandler{

/

处理自定义业务异常

/

@ExceptionHandler(BusinessException.class)

publicResult<?>handleBusinessException(BusinessExceptione,HttpServletRequestrequest){

log.warn("业务异常:URI={},Code={},Msg={}",request.getRequestURI(),e.getCode(),e.getMessage());

returnResult.error(e.getCode(),e.getMessage());

}

/

处理参数校验异常(@Validated/@Valid触发)

/

@ExceptionHandler(MethodArgumentNotValidException.class)

publicResult<?>handleValidationException(MethodArgumentNotValidExceptione,HttpServletRequestrequest){

StringerrorMsg=e.getBindingResult().getFieldErrors().stream()

.map(FieldError::getDefaultMessage)

.collect(Collectors.joining(";"));

log.warn("参数校验失败:URI={},Errors={}",request.getRequestURI(),errorMsg);

returnResult.error(400,"请求参数不合法:"+errorMsg);

}

/

兜底处理所有其他未声明异常

/

@ExceptionHandler(Exception.class)

publicResult<?>handleGlobalException(Exceptione,HttpServletRequestrequest){

//关键:记录完整的异常堆栈,便于排查

log.error("系统异常:URI={}",request.getRequestURI(),e);

//面向用户返回友好提示,避免泄露系统细节

returnResult.error(500,"系统繁忙,请稍后再试");

}

}

方案特点与注意事项

优点:与SpringMVC无缝集成、配置简洁、代码侵入性低,能完美满足RESTfulAPI对统一错误格式的需求。

局限性:主要处理从`DispatcherServlet`开始到`Controller`返回之间的异常。对于在进入Controller之前(如`Filter`)或视图渲染之后发生的异常,默认无法捕获。

常见问题排查:

处理器不生效:确保类被Spring组件扫描到(通常位于主应用类同级或子包下)。

异常被“吞没”:若在业务代码中使用`trycatch`捕获异常后未重新抛出,则全局处理器无法介入。

方案二:自定义BasicErrorController(用于接管默认错误端点)

此方案通过继承并定制`BasicErrorController`,完全覆盖SpringBoot默认的`/error`错误处理端点,适用于深度定制错误响应。

核心机制

SpringBoot默认将所有未处理的错误(包括404等)映射到`/error`端点,由`BasicErrorController`处理。它会根据请求的`Accept`头决定返回HTML错误页或JSON错误信息。自定义此控制器可以彻底改变这一默认行为。

实现示例

java

@Controller

@RequestMapping("${server.error.path:${error.path:/error}}")

publicclassCustomErrorControllerextendsBasicErrorController{

publicCustomErrorController(ErrorAttributeserrorAttributes){

super(errorAttributes,newErrorProperties());

}

@Override

publicResponseEntity<Map<String,Object>>error(HttpServletRequestrequest){

HttpStatusstatus=getStatus(request);

Map<String,Object>originalError=super.error(request).getBody();

//重构错误响应体

Map<String,Object>customError=newHashMap<>();

customError.put("success",false);

customError.put("timestamp",originalError.get("timestamp"));

customError.put("status",status.value());

customError.put("error",originalError.get("error"));

customError.put("message","自定义:访问"+originalError.get("path")+"时出错");

//生产环境建议移除"trace"等敏感信息

//customError.remove("trace");

returnnewResponseEntity<>(customError,status);

}

}

方案特点与适用场景

优点:掌控力极强,可定义SpringBoot底层错误处理的所有细节。

缺点:实现相对复杂,主要面向SpringBoot的默认错误路径。

适用场景:

1.传统Web应用需要提供品牌化的精美错误页面。

2.对SpringBoot默认的错误JSON结构有极其特殊且统一的改造需求。

3.需要处理如404(NoHandlerFoundException)等在进入Controller前就被全局捕获的异常。

方案三:实现HandlerExceptionResolver接口(底层兜底方案)

此方案实现了SpringMVC最底层的异常解析接口,可作为全局异常处理的最后一道防线。

核心机制

`HandlerExceptionResolver`是SpringMVC异常处理链中的一个核心接口。

其优先级低于`@ExceptionHandler`。若更高优先级的处理器已处理异常,它通常不会生效。

优势在于其处理范围最广,能够处理`Filter`、`Interceptor`等MVC框架生命周期早期或晚期抛出的、未被`@ControllerAdvice`捕获的异常。

实现示例

java

@Component

@Order(Ordered.LOWEST_PRECEDENCE)//设置为最低优先级,作为最终兜底

publicclassGlobalHandlerExceptionResolverimplementsHandlerExceptionResolver{

privatestaticfinalObjectMapperobjectMapper=newObjectMapper();

@Override

publicModelAndViewresolveException(HttpServletRequestrequest,

HttpServletResponseresponse,

Objecthandler,

Exceptionex){

//1.记录所有未被前述方案捕获的异常

log.error("全局异常解析器捕获未处理异常,URI:{}",request.getRequestURI(),ex);

//2.手动构造并返回统一的JSON响应

try{

response.setContentType(MediaType.APPLICATION_JSON_VALUE);

response.setCharacterEncoding("UTF8");

response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

Result<?>result=Result.error(500,"系统内部错误,请稍后重试");

Stringjson=objectMapper.writeValueAsString(result);

try(PrintWriterwriter=response.getWriter()){

writer.write(json);

writer.flush();

}

}catch(IOExceptione){

log.error("在异常解析器中写入响应时出错",e);

}

//3.返回空的ModelAndView,告知框架异常已在此处理完毕

returnnewModelAndView();

}

}

方案特点与适用场景

优点:处理范围最全面,是捕获“漏网之鱼”的终极保障。

缺点:需手动处理HTTP响应,代码较为繁琐,且会绕过SpringBoot的一些自动化特性。

适用场景:通常不作为首选方案,而是与方案一结合使用,用于确保捕获那些因超出`Controller`生命周期而未被`@ControllerAdvice`处理的异常(例如,在自定义`Filter`或安全框架认证/授权环节抛出的异常)。

总结与选型建议

1.首选方案一(`@RestControllerAdvice`):对于绝大多数基于SpringMVC的RESTAPI项目,此方案足以应对95%以上的异常处理需求。它简洁、强大且符合框架设计理念。

2.按需启用方案二(`BasicErrorController`):当需要对SpringBoot的默认错误页面或非Controller流程的异常(如静态资源404)进行深度、统一的定制时启用。

3.谨慎使用方案三(`HandlerExceptionResolver`):将其视为一个补充和兜底机制。在复杂的应用架构中,若存在`@ControllerAdvice`无法覆盖的异常处理死角(如全局过滤器的异常),可实现此接口进行最终捕获,并确保其优先级最低。

一个稳健的异常处理体系往往结合方案一与方案三,由`@RestControllerAdvice`处理主要业务异常,由自定义的`HandlerExceptionResolver`作为安全网,确保所有异常都能被记录并以可控的方式反馈给客户端。

来源:小程序app开发|ui设计|软件外包|IT技术服务公司-木风集团-木风集团

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询