在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
相关产品推荐
相关产品推荐

