Spring Boot全局异常处理器未捕获ResourceNotFoundException求助
解决Spring Boot中JAX-RS端点异常无法被@ControllerAdvice捕获的问题
你的问题根源很明确:你用了JAX-RS(Jersey)的注解来定义端点,但Spring的@ControllerAdvice只负责处理Spring MVC/Spring WebFlux控制器抛出的异常,对JAX-RS端点完全无效,所以抛出的ResourceNotFoundException才会直接返回堆栈跟踪,没有被全局处理器捕获。
下面给你两种可行的解决方案,根据你的技术选型来选:
方案一:继续使用JAX-RS,改用JAX-RS的异常处理机制
JAX-RS有自己的异常处理规范,需要实现ExceptionMapper接口并标注@Provider来全局捕获异常:
import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; @Provider public class ResourceNotFoundExceptionMapper implements ExceptionMapper<ResourceNotFoundException> { @Override public Response toResponse(ResourceNotFoundException ex) { ExceptionResponse response = new ExceptionResponse(); response.setErrorCode("resource not found"); response.setErrorMessage(ex.getMessage()); return Response.status(Response.Status.NOT_FOUND) .entity(response) .build(); } }
注意事项:
- 确保这个
@Provider类被Jersey的扫描机制覆盖到:如果你的Spring Boot项目用了spring-boot-starter-jersey,可以在Jersey的配置类里通过register(ResourceNotFoundExceptionMapper.class)手动注册,或者给这个类加上@Component让Spring自动管理(前提是Jersey和Spring整合正常)。
方案二:切换到Spring MVC注解,让@ControllerAdvice生效
如果没有必须用JAX-RS的理由,建议直接改用Spring MVC的注解,这样你的GlobalExceptionHandlerController就能正常工作了:
修改CustomerEndpoint的注解:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/customer") public class CustomerEndpoint { private static final Logger LOGGER = LoggerFactory.getLogger(CustomerEndpoint.class); @Autowired private ICustomerService customerService; @GetMapping("/{id}") public ResponseEntity<CustomerVO> getCustomerById(@PathVariable("id") Integer id) throws ResourceNotFoundException { CustomerVO customer = customerService.getCustomerById(id); if (customer == null) { // 注意:构造器参数是long,要把Integer转成long throw new ResourceNotFoundException(id.longValue(), "Customer not found"); } return ResponseEntity.ok(customer); } }
额外检查点:
- 确认
GlobalExceptionHandlerController所在的包被Spring的组件扫描覆盖到(比如和主启动类同包,或者通过@ComponentScan指定扫描路径)。 - 你原来的代码里抛出异常时写的
customerId是未定义的变量,要改成方法参数id,并且转成long类型匹配构造器。
这样调整后,当请求不存在的客户ID时,ResourceNotFoundException就会被GlobalExceptionHandlerController捕获,返回你定义的ExceptionResponse格式的404响应。
内容的提问来源于stack exchange,提问作者hema chandra
相关产品推荐
相关产品推荐

