You need to enable JavaScript to run this app. Spring Boot+SPA 解决刷新403时如何仅对UI路径重定向,保留/api错误处理
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+SPA 解决刷新403时如何仅对UI路径重定向,保留/api错误处理

当前实现的核心问题

你写的自定义/error映射,直接覆盖了Spring Boot原生的错误控制器BasicErrorController——所有触发错误流程的请求(不管是前端页面路径还是/api/**接口),都会被强制走你的重定向逻辑,转发到/(index.html)。
当原始请求是发给/api/someApi的POST参数错误时,转发后的请求实际等价于“向index.html发送POST请求”,而静态资源路径默认只支持GET方法,自然就会返回405 Method Not Allowed,完全丢失了接口原本的错误状态和结构化错误信息。

可落地的实现方案

方案一:改造现有/error处理器,基于原始请求路径分流

Spring Boot在进入错误流程时,会把原始请求的关键信息存在request的内置属性中,你可以通过这些属性判断是否要触发重定向:

  • 从request中读取RequestDispatcher.ERROR_REQUEST_URI,拿到触发错误的原始请求路径
  • 对/api/前缀的请求,直接返回Spring默认的错误响应,不做转发

修正后的核心代码(顺便修正原代码中的笔误:ModelAndView拼写、@RequestMapping的路径引号缺失):

@RequestMapping("/error")
public ModelAndView redirect(HttpServletRequest request) {
    // 读取Spring内置错误上下文的原始请求信息
    String originalUri = (String) request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
    Integer originalStatusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

    // 接口类请求:保留原生错误处理逻辑,不重定向
    if (originalUri != null && originalUri.startsWith("/api/")) {
        ModelAndView defaultError = new ModelAndView();
        // 恢复原始错误状态码,避免状态被覆盖
        defaultError.setStatus(HttpStatus.valueOf(originalStatusCode));
        // 交给Spring默认的错误视图生成逻辑返回结构化错误
        defaultError.setView(new MappingJackson2JsonView());
        return defaultError;
    }

    // 非接口的UI路径请求:转发到index.html交给SPA路由处理
    return new ModelAndView("forward:/");
}

方案二(更推荐):基于Spring Boot内置扩展点ErrorViewResolver实现分流

Spring Boot专门预留了ErrorViewResolver接口用来自定义错误视图的返回逻辑,用这个方案完全不需要覆盖原生的BasicErrorController,不会破坏原有错误处理流程:

@Component
public class SpaForwardErrorViewResolver implements ErrorViewResolver {
    @Override
    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
        String originalUri = (String) request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);

        // 接口路径的错误:返回null表示不做自定义处理,直接走Spring默认错误逻辑
        if (originalUri != null && originalUri.startsWith("/api/")) {
            return null;
        }

        // UI路径的错误:转发到index.html
        return new ModelAndView("forward:/");
    }
}

这个方案的优势:

  • 完全不修改Spring Boot原生的错误控制器,/api/**的错误会完全保持原有行为:返回对应的状态码、结构化JSON错误体、全局异常处理器的逻辑也不会被打断
  • 不需要手动处理状态码、错误模型的传递,Spring会自动把原有的错误上下文传给默认处理器
  • 从根源上避免了转发到静态资源后触发方法不支持、状态码错乱的问题
常见踩坑提醒
  • 若项目集成了Spring Security,需保证/error路径被Security过滤器链放行,否则请求进入错误流程时会先被Security拦截,导致分流逻辑无法生效
  • 路径匹配规则要严格,避免把/api/下的路径错误转发到index,startsWith("/api/")的规则可以正常覆盖多层嵌套的api路径(比如/api/user/profile)
  • 静态资源路径(比如/static/**、/assets/**)的错误可以根据需要选择是否一起转发,不影响api的分流逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 13:15:04