如何在Spring Boot中用@ControllerAdvice处理404 NotFound异常?
解决Spring Boot中用@ControllerAdvice处理404(错误端点)异常的问题
首先明确:可以通过@ControllerAdvice处理请求错误端点的404异常,但你当前使用的javassist.NotFoundException完全不对,因为Spring MVC在找不到请求映射时,抛出的是特定的异常类,下面是具体解决方案:
1. 为什么当前代码不生效
当客户端请求不存在的端点时,Spring Boot默认不会抛出NotFoundException(不管是javassist还是自定义的),而是直接返回白标错误页面。只有配置开启后,Spring才会抛出org.springframework.web.servlet.NoHandlerFoundException,这才是你需要捕获的异常类。
2. 配置Spring Boot抛出NoHandlerFoundException
在application.properties中添加以下配置:
# 开启找不到处理器时抛出异常 spring.mvc.throw-exception-if-no-handler-found=true # 关闭静态资源映射(避免静态资源路径干扰,比如/favicon.ico这类请求不会触发异常) spring.web.resources.add-mappings=false
如果使用application.yml则配置如下:
spring: mvc: throw-exception-if-no-handler-found: true web: resources: add-mappings: false
3. 修改ControllerAdvice类
添加处理NoHandlerFoundException的方法,同时移除无用的javassist.NotFoundException相关代码:
import com.ds.ecommerce.exception.PriceNotFoundException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.servlet.NoHandlerFoundException; import javax.xml.bind.ValidationException; @Slf4j @ControllerAdvice public class PricesGlobalExceptionHandler { @ResponseBody @ExceptionHandler @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ErrorDTO handleException(Exception exception) { log.error(exception.getMessage(), exception); return ErrorDTO.builder() .code(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()) .message("Unexpected error!") .build(); } @ResponseBody @ExceptionHandler(value = {ValidationException.class}) @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorDTO handleException(ValidationException validationException) { String exceptionMessage = validationException.getMessage(); log.error(exceptionMessage, validationException); return ErrorDTO.builder() .code(HttpStatus.BAD_REQUEST.getReasonPhrase()) .message(exceptionMessage) .build(); } @ResponseBody @ExceptionHandler(value = {PriceNotFoundException.class}) @ResponseStatus(HttpStatus.NOT_FOUND) public ErrorDTO handleException(PriceNotFoundException priceNotFoundException) { String exceptionMessage = priceNotFoundException.getMessage(); log.error(exceptionMessage, priceNotFoundException); return ErrorDTO.builder() .code(HttpStatus.NOT_FOUND.getReasonPhrase()) .message(exceptionMessage) .build(); } // 新增:处理请求不存在端点的404异常 @ResponseBody @ExceptionHandler(value = {NoHandlerFoundException.class}) @ResponseStatus(HttpStatus.NOT_FOUND) public ErrorDTO handleNoHandlerFoundException(NoHandlerFoundException ex) { String message = String.format("请求的路径 %s 不存在", ex.getRequestURL()); log.error(message, ex); return ErrorDTO.builder() .code(HttpStatus.NOT_FOUND.getReasonPhrase()) .message(message) .build(); } }
4. 补充说明
PriceNotFoundException是你自定义的业务异常,用于处理业务逻辑中找不到资源(比如找不到商品价格)的场景,和请求错误端点的404属于不同场景。- 配置
spring.web.resources.add-mappings=false是为了确保静态资源的请求(比如/css、/js)也会触发NoHandlerFoundException,如果你的项目需要保留静态资源映射,可以根据实际情况调整,但此时静态资源路径的请求不会进入异常处理器。
内容的提问来源于stack exchange,提问作者elvis
相关产品推荐
相关产品推荐

