Spring Boot 2.7.18全局异常处理配置(不禁用自动配置)
解决方案:Spring Boot 2.7.18 全局异常处理(兼容单页应用+REST端点)
核心结论
你的思路没问题,ResponseEntityExceptionHandler是Spring Boot实现全局异常处理的标准方式,问题出在配置冲突导致静态资源(Angular单页应用文件)无法被正确处理,同时异常处理逻辑未覆盖400、500这类容器级错误。
方案一:保留Spring Boot默认配置(推荐)
无需添加@EnableWebMvc,也不要修改spring.web.resources.add-mappings=false,通过以下调整实现全局异常处理:
1. 修正全局异常处理器代码
覆盖ResponseEntityExceptionHandler的更多默认方法,同时区分API请求和前端静态资源/页面请求,避免影响Angular应用加载:
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; @ControllerAdvice class GlobalExceptionHandler extends ResponseEntityExceptionHandler { private static final Logger logger = Logger.getLogger(GlobalExceptionHandler.class.getName()); private static final String GENERIC_ERROR_MSG = "……您的请求无法完成……"; // 处理所有未被捕获的异常(含REST端点抛出的异常) @ExceptionHandler(Throwable.class) ResponseEntity<Object> handleAllUncaughtExceptions(Throwable ex, HttpServletRequest request) { // 记录异常详情用于排查 logger.severe("请求路径: " + request.getRequestURI() + " 发生异常: " + ex.getMessage()); ex.printStackTrace(); // 区分API请求和页面请求 if (isApiRequest(request)) { Map<String, String> responseBody = new HashMap<>(); responseBody.put("message", GENERIC_ERROR_MSG); return new ResponseEntity<>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR); } else { // 前端页面请求,返回自定义错误页或重定向到首页(按需调整) return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("error.html"); } } // 处理400 Bad Request(如参数绑定错误) @Override protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { HttpServletRequest nativeRequest = (HttpServletRequest) request.getNativeRequest(); logger.severe("400错误: 请求路径=" + nativeRequest.getRequestURI() + ", 原因=" + ex.getMessage()); if (isApiRequest(nativeRequest)) { Map<String, String> responseBody = new HashMap<>(); responseBody.put("message", GENERIC_ERROR_MSG); return new ResponseEntity<>(responseBody, status); } return super.handleExceptionInternal(ex, body, headers, status, request); } // 处理404错误(仅针对API请求,前端路由由Angular处理) @Override protected ResponseEntity<Object> handleNoHandlerFoundException(org.springframework.web.servlet.NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { HttpServletRequest nativeRequest = (HttpServletRequest) request.getNativeRequest(); logger.warning("404错误: 请求路径=" + nativeRequest.getRequestURI()); if (isApiRequest(nativeRequest)) { Map<String, String> responseBody = new HashMap<>(); responseBody.put("message", GENERIC_ERROR_MSG); return new ResponseEntity<>(responseBody, HttpStatus.NOT_FOUND); } else { // 前端单页应用路由,重定向到index.html让Angular处理 return ResponseEntity.status(HttpStatus.OK) .body("index.html"); } } // 根据实际API前缀判断是否为API请求(示例为/api/**) private boolean isApiRequest(HttpServletRequest request) { return request.getRequestURI().startsWith("/api/"); } }
2. 添加必要配置
在application.properties中仅添加:
# 仅对API请求抛出404异常,静态资源请求不触发 spring.mvc.throw-exception-if-no-handler-found=true
原代码未触发的原因
@ExceptionHandler(Throwable.class)不会捕获容器级错误(如默认的400、404处理),需覆盖ResponseEntityExceptionHandler对应方法。- 未区分API和前端请求,导致静态资源请求被异常处理器拦截,无法加载。
方案二:使用@EnableWebMvc并恢复Spring Boot默认配置
若必须使用@EnableWebMvc,需手动注册Spring Boot默认资源处理器,避免静态资源无法访问:
1. 创建WebMvc配置类
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc class WebMvcConfig implements WebMvcConfigurer { // 恢复Spring Boot默认静态资源映射 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") .addResourceLocations("classpath:/static/", "classpath:/public/", "classpath:/resources/", "classpath:/META-INF/resources/") .setCachePeriod(0); } }
2. 复用方案一中的异常处理器
保持方案一的GlobalExceptionHandler实现,同时添加spring.mvc.throw-exception-if-no-handler-found=true配置。
额外注意事项
- WebSocket异常处理:WebSocket异常需单独处理,可通过
@ServerEndpoint的onError方法或实现WebSocketHandlerDecoratorFactory全局处理。 - 日志优化:建议用SLF4J/Logback替代JDK Logger,更灵活记录异常堆栈。
- 前端路由兼容:Angular单页应用的非API 404请求需重定向到
index.html,由Angular路由引擎处理页面跳转。
内容的提问来源于stack exchange,提问作者plex4r
相关产品推荐
相关产品推荐

