Spring Boot自定义ExceptionHandler未生效,请求排查原因
Spring Boot REST API 自定义异常未被捕获问题
我在Spring Boot开发REST API时,为了让客户端收到有意义的响应而非404,添加了异常处理逻辑,但抛出的自定义异常并未被处理器捕获。
相关代码
REST接口类
@Path("/v1") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Slf4j @Service @RequiredArgsConstructor public class UserRestService { private final UserRepository userRepository; @GET @Path("/users/{publicId}") public RestResponse<UserListItemRestDto> getUserByPublicId(@PathParam("publicId") UUID publicId) { Optional<User> optionalUser = userRepository.findOneByPublicId(publicId); if(optionalUser.isEmpty()){ throw new ApiRequestException("CANNOT FIND USER"); } User user = optionalUser.get(); return RestResponse.of(UserListItemRestDto.builder() .email(user.getEmail()) .name(user.getName()) .build()); } ...
异常处理器类
@RestControllerAdvice public class ApiExceptionHandler { @ExceptionHandler(ApiRequestException.class) public ResponseEntity<ApiException> handleApiRequestException(ApiRequestException e){ return new ResponseEntity<>(new ApiException(e.getMessage(), e.getCause(), HttpStatus.BAD_REQUEST, ZonedDateTime.now()),HttpStatus.BAD_REQUEST); } }
自定义异常类
public class ApiRequestException extends RuntimeException{ public ApiRequestException(String message){ super(message); } public ApiRequestException(String message, Throwable cause){ super(message,cause); } }
报错信息
org.jboss.resteasy.spi.UnhandledException: com.common.rest.exception.ApiRequestException: CANNOT FIND USER at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:105) ~[resteasy-core-5.0.0.Final.jar:5.0.0.Final] ...(省略部分栈信息) Caused by: com.common.rest.exception.ApiRequestException: CANNOT FIND USER at com.backend.flows.user.rest.UserRestService.getUserByPublicId(UserRestService.java:55) ~[classes/:na] ...(省略部分栈信息)
问题原因与解决方案
核心问题是技术栈不兼容:你用了JAX-RS(RESTEasy)的注解定义接口,但用了Spring MVC的@RestControllerAdvice做异常处理,两者不属于同一生态,无法互通。
方案一:切换为Spring MVC注解(推荐)
将JAX-RS注解替换为Spring MVC原生注解,保持Spring生态一致性:
@RequestMapping("/v1") @RestController @Slf4j @RequiredArgsConstructor public class UserRestService { private final UserRepository userRepository; @GetMapping("/users/{publicId}") public RestResponse<UserListItemRestDto> getUserByPublicId(@PathVariable UUID publicId) { Optional<User> optionalUser = userRepository.findOneByPublicId(publicId); if(optionalUser.isEmpty()){ throw new ApiRequestException("CANNOT FIND USER"); } User user = optionalUser.get(); return RestResponse.of(UserListItemRestDto.builder() .email(user.getEmail()) .name(user.getName()) .build()); } }
修改后,原有的@RestControllerAdvice异常处理器就能正常捕获异常。
方案二:使用RESTEasy原生异常处理(若坚持用JAX-RS)
实现JAX-RS的ExceptionMapper接口来处理异常:
@Provider public class ApiRequestExceptionMapper implements ExceptionMapper<ApiRequestException> { @Override public Response toResponse(ApiRequestException exception) { ApiException apiException = new ApiException( exception.getMessage(), exception.getCause(), HttpStatus.BAD_REQUEST, ZonedDateTime.now() ); return Response.status(Response.Status.BAD_REQUEST) .entity(apiException) .type(MediaType.APPLICATION_JSON) .build(); } }
确保该类被Spring扫描到(放在主类的扫描包下,或通过@ComponentScan指定)。
额外注意:ApiException类需要提供完整的getter方法,否则序列化后客户端无法获取完整异常信息。
内容的提问来源于stack exchange,提问作者Bufer
相关产品推荐
相关产品推荐

