欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 下集:一条打包到底的静态部署之路

下集:一条打包到底的静态部署之路

2025/5/19 3:42:59 来源:https://blog.csdn.net/m0_37609579/article/details/148030809  浏览:    关键词:下集:一条打包到底的静态部署之路

在这里插入图片描述

说完坑,再来讲正经操作。

这次我决定写得明明白白,清清楚楚,把那条“Spring Boot 扛着 Next.js 上线”的路子掰碎了揉细了告诉你。

无废话、无迷信、无AI幻觉。

第一步:Next.js 静态导出

项目根目录下的 next.config.js 要写得很清楚,不要留一丝幻想:

/** @type {import('next').NextConfig} */
const nextConfig = {output: 'export',           // 重点!导出为纯静态trailingSlash: true,       // 每个路径带斜杠,方便生成 index.htmlimages: {unoptimized: true        // 否则图片优化会报错},
};module.exports = nextConfig;

然后直接命令:

npm run build
npx next export

这时候,会生成一个 out/ 文件夹,里面是你真正能用来部署的东西。

结构大概长这样:

out/
├── admin/
│   └── login/
│       └── index.html
├── register/
│   └── index.html
├── index.html
├── _next/static/chunks/...js
└── ...

注意,每个页面其实就是一个路径+index.html 文件结构,所以根本不用搞什么“SPA跳转”那一套逻辑!

第二步:复制到Spring Boot资源目录

假设你后端目录结构是标准的:

backend/
└── src/└── main/└── resources/└── static/

那么执行这条命令:

cp -r out/* ../backend/src/main/resources/static/

清空 static 目录再复制比较稳妥。

第三步:配置 Security —— 非 /api/** 一律放行

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.cors(cors -> cors.configurationSource(corsConfigurationSource())).csrf(AbstractHttpConfigurer::disable).sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).authorizeHttpRequests(auth -> auth.requestMatchers("/api/admin/**").hasRole("ADMIN").requestMatchers("/api/**").authenticated().anyRequest().permitAll()).authenticationProvider(authenticationProvider()).addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);return http.build();
}

千万不要用 .anyRequest().authenticated(),那是开发环境用来封杀一切的,不适合你现在这个"一切靠静态"的部署场景。

第四步:配置 WebConfig —— 精准转发到 index.html

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/**").addResourceLocations("classpath:/static/").resourceChain(true).addResolver(new PathResourceResolver() {@Overrideprotected Resource getResource(String resourcePath, Resource location) throws IOException {Resource requested = location.createRelative(resourcePath);if (requested.exists() && requested.isReadable()) {return requested;}// 对于非静态资源请求,尝试回退到 index.htmlif (resourcePath.contains(".")) {return null; // 明确要请求静态资源的,找不到就报404}if (resourcePath.startsWith("api/")) {return null; // 让Controller处理}return new ClassPathResource("/static/index.html");}});}
}

这个配置非常关键。它做到了:

  • 能访问的静态资源直接返回
  • 明确的 API 请求让 controller 去处理
  • 只有“没有扩展名”的页面路径,比如 /admin/login,才回退到 index.html

AI 给你那种“全都 forward 到 index.html” 的 Controller 方案,在这个结构下是没必要、也极其危险的。会白屏、跳错页,还极难调试。

第五步:打包运行!

用 Maven 构建:

mvn clean package -DskipTests

运行:

java -jar target/backend-0.0.1-SNAPSHOT.jar

然后你可以打开:http://localhost:8082/

  • / 首页会显示出来
  • /admin/login 会跳转到你静态导出的 admin/login/index.html
  • /register/?token=abc123 会正确加载 register 页并保留查询参数
  • /api/** 接口仍然走后端 Controller,毫无冲突

最终效果:

你得到了一个:

  • 单一jar包即可部署
  • 不需要Node环境
  • 支持多页访问和刷新
  • 前后端分工明确但部署合体
  • 操作简明、老板无感知的系统

结语:这条路走通了,我回头一看

  • AI教的套路,不一定错,但常常不适合你这种“野路子结合小团队现状”的打法
  • 静态部署这条线,只要搞清楚目录结构和路径映射,真的比你想的简单
  • Spring Boot 其实是个好平台,只要你别逼它理解前端的世界

这次,我们用文件系统打败了抽象逻辑。

前端静态导出 + 后端反向代理 + 安全放行策略,这三板斧下去,小项目不管你多么前后端分离,最终都能“一锅端”。

别再迷信什么服务拆分了,小项目,能合就合。

回头再看那些鼓吹“必须前后端分离”的架构课件……我只想笑着对他们说一句:

“你把前端扔进static再说这话。”

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词