简介JavaEE SDK 7u3 是一套面向 Windows 7 环境的企业级 Java 开发套件主要服务于需要在旧操作系统上构建、测试和部署企业应用的开发者能够提供稳定可靠的底层运行与编译环境。该版本以 Glassfish 4.0 作为 Java EE 7 参考实现涵盖 Web 服务、事务处理、数据库连接、消息传递等标准服务并引入 WebSocket、CDI 等较新特性可配合 NetBeans IDE 的代码自动完成与调试工具进行高效开发。压缩包大小约一百二十六兆字节内含整套 SDK 组件与应用服务器相关文件适合遗留项目维护或对特定版本存在硬性依赖的团队选用。目前已有三百三十一人学习下载说明这一老版本在兼容性场景下仍具备实际参考价值。对于希望获得稳定开发环境、又暂时无法升级到新版的企业开发者这份套件能直接支撑起日常开发、测试与部署工作减少环境迁移带来的成本。 我的博客结构设计大致如下1. javaeesdk 7u3 不是考古是一台还在转的老发动机引入无子标题2. 拆开 7u3 的包SDK 里有什么为什么选它而不是单下 Web Profile2.1 参考实现SDK 的核心才是“标准答案”2.2 解压安装与第一个 domain从压缩包到管理控制台3. 把 7u3 接进日常开发命令行、环境变量与 Maven 坐标3.1 asadmin 管理命令与连接参数先让脚本跑通3.2 构建工具与 IDE从 Maven 坐标到自动部署4. 部署路径把一个 WAR 落到 7u3 的 domain 上4.1 最小 WAR 部署asadmin 部署命令与常用参数4.2 连接池与 JNDI 数据源让应用真正连上数据库5. 7u3 排查手册旧 SDK 撞上新环境的 5 个典型坑5.1 高版本 JDK 下启动失败模块系统与反射调用冲突5.2 改了内存参数却不生效set 命令与 domain.xml 的优先级5.3 HTTPS 握手失败TLS 协议版本和证书链过期5.4 端口被占与 domain 锁第二个实例怎么都起不来5.5 中文乱码从请求到数据库的完整链路6. 让 7u3 少闹腾启动参数、systemd 托管与备份习惯最后一章落到具体技巧上包含表格收尾用第一人称习惯希望帮到你现在开始写具体内容。我需要确保每个中间章节至少有1800字。由于中文一行约等于一个字符宽度的问题我数一下大概作者经验法在简体中文字渲染里每行约20-25个字符带宽度4-6行约80-150字。所以每段应该80-150字。我的内容需要比较充实。我预计合理成稿时总体在8000-9000字左右。写完的过程我需要注意语言的自然和可读性。避免it语言里的翻译腔。我现在准备写草稿。由于体量很大我会分段写。第2章细节要点Java EE 7 标准 参考实现概念Full Platform vs Web Profile 选择SDK 包内容bin、domains、docs、samples解压安装步骤 环境变量 启动 验证Windows/Linux 差异注意第3章细节要点asadmin 常用命令体系--passwordfile 和远程管理Maven 坐标 javax:javaee-api:7.0 providedIDE命令替代方案autodeploy 目录原理编译级别注意事项第4章细节要点mvn packageasadmin deploy 参数list-applications 验证从日志看部署错误创建连接池、JNDI 资源ping 验证驱动放置和常见错误第5章细节要点JDK 版本问题内存参数失效HTTPS 证书问题端口冲突中文乱码注意第5章标题是“7u3 排查手册旧 SDK 撞上新环境的 5 个典型坑”包含“排查”安全符合要求。第6章细节要点JVM 参数整理建议表systemd 托管备份清单表迁移习惯我需要不太使用特殊键词比如“稳定”字眼尽可能多用而不是“墙”等……注意没有风险。有一个风险在正文中我提到“mx”内存设置多少合适。我会给建议而不是精确程序化数值。好动手写全文。整个写作我仔细计算字数不是必要的但要保持在7000-12000字。我会把中间章内容写厚。写作时注意代码块后跟逻辑说明和参数说明不要写“本文”等字眼直接叙述避免禁用词每章暗中尽量有连接词“我一般会”“常见做法是”最后一章收尾“希望帮到你”开始动手。 ## 1. javaeesdk 7u3 不是考古是一台还在转的老发动机javaeesdk 7u3 全称 Java EE 7 SDK Update 3核心是连同参考实现 GlassFish 4.0 一起打包的一套完整 SDK。它跟 JDK 的 7u3 不是一回事很多刚接手老系统的开发看到这个标题就默认要配 JDK 7结果在启动阶段就翻了车。作为一套具体的 Java EE 7 发行版它的意义不是新而是“标准”老项目当年基于它开发今天改不动也绕不开。现在还频繁遇到它的场景主要有两种一是遗留系统要迁移服务器、换 JDK、补证书必须先把这套旧环境摸透二是新项目要和老系统联调接口行为必须以它的兼容性为准。无论哪种场景你需要的都不是科普而是一套能照着做的判断标准和操作流程。这篇笔记按接手老环境的顺序展开拆开 SDK 看内部组成把命令行和环境变量跑通完成一次真实部署再逐个排查旧版本最容易踩的坑最后落到让服务少出问题的收尾习惯上。适合开发、运维以及准备规划迁移方案的人。2. 拆开 7u3 的包SDK 里有什么为什么选它而不是单下 Web Profile2.1 参考实现SDK 的核心才是“标准答案”Java EE 7 是一组规范定义了 Servlet、EJB、JPA、JAX-RS、JMS 等接口但规范本身不附带可运行的程序。SDK 把这组规范连同实现一起交付其中捆绑的参考实现就是 GlassFish 4.0。参考实现的价值在于当规范文本有歧义比如某个注解在整个部署链路中究竟由谁解析参考实现的行为就代表规范的标准答案。对维护老系统的人来讲这套“标准答案”可以直接当排错依据。同一个TransactionAttribute在不同容器里行为不同别的商用服务器可能做了一些扩展GlassFish 4.0 更贴近规范原文所以排查时拿它做参照能快速确认是哪一层的实现偏差。遇到和 EJB 事务、JMS 消息、JPA 二级缓存相关的诡异现象先在 7u3 上复现一遍能过滤掉大量“假 bug”。选型上区分 Full Platform 和 Web Profile 是关键。项目里只用 Servlet/JSP、静态资源、REST 接口Web Profile 够用一旦涉及 EJB、JMS、JTA 分布式事务、定时调度就必须 Full Platform。判断老项目是否被 Web Profile 覆盖最快的方法是看依赖清单里有没有javax.ejb、javax.jms、javax.batch这样的包名。凡是出现这些直接上完整版 SDK 7u3别为省那一点磁盘空间给自己留隐患。2.2 解压安装与第一个 domain从压缩包到管理控制台SDK 7u3 的安装形态就是一个压缩包没有图形安装向导。拿到包之后解压即用但路径规划要做在前面。我一般会建一个不带版本号的软链接这样以后升级 SDK 时只换链接指向不用改脚本里的路径。# 把 SDK 压缩包放到 /opt 下指定目录解压 mkdir -p /opt/javaee unzip javaee-sdk-7u3.zip -d /opt/javaee # 解压后根目录通常是 glassfish4建立软链接方便引用 ln -s /opt/javaee/glassfish4 /opt/glassfish # 看一下解压出的顶层目录确认 bin、glassfish、docs 等都在 find /opt/glassfish -maxdepth 2 -type d | head -30unzip -d指定释放目标目录避免 zip 包把文件散落在当前目录。软链接指向glassfish4后续所有脚本里写/opt/glassfish即可版本号不会侵入配置。find查看目录层级目的是确认解压完整如果 bin 目录缺失说明包没解全后边所有命令都会失败。接下来配置环境变量。SDK 7u3 官方对应的 JDK 版本是 7 和 8但实际维护中我强烈建议用 JDK 8。JDK 7 太老很多 TLS 协议和新工具链已经不支持JDK 9 以后模块化改动又会让 GlassFish 启动报错。所以 JDK 8 是这个版本的最优解。# 以 JDK 8 为例注意 JAVA_HOME 指向 JDK 目录不要指到 JRE export JAVA_HOME/usr/local/java/jdk1.8.0_x64 export GLASSFISH_HOME/opt/glassfish export PATH$GLASSFISH_HOME/bin:$JAVA_HOME/bin:$PATH # 验证版本号能正常读出 asadmin versionJAVA_HOME指向 JDK 根目录不是bin目录也不是 JRE 安装目录否则asadmin找不到编译器和部分工具。GLASSFISH_HOME指向软链接路径asadmin version能返回类似 GlassFish 4.0 的版本信息。如果这里直接报错九成是环境变量写错或bin目录没有执行权限先排查这两点再往下走。启动默认 domain 并验证服务# 启动默认域 domain1监听端口默认是 4848管理和 8080HTTP asadmin start-domain # 列出当前存在的所有域及状态 asadmin list-domainsstart-domain不带参数时启动默认域日志输出到$GLASSFISH_HOME/glassfish/domains/domain1/logs/server.log。启动完成后浏览器访问http://localhost:4848能看到管理控制台访问http://localhost:8080能看到默认欢迎页面。这两个页面任何一个打不开先回头看日志不要盲目改端口。在 Windows 上解压时注意路径不要带空格zip 包内长路径也可能导致解压失败建议解压到D:\sdk\glassfish4这类短路径下再手动创建目录引用。Linux 下基本没这个问题但要注意/opt目录的写权限普通用户安装时经常会卡在创建 domain 这一步。3. 把 7u3 接进日常开发命令行、环境变量与 Maven 坐标3.1 asadmin 管理命令与连接参数先让脚本跑通GlassFish 的管理有图形控制台和命令行两套入口。图形控制台适合偶尔点两下的场景一旦要反复部署、批量操作还是命令行可靠。原因很简单命令行操作可以被脚本记录、被自动化任务复用还能避免在图形界面里手滑点错配置。asadmin 最常用的是一组 domain 生命周期命令它们是整个维护工作的基石# 停止指定域不写域名的默认操作是 domain1 asadmin stop-domain domain1 # 重启指定域适合修改配置后快速生效 asadmin restart-domain domain1 # 列出已部署的应用确认当前线上运行的是什么 asadmin list-applicationslist-applications在排查问题时非常好用它会显示应用名称、类型和当前状态。如果某次部署后应用没起来先跑这条命令看状态是enabled还是disabled再决定是调整配置还是直接查日志。远程管理时需要在 asadmin 命令后指定目标主机、端口和管理员账号# 用一个密码文件免交互登录适合放进自动化脚本 asadmin --host 192.168.10.20 --port 4848 \ --user admin \ --passwordfile /opt/secret/admin.pwd \ list-applications参数含义--host是目标机器 IP--port是管理端口--user是管理员账号--passwordfile指向明文密码文件文件第一行写AS_ADMIN_PASSWORD密码。注意密码文件的权限必须收紧否则相当于把管理密码贴在门上。刚接触这套命令的人最容易踩的坑是在本地启动了一个 domain然后用--host指向另一台机器发现连不上。这不是命令写错了而是目标机器的enable-secure-admin没开启或者防火墙把 4848 端口挡了。排查顺序是先在本机用asadmin list-domains确认域名和端口再检查目标机器的管理服务状态最后看防火墙策略。3.2 构建工具与 IDE从 Maven 坐标到自动部署Java EE 7 项目编译时依赖的是标准 API而不是 GlassFish 自带的实现类。Maven 里的依赖坐标很稳定关键是 scope 必须用provideddependency groupIdjavax/groupId artifactIdjavaee-api/artifactId version7.0/version scopeprovided/scope /dependencyprovided表示编译和测试时需要这个 API但打包进 WAR 时要排除掉。因为 GlassFish 启动时自己会加载同名实现类如果把 API 和实现一起打进去类加载器会面临两份同名ServletContext的冲突表现就是部署时一堆NoClassDefFoundError和ClassCastException。这是新手最常犯的错误也是 IDE 里编译通过、一部署就崩的常见原因。构建系统里要注意编译级别。我一般会把 Maven 编译器插件锁定在 JDK 8plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.8.1/version configuration source1.8/source target1.8/target /configuration /pluginsource和target都设为1.8保证生成的 class 文件版本能被老容器识别。如果本机 JDK 是 17但编译目标写成target17打包出的 class 文件 GlassFish 4.0 的类加载器根本读不进去启动时直接报UnsupportedClassVersionError。IDE 侧的接入相对简单。常见做法是在 IDE 里配置应用服务器路径和 domain 目录IDE 的部署按钮底层调用的仍然是 asadmin。配置时注意两点IDE 使用的 JDK 必须也是 8否则热部署会失败部署方式推荐选择“部署到管理域”而不是“复制到 autodeploy 目录”因为后者在 IDE 里无法及时反馈部署状态。实际开发中还有一条更省事的路径把构建产物往autodeploy目录里一丢GlassFish 会自动捡起来部署。这个目录默认在$GLASSFISH_HOME/glassfish/domains/domain1/autodeploy。它的机制是目录扫描每次有新文件写入就触发部署。好处是搬家式部署特别快坏处是手滑丢一个旧包进去就会误线上我一般只在本地测试环境用 autodeploy生产环境一律走 asadmin 命令。4. 部署路径把一个 WAR 落到 7u3 的 domain 上4.1 最小 WAR 部署asadmin 部署命令与常用参数部署一个 WAR 包本质上就是把文件复制到 domain 的应用目录然后让容器完成类加载、资源初始化、监听器启动这一串动作。手工复制不是不行但 asadmin 会顺带帮你处理依赖、上下文路径、状态回滚这些事所以老老实实用命令。先构建出 WAR 包再执行部署# 在项目根目录构建跳过测试以节省时间 mvn clean package -DskipTests # 部署到默认域指定应用名和上下文根 asadmin deploy --name demo --contextroot /demo --force target/demo-1.0.war # 部署后立即确认应用状态 asadmin list-applications--name指定部署后的应用名后续的更新、卸载、启停都靠这个名字--contextroot是访问路径浏览器通过http://localhost:8080/demo访问--force允许同名应用重复部署时直接替换避免每次都要先 undeploy 再 deploy。部署成功后在list-applications输出里能看到demo。如果部署后访问 404先看应用是否处于enabled状态再看上下文根是否拼写一致。还有一类隐蔽问题见多了本地打包时用 JDK 8部署到服务器时本机有JAVA_HOME指向 JDK 11GlassFish 启动时继承了错误环境。部署和运行的 JDK 必须一致Windows 上还经常出现服务注册表里残留旧 JAVA_HOME 的情况一重启就原形毕露。生产环境我一般不用--force而是先部署一个新版本名验证没问题后再切换流量。切换方式是部署时用相同的--contextroot让新应用先就绪然后通过asadmin undeploy摘掉旧版本。整个过程对调用方是无感的。4.2 连接池与 JNDI 数据源让应用真正连上数据库Java EE 老项目的数据库连接一般不走应用自己创建Connection的方式而是把连接池建在容器里应用通过 JNDI 名字去拿。这样做的原因有三个连接复用能省掉反复建连的耗时容器能统一管理连接泄漏和超时XA 分布式事务也必须依赖容器的资源管理。所以看到老的持久化配置里写jdbc/appdb那指的是 JNDI 资源不是数据库 URL。先看一下当前环境已有哪些资源# 列出连接池和 JNDI 资源 asadmin list-jdbc-connection-pools asadmin list-jdbc-resources没有现成资源时依次执行两步创建。下面以常见的 MySQL 数据库为例# 第一步创建物理连接池指定数据源实现类和数据库连接属性 asadmin create-jdbc-connection-pool \ --restype javax.sql.DataSource \ --datasourceclassname com.mysql.jdbc.Driver \ --property userappuser:passwordChangeMe0912:urljdbc:mysql://dbhost:3306/appdb?useUnicodetrue\characterEncodingUTF-8 \ appPool # 第二步创建 JNDI 资源把逻辑名绑定到连接池上 asadmin create-jdbc-resource --connectionpoolid appPool jdbc/appdb # 第三步检查连接池能不能真正连上数据库 asadmin ping-connection-pool appPool--datasourceclassname是驱动类全限定名这个类必须存在于 domain 的lib/ext目录下。常见做法是把驱动 jar 放进$GLASSFISH_HOME/glassfish/domains/domain1/lib/ext然后重启 domain。--property里用冒号分隔多项属性URL 中的在 Shell 里要用\转义否则会被当成后台执行符。ping-connection-pool返回成功说明从连接池到数据库的链路是通的。在这个操作里最容易翻车的是驱动类写错。MySQL 老驱动叫com.mysql.jdbc.Driver新驱动改成了com.mysql.cj.jdbc.Driver两个类名不一样放错任何一个都会报找不到类。排查思路是先用jar tf查看驱动 jar 里到底有哪些类再回填--datasourceclassname不能用猜的。还有一种情况连接池创建成功ping 也通但应用启动时还是报NamingException。这不是连接池的问题而是 JNDI 资源名没对上。老项目里persistence.xml写的jdbc/appdb和 asadmin 里创建的资源名一字不差才行大小写、斜杠都不能错。我一般会把 JNDI 资源名全部小写从源头上避开拼写差异。5. 7u3 排查手册旧 SDK 撞上新环境的 5 个典型坑5.1 高版本 JDK 下启动失败模块系统与反射调用冲突现象用 JDK 11 或 17 启动 domain日志里出现IllegalAccessError、NoClassDefFoundError异常堆栈指向java.sql、java.xml或javax.annotation相关类启动进程直接退出。原因JDK 9 开始引入模块系统把原本散落在各处的内部 API 做了封装老 GlassFish 用反射访问这些内部接口时被模块边界拦截。与此同时 Java EE 的 API 从 JDK 里被移除老容器找不到javax.*的运行时实现。解决我一般直接锁定 JDK 8不折腾--add-opens那一堆参数。老容器的兼容性列表就是按照 JDK 8 验证的换到新 JDK 后各种反射问题防不胜防。维护脚本里显式固定export JAVA_HOME/usr/local/java/jdk1.8.0_x64 /opt/glassfish/bin/asadmin restart-domain domain1JAVA_HOME在启动脚本和 domain.xml 里的配置要保持一致。如果两处不一致启动时走的 JDK 和配置文件里声明的完全不是同一个问题会被隐藏得很深。我的排查习惯是先跑asadmin version再看实际 Java 进程的启动命令确认进程真正用的是哪个 JDK。5.2 改了内存参数却不生效set 命令与 domain.xml 的优先级现象用asadmin create-jvm-options加了-Xmx1024m重启 domain 后查看进程参数值还是原来的 512m。或者启动时直接报Unrecognized VM option PermSize。原因SDK 7u3 对应的旧调优模板常写-XX:PermSize和-XX:MaxPermSize这两个参数在 JDK 8 里已经被元空间取代写了会被直接忽略甚至报错。另一个原因是create-jvm-options命令虽然执行成功但修改写进了 domain.xml 的java-config节点而进程真正读取的参数可能来自启动脚本或系统环境变量覆盖。解决最直观的方法是直接编辑 domain.xml而不是用命令一层层改# 先查看当前域生效的 JVM 参数 asadmin get domain1.java-config.jvm-options # 修改示例删除旧值后新增 asadmin delete-jvm-options -Xmx512m asadmin create-jvm-options -Xmx1024m:-XX:MaxMetaspaceSize256m # 重启后验证进程参数 asadmin restart-domain domain1create-jvm-options一次设置多个参数时用冒号分隔这个语法很容易写错。写错的时候不会立刻报错而是重启后只有前半段生效我一般直接改$GLASSFISH_HOME/glassfish/domains/domain1/config/domain.xml里的jvm-options标签改完再重启直观且不易出错。5.3 HTTPS 握手失败TLS 协议版本和证书链过期现象外部客户端访问https://端口默认 8181时握手失败浏览器提示连接不安全或直接拒绝但在服务器本地用curl又能通。原因老 SDK 默认密钥库里放的是若干年前生成的自签名证书有效期早就过了另外 JDK 8 之前的 TLS 协议协商能力偏弱新客户端默认要求 TLS 1.2老服务端如果只支持 TLS 1.0两边协商不上表现就是连接被重置。解决把证书换新TLS 版本尽量拉高。操作前先备份密钥库这是后悔药# 备份原有密钥库 cp keystore.jks keystore.jks.bak.$(date %Y%m%d) # 生成新的自签名密钥对alias 沿用默认的 s1as keytool -genkeypair -alias s1as -keyalg RSA -keysize 2048 \ -validity 3650 \ -keystore /opt/glassfish/glassfish/domains/domain1/config/keystore.jks \ -storepass changeit -keypass changeit \ -dname CNlocalhost, OUIT, OInternal, CCN-validity 3650表示证书有效期 3650 天约十年换一次能顶很久。-dname必须提供否则 keytool 交互式追问会把脚本卡住。执行完后重启 domain再用curl -v https://localhost:8181验证握手是否成功。证书换完后客户端需要重新信任这个自签证书。如果应用对接方没法手动导入证书那就得考虑内部 CA 签发或者让网关层做 TLS 终止。老容器的 HTTPS 排查十次里有七次是证书过期剩下三次是协议版本不匹配很少真有“莫名其妙连不上”的玄学。5.4 端口被占与 domain 锁第二个实例怎么都起不来现象在同一台机器上创建第二个 domain 并启动报Address already in use或者提示管理端口已被占用如果上一个 domain 被强制 kill再次启动时报锁文件错误。原因两个 domain 的默认端口会重叠默认 domain1 的 4848 和 8080 与新建 domain 的默认配置完全相同。另一个原因是 GlassFish 启动时会写锁文件来标记运行状态进程被强杀或系统宕机锁文件残留启动逻辑会误以为已经有实例在跑。解决新建 domain 时用--portbase让端口自动偏移# 以 18000 为基准管理端口映射到 18048HTTP 端口映射到 18080 asadmin create-domain --portbase 18000 appdomain # 启动新域 asadmin start-domain appdomain--portbase会自动给默认端口加一个偏移量省去逐项改端口的手工操作。11000 以上的基准值比较安全既能避开已占用的段也方便后续通过端口号快速识别是哪个域。如果确认端口没有被占用但仍报端口冲突就去 domain 目录下找锁文件路径一般在$GLASSFISH_HOME/glassfish/domains/域名/下文件名带.lck后缀。删除前先确认没有存活进程避免误删后两个实例同时写同一份配置那种情况更麻烦。5.5 中文乱码从请求到数据库的完整链路现象浏览器提交的中文参数在页面显示为问号日志里打印出来的中文是乱码数据库表里的中文也变成问号或 Unicode 转义字符。原因不是某一个环节坏了而是请求编码、应用容器编码、数据库连接编码、数据库表字符集四段链路不全是 UTF-8任何一端不一致就会出现乱码。最常见的错位是请求已经用 UTF-8 进入容器但 JDBC URL 没带characterEncodingUTF-8导致数据入库时被转成别的编码。解决按链路逐段锁定。# 第一段容器请求编码改成 UTF-8 asadmin set server.network-config.protocols.protocol.http-listener-1.http.encoding-enabledtrue asadmin set server.network-config.protocols.protocol.http-listener-1.http.encoding-uri-encodingUTF-8 # 第二段JVM 文件编码统一成 UTF-8 asadmin create-jvm-options -Dfile.encodingUTF-8 # 第三段重启让配置生效 asadmin restart-domain domain1encoding-enabled打开后 GlassFish 会按encoding-uri-encoding指定的编码解析请求参数-Dfile.encodingUTF-8主要影响日志输出和文件读写。真正容易漏掉的还是 JDBC URL必须在连接池属性里明确加上characterEncodingUTF-8连接池配置的优先级比你persistence.xml里写的任何属性都高。如果数据库里已经存了乱码改配置救不了存量数据。应对办法是先导出现有数据修复字符集后再导入关键是这次要把连接 URL、表和库的默认字符集、客户端连接编码都确认一致不然下次迁移数据还会再来一遍。6. 让 7u3 少闹腾启动参数、systemd 托管与备份习惯最后一章不聊新功能聊怎么让这台老发动机少出幺蛾子。SDK 7u3 本身已经不是活跃开发版本日常维护的目标是“稳定运行、可快速恢复”所以我会把精力放在三个地方参数固化、进程托管、备份留底。JVM 参数不要每次在命令行里临时加统一写进 domain.xml。一个经过验证的常见配置如下参数建议值说明-Xms256m启动时堆大小避免频繁扩容-Xmx1024m堆上限按实际应用内存占用调整-XX:MaxMetaspaceSize256m元空间上限防止类加载器泄漏-Dfile.encodingUTF-8UTF-8统一中文编码-Duser.timezoneAsia/Shanghai系统时区避免日志时间与本地时间不一致进程托管建议用 systemd 而不是裸启动脚本。托管的好处是开机自启、崩溃自动拉起、日志统一收集。domain 启动和停止各写一条命令即可# ExecStart 使用 start-domainExecStop 使用 stop-domain ExecStart/opt/glassfish/bin/asadmin start-domain domain1 ExecStop/opt/glassfish/bin/asadmin stop-domain domain1注意asadmin stop-domain是阻塞式的systemd 可以通过ExecStop稳定收到退出状态。如果 systemd 配置有问题现象是服务状态显示 active但端口听不到这时先看journalctl -u glassfish的日志再检查ExecStart里的路径是否因为软链接解析不完整导致失败。备份是最后一道防线。我维护的每一套 SDK 7u3 环境备份清单只有三样东西备份对象路径恢复方式域配置domains/domain1/config/domain.xml停止域后覆盖重启已部署应用domains/domain1/applications/复制回原目录后启用自定义库domains/domain1/lib/ext/含连接池驱动和第三方 jar用 crontab 定期把这三个目录打包保留最近七天版本出问题时能恢复到任意一天的状态。我曾经就是因为少备份了lib/ext下的驱动 jar服务器故障后新环境连不上数据库排查了很久才发现是驱动没放。从那以后我的习惯是每次改完 domain.xml 或连接池配置立刻手动打包一份配置快照再做变更操作。这个习惯帮我少熬了不少夜希望也能帮到你。本文还有配套的精品资源点击获取