You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Spring Boot仅在HTML请求时返回500.html错误页

问题解决:根据请求类型返回JSON或HTML错误响应

问题背景

需求:

  • 使用curl调用localhost:8080/fail时返回JSON格式异常信息
  • 通过浏览器访问该接口时返回src/main/templates/error/500.html页面

现有配置:

  • 已实现标注@ControllerAdvice的全局异常处理器GeneralExceptionHandler
  • src/main/templates/error/路径下已放置500.html和404.html,其中404页面可正常生效

问题:触发异常时,无论用curl还是浏览器访问,始终返回JSON结果,浏览器无法加载500错误页面。

问题根源

你的@ControllerAdvice全局异常处理器会捕获所有异常并统一返回JSON响应,没有根据请求的Accept头部判断客户端期望的响应格式,覆盖了Spring Boot默认的错误页面渲染逻辑。而404能正常生效是因为它未被你的全局异常处理器捕获,走的是Spring Boot默认错误处理流程。

解决方案

1. 修改全局异常处理器,根据请求类型返回对应响应

将异常处理方法改为根据客户端请求的Accept头,动态返回ModelAndView(HTML页面)或ResponseEntity(JSON):

@ControllerAdvice
public class GeneralExceptionHandler {

    @Autowired
    private ContentNegotiationManager contentNegotiationManager;

    @ExceptionHandler(Exception.class)
    public Object handleGlobalException(Exception ex, HttpServletRequest request) {
        // 解析请求期望的响应媒体类型
        ServletWebRequest webRequest = new ServletWebRequest(request);
        MediaType targetMediaType = contentNegotiationManager.resolveMediaTypes(webRequest).getFirst();

        if (MediaType.TEXT_HTML.isCompatibleWith(targetMediaType)) {
            // 浏览器请求,返回500错误页面
            ModelAndView modelAndView = new ModelAndView("error/500");
            modelAndView.addObject("errorMsg", ex.getMessage());
            return modelAndView;
        } else {
            // 非浏览器请求(如curl),返回JSON异常信息
            Map<String, Object> errorResp = new HashMap<>();
            errorResp.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
            errorResp.put("message", ex.getMessage());
            return new ResponseEntity<>(errorResp, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

注意:确保使用的是@ControllerAdvice而非@RestControllerAdvice,后者默认所有方法返回JSON,无法返回ModelAndView。

2. 配置内容协商策略(可选)

在application.properties中配置Spring MVC的内容协商规则,确保优先根据Accept头判断响应类型:

# 禁用路径扩展名和参数作为内容协商依据
spring.mvc.contentnegotiation.favor-path-extension=false
spring.mvc.contentnegotiation.favor-parameter=false
# 允许根据Accept头判断响应类型
spring.mvc.contentnegotiation.ignore-accept-header=false
# 默认响应类型为JSON
spring.mvc.contentnegotiation.default-content-type=application/json

3. 验证测试

  • 使用curl请求:curl localhost:8080/fail,应返回JSON格式错误信息
  • 使用浏览器访问localhost:8080/fail,应渲染500.html页面

内容的提问来源于stack exchange,提问作者Archimedes Trajano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:11:18