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

Spring Boot+Angular单WAR部署Tomcat9 访问路由返回JSON异常

问题背景
  • 技术栈基于Spring Boot 2.6.6、Angular 6.1.0开发,目标是将前后端合并打包为单个WAR文件部署
  • 本地验证正常:Eclipse中以Spring Boot应用形式直接启动、单独启动Angular开发服务时,配置上下文路径后全流程运行无异常
  • 异常触发场景:将构建生成的WAR包部署到Tomcat 9.0.30容器后,应用加载出现两类异常
    1. 访问URL localhost:8080/Demo/#/login 时,浏览器未加载预期的登录页面,直接返回Spring Data REST接口索引JSON,示例内容如下:
{
    "_links": {
        "users": {
            "href": "http://localhost:8080/Demo/index.html/users{?page,size,sort}",
            "templated": true
        },
        "country": {
            "href": "http://localhost:8080/Demo/index.html/country{?page,size,sort}",
            "templated": true
        }
    }
}
  1. 直接访问 localhost:8080/Demo/index.html 时可以正常加载前端UI,但刷新页面后URL会自动变为localhost:8080/Demo/#/login,页面随即再次返回上述JSON内容,应用无法正常使用。
问题根因
  • Angular构建时的base href配置错误,和Tomcat部署的上下文路径不匹配,导致路径拼接时把index.html当成了路径层级,从返回JSON里的href字段也能看到这个问题
  • Spring MVC的请求映射优先级设置不当,Spring Data REST的默认根路径处理器优先级高于静态资源映射,根路径请求被后端接口拦截,没有返回前端入口文件
  • 前后端接口路径没有做明确前缀隔离,静态资源请求和后端接口请求出现路径冲突
  • WAR包打包配置不符合外部Tomcat部署要求,静态资源存放位置或启动类配置有误
修复方案

1. 调整Angular构建配置

修改Angular项目src/index.html中的base标签,和部署上下文路径保持一致:

<!-- *注意:路径末尾必须加斜杠,否则静态资源路径拼接会出错* -->
<base href="/Demo/">

也可以直接在构建命令中指定base路径,避免手动修改漏改:

ng build --prod --base-href=/Demo/

构建完成后,将Angular打包输出的dist目录下所有文件,全部复制到Spring Boot项目的src/main/resources/static/目录下,确保index.html直接位于static目录根层级。

2. 修正Spring Boot配置

首先在application.yml中正确配置上下文路径和静态资源映射规则:

server:
  servlet:
    context-path: /Demo
spring:
  mvc:
    static-path-pattern: /**
  web:
    resources:
      static-locations: classpath:/static/

新增WebMVC配置类,将非接口路径的请求统一转发到前端index.html,避免被后端处理器拦截:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class FrontendRouteConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 匹配所有非接口层级的路径,统一转发到前端入口
        registry.addViewController("/{path:[\\w\\-]+}")
                .setViewName("forward:/index.html");
        registry.addViewController("/{prefix:^(?!api$).*$}/**/{path:[\\w\\-]+}")
                .setViewName("forward:/index.html");
    }
}

如果项目引入了Spring Data REST,单独给数据接口配置统一前缀,和前端路径彻底隔离,避免冲突:

import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;

@Configuration
public class RestRepositoryConfig implements RepositoryRestConfigurer {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
        // 所有Spring Data REST接口统一走/api前缀
        config.setBasePath("/api");
    }
}

3. 修正WAR包部署配置

确保Spring Boot启动类继承SpringBootServletInitializer,适配外部Tomcat容器启动逻辑:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DemoApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

调整pom.xml打包配置,设置打包方式为war,同时将内置Tomcat依赖设置为provided范围,避免和外部Tomcat的jar包冲突:

<packaging>war</packaging>

<dependencies>
    <!-- 其余业务依赖保持不变 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

按以上配置重新构建WAR包部署后,路径冲突问题会完全解决,前端路由、后端接口均可正常访问。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 08:06:31