
简介面向AMS流媒体平台的Web安装包供运维人员或开发者在Linux服务器上快速搭建AMS Web管理界面同时解决新版环境下的兼容性与FLV直播播放问题。压缩包共4个文件分别提供txt说明文档、tgz程序数据包、SQL数据库脚本和sh自动化安装脚本整体大小54.12MB其中sql脚本用于初始化数据库tgz内含程序与静态资源sh脚本实现自动化安装借助说明文档可快速核对环境要求减少手工配置带来的差错覆盖从数据库初始化、文件上传管理到Web服务启动的完整流程。该版本重点更新了上传文件管理能力并调整了频道发布状态与设置的联动逻辑同时增强FLV播放器的兼容表现适用于需要迁移、升级或自建AMS Web环境的场景尤其适合已有基础流媒体服务概念、希望快速验证与部署的用户。资源目前已吸引293人学习下载是一份可直接用于生产环境的AMS Web端安装方案无论用于内网部署还是外网访问都能获得完整落地支持。 如果你看到web-setup-20250617-033035这种命名大概率会以为只是某个自动化脚本随机生成的临时目录。其实这是我给一套完整的 Web 项目搭建流程起的任务编号2025 年 6 月 17 日凌晨 3 点 30 分我把一个内部工具从“手动搭环境”改成了“一个安装程序完成全部配置”这个编号就是当时的构建记录。今天把这套流程里的关键环节拆开讲包括从 IDEA 创建 Web 项目、前端工程化、用 Inno Setup 制作安装包到服务器安全加固和 Selenium 自动化验证。适合所有想把 Web 项目从“能跑”变成“能交付”的开发者特别是准备做本地部署工具、离线安装包和规范化发布流程的朋友。1. 项目定位与整体设计思路1.1 标题背后是什么先说命名。web-setup-20250617-033035里web是模块类型setup表示环境初始化与安装包制作后面的时间戳是任务触发时间。这种命名方式在自动化运维里很常见价值在于可追溯哪天跑的、哪个模块、哪个版本一眼就能看出来。我当时做这件事的起因很简单团队交付一个 Web 系统用户直接访问服务器但有三类场景必须在用户本机运行离线演示、数据安全要求高的单机部署、以及临时交付给外部合作方试用。如果每次靠手动配 JDK、配 Tomcat、导数据库出错概率极高。所以我决定把整个搭建过程固化下来形成标准安装包和部署脚本。这个项目里我关心的不只是“Web 项目本身”而是从零到一整套交付物源码、构建脚本、安装包、安全基线、自动化冒烟测试。项目编号里的setup不是只指安装器它涵盖了环境准备、配置生成、依赖安装、包体和用户引导整个过程。1.2 技术选型为什么这么定技术栈选型的核心逻辑是“团队擅长什么 最终交付形态是什么”。最终交付形态是 Windows 安装包里面要内嵌一个 Web 服务所以后端选了 Java Spring Boot因为它自带内嵌 Tomcat打成一个 jar 就能跑再用 WinSW 或 NSSM 注册成 Windows 服务非常顺。前端选了 Vue 3 Element Plus组件生态成熟构建产物直接放进 Spring Boot 的static目录避免前后端分离带来的跨域和部署额外成本。如果只是个人记账系统或内部小工具用 Flask 完全够用省去大量配置。但企业级 Web 开发要考虑权限、审计日志、复杂报表、高并发Java 生态的成熟度和团队熟悉度更有优势。选型时也要考虑安装包权限Spring Boot 的内嵌 Tomcat 对端口和资源的管理更可控Inno Setup 只需要负责文件复制、服务注册和卸载复杂度反而更低。2. 从零初始化 Web 项目2.1 IDEA 2024 创建 Web 项目的关键配置我用的是 IntelliJ IDEA 2024.1和旧版本相比创建 Web 项目的入口变化比较大。打开New Project左侧选择Jakarta EE注意不是旧版的Java Enterprise。Project SDK 选 JDK 17Application Server 选本地安装的 Tomcat 10.1勾选Web Profile。这里有个关键点IDEA 2024 默认生成的是 Gradle 项目如果团队习惯 Maven可以在右侧选择Maven再生成避免后面手动改目录结构。创建完成后新版项目默认没有web.xml如果你使用的是 Servlet 5直接用WebServlet注解就能注册 Servlet不一定需要 web.xml。但如果你沿用旧项目习惯想手动添加可以在src/main/webapp/WEB-INF下创建。另一个坑是包名冲突Tomcat 10 之后命名空间从javax.*改成了jakarta.*如果用旧教程写javax.servlet会发现编译报错。创建完项目后第一件事不是写代码而是先把 Maven/Gradle 仓库设置为国内镜像否则拉依赖会很痛苦这一步能省掉后面大量等待时间。IDEA 里还需要配置好 Tomcat 的 artifact 部署方式。在Run/Debug Configurations里新增 Tomcat Server选择Deployment标签页把 war exploded 添加进去并在Server标签页里设置On frame deactivation为Update resources这样改前端静态文件不用重启服务就能看到效果。我用这个配置跑了很久比每次重启省太多时间。2.2 前端工程初始化与依赖管理前端我用了npm create vuelatest脚手架勾选了 Vue Router 和 Pinia。新版 Vue 3 项目中我强烈建议直接使用script setup写法它省去了export default和重复的setup()返回语句组件代码更短性能也不受影响。比如一个简单计数器组件用script setup只需要定义响应式变量和函数模板里直接用不用return。依赖管理工具我一开始用 pnpm因为它在多项目下省磁盘空间。但实际执行pnpm install时在 Windows 环境里遇到过符号链接失败的问题表现为安装过程卡住不动后来发现是杀毒软件实时扫描拦截了 pnpm 创建的链接文件。这类问题不只是 pnpm 有npm 在部分环境也有但 pnpm 更明显。解决方法很直接把项目目录加入杀毒软件白名单或者临时改用npm install。千万不要盲目反复删除node_modules那是治标不治本。之前跑某工具时出现过pnpm dsh web卡在安装阶段的状况排查到最后也是这个原因。前端构建产物的目录结构也需要提前约定好。我当时的做法是让 Vue 构建输出到../src/main/resources/static这样 Spring Boot 打包时直接带上前端资源由一个端口统一输出省去 Nginx 转发。不过要注意刷新路由时 Spring Boot 默认可能返回 404需要在后端加一个server.servlet.session.timeout之外的转发规则把非 API 路径转发到index.html否则前端路由一刷新就白屏。3. 用 Inno Setup 做安装包和本地分发3.1 为什么 Web 项目也要做安装包先回答一个疑问Web 项目不是部署在服务器上就行吗为什么还要做安装包做安装包不是让 Web 应用失去在线访问能力而是解决“桌面化交付”的场景。比如把 Web 服务做成 Windows 本地应用用户双击安装自动启动服务浏览器打开localhost:8080就能用。这对不懂技术的用户最友好也便于卸载时清理干净。Inno Setup 6 是我用过最顺手的免费安装包工具。它脚本语言简单支持 Unicode中英文界面切换容易还支持自定义安装流程。对比 NSIS 和 WiXInno Setup 的上手成本最低文档丰富社区里遇到问题基本都能搜到答案。最关键的是它可以直接嵌入自定义代码段实现“让用户选择任意路径然后把文件夹复制过去”这种定制需求。3.2 自定义路径选择和自动复制文件夹这是热词里提到的一个很实际的需求安装页面里让用户选择一个自定义路径安装程序自动复制某个文件夹到这个路径。在 Inno Setup 里可以用CreateInputDirPage创建一个输入目录页然后在CurStepChanged事件里执行复制逻辑。下面是我项目里的一段精简脚本[Setup] AppNameMyWebApp AppVersion1.0.0 DefaultDirName{autopf}\MyWebApp OutputDiroutput [Code] var DataDirPage: TInputDirWizardPage; procedure InitializeWizard; begin DataDirPage : CreateInputDirPage( wpSelectDir, 选择数据目录, 请选择Web服务需要使用的数据文件夹, 数据目录将用于存放上传文件和数据库文件, False, ); DataDirPage.Add(); end; procedure CurStepChanged(CurStep: TSetupStep); begin if CurStep ssInstall then begin if DirExists(DataDirPage.Values[0]) then FileCopy( ExpandConstant({app}\default_data\*), DataDirPage.Values[0] \, False); end; end;注意这里的FileCopy只能复制单个文件不能直接复制整个目录。如果需要递归复制建议预先在[Files]段用变量控制或者写一个递归函数。另一个更稳妥的方案是在[Tasks]里加一个“创建数据目录”的复选框用户勾选后再执行复制不勾选就用默认路径。不要去读取注册表或系统目录来猜测用户意图直接让用户选逻辑最简单也最不容易出错。3.3 中文界面配置Inno Setup 的英文界面直接用没问题但给国内用户用还是中文界面更友好。Inno Setup 6 官方提供了简体中文语言文件ChineseSimplified.isl你可以在脚本里这么写[Languages] Name: default; MessagesFile: compiler:Default.isl Name: chinesesimp; MessagesFile: compiler:Languages\ChineseSimplified.isl如果你想让安装程序启动时默认就是中文而不是让用户手动选择可以在[Setup]里加[Setup] LanguageDetectionMethodlocale或者更直接一点用命令行指定语言Setup.exe /LANGchinesesimp中文字体方面默认字体在某些旧 Windows 上会显示为方框建议在[Setup]里设置[Setup] DefaultDialogFontNameMicrosoft YaHei DefaultSelectedFontNameMicrosoft YaHei另外脚本文件本身要保存为 UTF-8 with BOM否则中文字符串在编译时可能变成乱码。我早期在这个上面卡过很久编译出来的安装包标题全是问号后来统一用 UTF-8 编码保存就解决了。4. 部署安全与常用功能落地4.1 Web 服务器安全加固的基本操作安装包交付安全是很多人会忽略的一环。Web 服务如果只在内网跑安全意识也不能放松因为内网同样有横向扫描和漏洞利用。我在这套项目里做了几个基础加固一是关闭服务器版本号Spring Boot 中配置server.server-header不返回具体版本。二是禁用目录列表防止访问/static/下资源时看到文件树。三是在响应头中添加X-Frame-Options: DENY、Content-Security-Policy: default-src self减少页面注入风险。如果是走 Nginx 反向代理可以隐藏 Nginx 版本号并限制管理接口只允许内网 IP 访问。用ensp模拟配置防火墙时我会对web管理页面单独设置访问控制策略原则是一样的管理端口不暴露公网Web 应用服务只开放必要的端口。还有一点很重要交付前用 Acunetix 或 OWASP ZAP 做一次漏洞扫描重点看 SQL 注入、XSS 和未授权访问。CTF 里找 flag 的思路用在这里很合适你扫到了一个可疑参数就要像追 flag 一样去追它的参数污染链直到确认漏洞是否存在。漏洞扫描报告不要求零漏洞但高危项必须在交付前修复。4.2 文件下载与 PDF 打印的落地写法热词里有个问题很常见Web 下载如何不下载到内存而是直接下载到本地。这个问题的坑在于前端到底做了什么事。如果前端用fetch拿到blob再触发下载小文件没问题大文件会直接占满内存甚至浏览器崩溃。正确的做法是后端把文件以流式响应返回前端直接用一个a标签指向文件 URL不经过fetch。Java 项目里可以用ResponseEntityResource或StreamingResponseBody实现流式下载下面是常用写法GetMapping(/download) public ResponseEntityStreamingResponseBody download(HttpServletResponse response) { response.setContentType(application/octet-stream); response.setHeader(Content-Disposition, attachment; filename\report.pdf\); StreamingResponseBody body out - { try (InputStream is new FileInputStream(filePath)) { is.transferTo(out); } }; return ResponseEntity.ok(body); }前端只用window.location.href /download或者a href/download就能触发下载浏览器会直接流式写盘不会在内存里堆积。如果是前端生成 PDF 文件html2canvasjspdf适合小的报表但复杂页面会失真。更稳的方案是用浏览器自带的打印写一个打印按钮调用window.print()结合media print样式控制打印区域。如果需要在服务端批量生成 PDF推荐用 Puppeteer 渲染一个 HTML 模板再导出 PDF效果和浏览器打印一致且不依赖客户端的打印设置。5. 自动化验证与问题排查实录5.1 Selenium 浏览器驱动的选型逻辑自动化测试是交付前最后一道防线。Selenium 本身是跨浏览器的但驱动选错是新手最容易踩的坑。判断下载哪个驱动原则只有一个驱动的主版本号必须和浏览器的主版本号完全一致。比如你的 Chrome 版本是114.0.5735.90就下载114.x的 chromedriver而不是下最新的122.x。Chrome、Firefox、Edge 三者的驱动不一样Chrome 对应 chromedriverFirefox 对应 geckodriverEdge 对应 msedgedriver。用错驱动启动时大概率报SessionNotCreatedException。如果你不想手动去版本号匹配和下载就直接引入 WebDriverManagerWebDriverManager.chromedriver().setup(); WebDriver driver new ChromeDriver();它会自动读取当前浏览器版本并下载匹配的驱动。不过 WebDriverManager 也需要联网如果最终离线环境跑自动化还是要在 CI 上提前把所有驱动版本准备好。驱动放哪个目录也容易出问题。Windows 下不一定非要放到 System32放到项目里然后通过System.setProperty(webdriver.chrome.driver, 路径)指定更可控。注意驱动文件需要被防火墙和杀毒软件放行否则启动时会被异常结束。5.2 实操中踩过的坑和排查方法这套流程跑下来问题集中在几个地方。我整理了一个速查表方便复用现象可能原因解决办法安装后访问localhost:8080无反应服务未被启动或端口被占用检查 Windows 服务列表改用netstat -ano查找占用端口的进程Vue 路由刷新 404前后端路由未做 fallback后端写一个转发非 API 路径到index.html的 Controller安装包被杀毒软件误报Inno Setup 默认安装行为被识别为敏感取消不必要的注册表写入代码签名添加厂商白名单Selenium 启动时浏览器秒退驱动版本不匹配或浏览器沙箱受限核对版本加--no-sandbox参数仅限测试环境下载大文件时浏览器卡死前端用了 fetch blob换成原生链接下载或后端用流式响应Spring Boot 启动但 Tomcat 报端口被占用残留 Java 进程用taskkill /F /PID清理或者改用随机端口排查思路比技巧更重要。我的做法是先看服务状态和日志再看端口和网络最后才看代码。如果日志没有明确报错把所有变量先归零停掉其他服务、清空缓存、换默认端口再逐步恢复。这就像 CTF 里找 flag不要凭感觉翻来翻去而是一层层缩小范围直到锁定唯一的异常点。我这次把安装包和自动化测试打通后整个交付流程稳定了很多后续再改功能只需要跑一遍安装、启动、冒烟几分钟就能确认有没有破坏性回归。我现在个人体会比较深的一点是项目命名里带时间戳看着不起眼但配合自动化流程后每次构建结果都留痕排查问题能直接定位到具体版本和环境比自己瞎猜“上次改了什么”高效太多。如果你也在做 Web 项目交付建议从最简单的安装包和自动化冒烟开始哪怕只覆盖登录、下载、打印三个核心操作也能避免大量低级错误。本文还有配套的精品资源点击获取