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

在SpringBoot中部署多Angular应用,解决页面刷新404问题

解决多Angular应用部署Spring Boot的子路由刷新问题及替代部署方案

一、修复当前子路由刷新404及无限循环问题

1. 先确保Angular构建配置正确

每个Angular应用的angular.json中,build配置需指定baseHref和deployUrl,确保资源路径指向正确子路径:

"projects": {
  "app1": {
    "architect": {
      "build": {
        "options": {
          "baseHref": "/app1/",
          "deployUrl": "/app1/",
          "outputPath": "dist/apps/app1"
          // 其他配置...
        }
      }
    }
  },
  "app2": {
    "architect": {
      "build": {
        "options": {
          "baseHref": "/app2/",
          "deployUrl": "/app2/",
          "outputPath": "dist/apps/app2"
          // 其他配置...
        }
      }
    }
  }
}

构建完成后,将dist/apps下的内容复制到Spring Boot的classpath:/static/apps/目录。

2. 方案一:修改FrontEndRoutingController,区分静态资源与路由请求

通过判断请求路径是否包含静态资源扩展名,避免转发静态资源请求导致的无限循环:

@Controller
public class FrontEndRoutingController {

    private static final List<String> STATIC_EXTENSIONS = Arrays.asList(
        ".js", ".css", ".html", ".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg"
    );

    @GetMapping("/app1/**")
    public String handleApp1(HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        // 静态资源直接放行,由Spring默认资源处理器处理
        if (STATIC_EXTENSIONS.stream().anyMatch(requestUri::endsWith)) {
            return null;
        }
        // 路由请求转发到对应应用的index.html
        return "forward:/app1/index.html";
    }

    @GetMapping("/app2/**")
    public String handleApp2(HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        if (STATIC_EXTENSIONS.stream().anyMatch(requestUri::endsWith)) {
            return null;
        }
        return "forward:/app2/index.html";
    }
}

3. 方案二:使用WebMvcConfigurer统一配置(无需额外控制器)

通过配置资源处理器映射静态资源,再用视图控制器转发路由请求,利用Spring的匹配优先级避免循环:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 映射app1静态资源路径
        registry.addResourceHandler("/app1/**")
                .addResourceLocations("classpath:/static/apps/app1/");
        // 映射app2静态资源路径
        registry.addResourceHandler("/app2/**")
                .addResourceLocations("classpath:/static/apps/app2/");
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 处理app1的路由请求,转发到index.html
        registry.addViewController("/app1/**")
                .setViewName("forward:/app1/index.html")
                .setCacheSeconds(0);
        // 处理app2的路由请求
        registry.addViewController("/app2/**")
                .setViewName("forward:/app2/index.html")
                .setCacheSeconds(0);
    }
}

注:Spring会优先处理资源处理器的匹配,静态资源不会被视图控制器转发,自然避免无限循环。

二、多Angular应用的其他部署方案

1. Nginx反向代理+前后端分离部署

将每个Angular应用独立构建后,部署到Nginx的对应目录,配置Nginx路由:

server {
    listen 80;
    server_name localhost;

    # 处理app1的路由
    location /app1/ {
        root /usr/share/nginx/html/dist/apps;
        try_files $uri $uri/ /app1/index.html;
    }

    # 处理app2的路由
    location /app2/ {
        root /usr/share/nginx/html/dist/apps;
        try_files $uri $uri/ /app2/index.html;
    }

    # 转发API请求到Spring Boot
    location /api/ {
        proxy_pass http://localhost:8080/api/;
        proxy_set_header Host $host;
    }
}

这种方式前后端解耦,Angular应用和Spring Boot可独立扩容、部署。

2. Nx Module Federation微前端架构

利用Nx的Module Federation功能,将多个Angular应用作为远程模块,通过一个宿主应用统一管理路由:

  • 配置宿主应用的module-federation.config.js,引入远程应用;
  • 远程应用暴露组件或路由模块;
  • 部署时可选择将所有应用打包到一起部署到Spring Boot,或单独部署每个远程应用,通过宿主应用加载。

3. Spring Boot + Thymeleaf模板映射(适合简单场景)

将每个Angular应用的index.html改为Thymeleaf模板,放在classpath:/templates/apps/目录,配置视图解析器:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.thymeleaf()
                .prefix("classpath:/templates/apps/")
                .suffix(".html");
    }

    @GetMapping("/app1/**")
    public String app1Route() {
        return "app1/index";
    }

    @GetMapping("/app2/**")
    public String app2Route() {
        return "app2/index";
    }
}

同时将Angular构建后的静态资源放在classpath:/static/apps/目录,确保资源路径正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:27:38