宝兰德 AppServer 部署方案
SpringBoot版本:4.x(本文实测 JeecgBoot 3.9.3 + SpringBoot 4.1.0)
JDK版本:17
本文为认证测试专用新文档,实际安装介质为
D:\宝兰德\BES-APPSERVER-STANDARD-11.0-SP5-BN001.tar.gz(BES Application Server Standard V11.0 SP5)。前后台均采用 war 包部署到宝兰德 BES AppServer(标准版)。
本文针对 SpringBoot 4 版本(
jakarta.*命名空间、JDK17+)。SpringBoot 4 要求容器支持 Jakarta Servlet 6.1,BES 11.0 SP5 自带的lib/jakartaee.jar已提供 Servlet 6.1 API。SpringBoot 3 版本请参考《宝兰德 AppServer 部署方案(SpringBoot3)》。
环境说明
| 项目 | 版本 |
|---|---|
| 操作系统 | TencentOS Server 3.3(x86_64) |
| JDK | OpenJDK 17.0.20 |
| BES AppServer | Standard V11.0(SP5 build 001.000),安装包自带试用授权 |
| JeecgBoot | 后端 3.9.3(SpringBoot 4.1.0),前端 3.9.3 |
| 数据库 / 缓存 | MySQL 8.0.46、Redis 6.2(与 BES 部署在同一台服务器) |
与 SpringBoot3 文档的差异
| 项目 | SpringBoot3 文档 | SpringBoot4(本文) |
|---|---|---|
| BES 安装介质 | 一键安装脚本包 | 标准版产品 tar.gz,解压即用,包内没有顶层目录 |
| Hibernate/JPA 冲突 | 需排除 HibernateJpaAutoConfiguration | 不需要处理(原因见「二、3」) |
| 内嵌 Tomcat | 设为 provided | 保持默认 scope(原因见「二、2」) |
| 部署选项 | 默认即可 | 「支持组件」必须勾选 JSONP(原因见「四、2」) |
一、BES AppServer 安装
1、上传并解压
将 BES-APPSERVER-STANDARD-11.0-SP5-BN001.tar.gz 上传到服务器(本文为 /root),创建安装目录后解压:
# 本地执行:上传安装包到服务器 /root
scp BES-APPSERVER-STANDARD-11.0-SP5-BN001.tar.gz root@<服务器IP>:/root/
# 服务器执行:创建安装目录并解压
cd /root
mkdir -p /opt/bes
tar -xzf BES-APPSERVER-STANDARD-11.0-SP5-BN001.tar.gz -C /opt/bes
该 tar.gz 没有顶层目录(第一层就是
ROOT/、conf/、bin/等),务必先创建安装目录再用-C指定解压位置。直接在/opt下解压,会把 bin、conf、lib 等 11 个目录散落到/opt中。

解压后目录结构:
/opt/bes/
├── bin/ # startserver、stopserver 等脚本,以及 env.properties
├── conf/ # server.config 等配置文件
├── deployments/ # 已部署的应用
├── lib/ # 依赖库(含 jakartaee.jar)
├── license/ # 授权文件 bes.lic.txt(安装包自带试用授权)
├── logs/ # 日志
└── ...
2、指定 JDK 并调大内存
在 bin/env.properties 中指定 JDK17:
cd /opt/bes/bin
sed -i '$a JAVA_HOME=/usr/lib/jvm/java-17-openjdk' env.properties
cat env.properties

env.properties的最后一行没有换行符,直接用echo ... >> env.properties追加会和上一行ADMIN_PORT=1900拼在一起,JAVA_HOME 不生效。请用vi编辑,或者用上面的sed '$a'追加。
部分系统默认的
java不是 17(例如 TencentOS 镜像自带 Kona JDK 8),显式指定 JAVA_HOME 可以避免 BES 用错 JDK。JAVA_HOME按服务器上 JDK17 的实际路径填写。
JeecgBoot 后端 war 较大,BES 默认堆 -Xmx2048m 部署时会内存溢出(OutOfMemoryError: Java heap space),启动前在 conf/server.config 中调到 3072m:
cd /opt/bes/conf
sed -i 's/-Xmx2048m/-Xmx3072m/' server.config
grep -n "Xmx" server.config
输出中应能看到
<jvm-options>-Xmx3072m</jvm-options>。BES 已经启动过的,改完要重启才生效。
3、启动 BES
startserver 在前台运行,退出终端就会停止,需要用 nohup 放到后台:
cd /opt/bes/bin
nohup ./startserver > /opt/bes/logs/startserver.out 2>&1 &
tail -f /opt/bes/logs/startserver.out
首次启动会自动导入 license/bes.lic.txt 中的授权,看到 Server startup in [xxxx] milliseconds 即启动完成:

停止 BES:
cd /opt/bes/bin && ./stopserver
4、确认端口
ss -tlnp | grep -E ':1900|:8080'
| 端口 | 说明 |
|---|---|
| 1900 | 管理控制台(HTTPS) |
| 8080 | 应用 HTTP 端口(http-listener-1) |

端口在
conf/server.config的http-listener中配置,JVM 参数在java-config中配置。
5、登录管理控制台
管理控制台信息:
地址:https://<服务器IP>:1900/console
用户名:admin
默认密码:B#2008_2108#es(首次登录强制修改)
控制台端口 1900 是 HTTPS,不是 HTTP,必须用
https://访问。用http://访问会被服务器直接断开连接,浏览器报ERR_CONNECTION_CLOSED。控制台默认开启 Host 头校验:用公网 IP 访问(Host 头为公网 IP)时返回 HTTP 400,只有内网 IP、
127.0.0.1访问才正常。因此推荐用下面的「方式一」SSH 隧道访问。
下面两种访问方式任选其一。
方式一:SSH 隧道访问(推荐)
无需改动服务器配置、无需对公网开放 1900 端口,还能自动绕过 Host 头校验(经隧道后浏览器里的 Host 是 127.0.0.1,不会被拦)。
在本地开一个终端(Windows 用 PowerShell 或 Git Bash),执行下面的命令、输入 root 密码,并保持该窗口不关闭:
ssh -L 1900:127.0.0.1:1900 root@<服务器公网IP>
然后在本机浏览器访问:
https://127.0.0.1:1900/console
自签名证书浏览器会提示风险,点「高级 → 继续前往」即可。后续部署前端应用(8080 端口)后,可在隧道命令里再加一段一起转发:
ssh -L 1900:127.0.0.1:1900 -L 8080:127.0.0.1:8080 root@<服务器公网IP>,前端走http://127.0.0.1:8080/。
方式二:直连公网 IP 访问
需要改动两处:
- 在云服务器安全组入站规则中放行
TCP:1900(云主机默认通常只开放 22,不放行则浏览器连不上,报ERR_CONNECTION_CLOSED或连接超时)。来源建议限定为你的公网 IP,不要用0.0.0.0/0。 - 直连公网 IP 会被 Host 头校验拦成 HTTP 400,需给控制台关闭该校验,步骤见文末「附录:浏览器访问控制台返回 400」。
两处都完成后,浏览器访问 https://<服务器公网IP>:1900/console。
访问到控制台后,登录页如下:

首次登录会提示「检测到您的密码仍是默认密码,请先修改密码」,修改后用新密码重新登录:

登录后进入「实例总览」,可以看到版本号 V11.0 (SP5 build 001.000)、HTTP 端口、JAVA HOME,右上角为授权信息(安装包自带试用授权 BES TRIAL,有效期 184 天):

二、后台 JeecgBoot 打 war 包
1、修改jeecg-system-start/pom.xml
打包格式由 jar 改为 war:
<artifactId>jeecg-system-start</artifactId>
<!-- 由 jar 改为 war -->
<packaging>war</packaging>
注释掉 spring-boot-maven-plugin(war 部署到外部容器,不需要 repackage 成可执行包):
<build>
<plugins>
<!--<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>org.jeecg.JeecgSystemApplication</mainClass>
</configuration>
</plugin>-->
</plugins>
</build>
启动类
JeecgSystemApplication已继承SpringBootServletInitializer,无需修改。BES 会通过ServletContainerInitializer自动拉起 Spring,不需要额外添加web.xml。
2、内嵌 Tomcat 保持默认 scope
不要把
spring-boot-starter-tomcat设为provided。BES 的 Web 容器(com.bes.enterprise.webtier)没有提供org.apache.catalina.*类;而 JeecgBoot 的TomcatFactoryConfig(jeecg-system-biz)直接引用了 Tomcat 的类,设为provided后在 BES 中会找不到这些类。war 部署时内嵌 Tomcat 不会启动,只提供类供引用。
spring-boot-starter-tomcat 由 web starter 传递引入,保持原样、不做任何修改即可。
3、无需处理 Hibernate/JPA(与 SpringBoot3 的区别)
SpringBoot3 文档需要在启动类上排除 HibernateJpaAutoConfiguration,SpringBoot4 不需要:
- SpringBoot 4 把 JPA 自动配置拆到了独立的
spring-boot-hibernate模块,JeecgBoot 没有引入该模块,不会触发 JPA 初始化; spring-boot-autoconfigure4.x 中已经没有org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration这个类,照搬 SpringBoot3 文档的 import 会直接编译失败。
BES 部署表单「支持组件」中的 JPA 默认不勾选,保持不勾选即可。
4、配置application-prod.yml
修改数据库、Redis 和文件上传配置(本文 MySQL、Redis 与 BES 在同一台服务器):
spring:
datasource:
dynamic:
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/jeecgbootbpm?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: <数据库密码>
driver-class-name: com.mysql.cj.jdbc.Driver
data:
redis:
database: 0
host: 127.0.0.1
port: 6379
password: <Redis密码>
jeecg:
# 上传类型:local(本地存储)
uploadType: local
path:
upload: /opt/jeecg-boot/upload
webapp: /opt/jeecg-boot/webapp
SpringBoot 4 的 Redis 配置位于
spring.data.redis.*,从旧工程迁移时务必核对配置前缀。
war 部署时
server.port、server.servlet.context-path不生效:访问端口由 BES 的 HTTP 监听器决定(8080),上下文路径由部署时填写的「应用前缀」决定。如需用宝兰德 CacheDB 代替 Redis,参考《集成宝兰德CacheDB(SpringBoot4)》修改
spring.data.redis配置即可。
5、执行打包
在后端项目根目录执行(勾选 prod profile):
mvn clean package -Pprod -pl jeecg-module-system/jeecg-system-start -am -DskipTests
产物:jeecg-module-system/jeecg-system-start/target/jeecg-system-start-3.9.3.war(约 450MB)。
将其改名为 jeecg-boot.war:BES 部署时默认用文件名作为应用名称和应用前缀,改名后应用前缀默认就是 /jeecg-boot。
三、前台项目打包
1、修改接口地址.env.production
#后台接口父地址(必填)
VITE_GLOB_API_URL=/jeecg-boot
#后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://服务器IP:8080/jeecg-boot
VITE_GLOB_API_URL必须与后端部署时的应用前缀完全一致(本文为/jeecg-boot),否则前端所有接口都会 404。
2、执行打包
pnpm install
pnpm build
打包完成后,dist/_app.config.js 中的 VITE_GLOB_API_URL、VITE_GLOB_DOMAIN_URL 应为上一步修改后的值。
3、添加WEB-INF/web.xml
在 dist 目录下新增 WEB-INF/web.xml,把 404 转到 index.html(前端使用 history 路由,刷新页面时需要回退到首页):
在 dist 目录下执行(直接生成 WEB-INF/web.xml):
mkdir -p dist/WEB-INF
cat > dist/WEB-INF/web.xml <<'EOF'
<web-app>
<error-page>
<error-code>404</error-code>
<location>/index.html</location>
</error-page>
</web-app>
EOF
4、打war包
jar 命令在 JDK 的 bin 目录下(如 D:\Program Files\Java\jdk-17\bin\jar.exe)。若未配置到 PATH,用全路径调用即可。在前端项目根目录执行,用 -C dist . 把 dist 的内容打到 war 根目录(跨 Windows cmd 和 Git Bash 都适用):
jar -cvf jeecg-vue.war -C dist .
不要用
jar -cvf jeecg-vue.war ./*这种写法:./*通配只有 Git Bash/Linux 的 shell 会展开,Windows cmd 不展开、jar自身也不展开通配符,会报找不到./*。用-C dist .最稳妥。
打完核对 war 根目录包含 WEB-INF/web.xml 和 index.html:
jar -tf jeecg-vue.war | findstr /B "WEB-INF/web.xml index.html _app.config.js"
四、部署项目
1、上传 war 到服务器
/data/deployFile/jeecg-boot.war
/data/deployFile/jeecg-vue.war
后端 war 约 450MB,通过控制台在浏览器中上传容易超时。建议先用 SFTP/scp 上传到服务器,部署时直接选择服务器上的文件。
2、部署后端
-
进入「应用管理 → 常用应用」,点击「部署」

-
部署类型选「部署为应用」。文件浏览器默认打开
/opt/bes/upload,点「返回上一级」回到根目录,依次进入data→deployFile,选中jeecg-boot.war,点击「下一步」
-
应用名称为
jeecg-boot,应用前缀为/jeecg-boot(默认取自文件名),类加载顺序保持默认的「子优先」
-
页面下拉到「支持组件」,勾选 JSONP,其余保持默认,点击「保存」

必须勾选 JSONP。 BES 是完整的 Jakarta EE 容器,会向应用暴露 JSON-B API;SpringBoot 4 的 Spring Data Redis 检测到 JSON-B 后会创建
JsonbMessageConverter,进而查找 JSON-P 实现。不勾选 JSONP 时找不到实现,应用启动失败,报错jakarta.json.JsonException: Provider org.glassfish.json.JsonProviderImpl not found(完整报错见附录)。支持组件只能在部署时设置,已部署的应用需要通过「重新部署」勾选。
后端 war 较大,首次部署需要 1 ~ 2 分钟,控制台可能提示「操作超时」,这并不代表部署失败,请以「常用应用」列表中的部署状态和
/opt/bes/logs/server.log为准。
3、部署前端
-
同样点击「部署」,进入
/data/deployFile,选中jeecg-vue.war,点击「下一步」
-
将应用前缀改为
/(根路径),点击「保存」
后端的应用前缀必须与前端打包时
VITE_GLOB_API_URL的路径一致。
五、访问系统
1、放行应用端口并验证
应用运行在 BES 的 HTTP 端口 8080(前端在根路径 /,后端在 /jeecg-boot)。要从公网访问,需在云服务器安全组入站规则中放行 TCP:8080(来源建议限定为你的公网 IP)。
不想对公网开放时,也可以用 SSH 隧道:
ssh -L 8080:127.0.0.1:8080 root@<服务器公网IP>,然后访问http://127.0.0.1:8080/。
先在服务器本机验证前后端都通:
# 前端首页
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/
# 后端接口(验证码图片)
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/jeecg-boot/sys/randomImage/111
两条都返回 200 即正常,另外 /opt/bes/logs/server.log 中应能看到 Started JeecgSystemApplication。
2、登录系统
浏览器访问 http://<服务器IP>:8080/,进入登录页:

输入账号、密码、验证码登录(账号来自导入的数据库,默认 admin / 123456)。登录后进入系统,菜单与数据正常加载:

至此 JeecgBoot(SpringBoot4)前后端部署到宝兰德 BES AppServer 完成。
附录:常见问题
后端启动失败:Provider org.glassfish.json.JsonProviderImpl not found
现象:「常用应用」中后端应用的部署状态为「启动失败」,/opt/bes/logs/server.log 中报错:
ERROR org.springframework.boot.SpringApplication - Application run failed
jakarta.json.JsonException: Provider org.glassfish.json.JsonProviderImpl not found
at jakarta.json.spi.JsonProvider.provider(JsonProvider.java:60)
at com.bes.johnzon.jsonb.JohnzonBuilder.build(JohnzonBuilder.java:131)
at jakarta.json.bind.JsonbBuilder.create(JsonbBuilder.java:69)
at org.springframework.messaging.converter.JsonbMessageConverter.<init>(JsonbMessageConverter.java:49)
at org.springframework.data.redis.serializer.DefaultRedisMessageConverters$DefaultBuilder.getDefaultConverters(DefaultRedisMessageConverters.java:153)
...
Caused by: java.lang.ClassNotFoundException: org.glassfish.json.JsonProviderImpl

原因:部署时「支持组件」没有勾选 JSONP。
解决:在「常用应用」列表中点击该应用的「重新部署」,选择同一个 war 包,在「支持组件」中勾选 JSONP 后保存。
浏览器访问控制台返回 400
原因:控制台默认开启 Host 头校验,Host 头为公网 IP 时被拒绝。
解决:推荐使用 SSH 端口转发访问(见「一、5」),无需修改配置。必须用公网 IP 直接访问时,编辑控制台的 web.xml。先备份:
cp /opt/bes/lib/system/apps/console/WEB-INF/web.xml /opt/bes/lib/system/apps/console/WEB-INF/web.xml.bak
方式一(手动):执行 vi /opt/bes/lib/system/apps/console/WEB-INF/web.xml,在 SecurityFilter 的 </filter-mapping> 之后插入:
<filter>
<filter-name>hostHeaderPreventionFilter</filter-name>
<filter-class>com.bes.enterprise.console.filter.HostHeaderPreventionFilter</filter-class>
<init-param>
<param-name>isCheckHost</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hostHeaderPreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
方式二(命令自动插入,免手动编辑):直接执行下面的脚本,会在 SecurityFilter 的 filter-mapping 之后插入上述过滤器:
python3 - <<'PY'
p = "/opt/bes/lib/system/apps/console/WEB-INF/web.xml"
s = open(p, encoding="utf-8").read()
anchor = ''' <filter-name>SecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
'''
add = ''' <filter>
<filter-name>hostHeaderPreventionFilter</filter-name>
<filter-class>com.bes.enterprise.console.filter.HostHeaderPreventionFilter</filter-class>
<init-param>
<param-name>isCheckHost</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hostHeaderPreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
'''
assert s.count(anchor) == 1, "锚点未唯一匹配,请改用方式一手动插入"
open(p, "w", encoding="utf-8").write(s.replace(anchor, anchor + add))
print("inserted")
PY
重启 BES 生效:
cd /opt/bes/bin && ./stopserver && nohup ./startserver > /opt/bes/logs/startserver.out 2>&1 &
关闭 Host 头校验会降低控制台安全性,修改前先备份
web.xml,并通过安全组限制 1900 端口的访问来源。
控制台提示「操作超时」
原因:后端 war 较大,部署和启动超过了控制台请求的等待时间。
解决:稍等 1 ~ 2 分钟后刷新「常用应用」列表,以部署状态和 /opt/bes/logs/server.log 为准。
控制台上传 war 超时
原因:后端 war 约 450MB,浏览器上传容易超时。
解决:先通过 SFTP/scp 上传到服务器(如 /data/deployFile),部署时在文件浏览器中直接选择。
部署时报 OutOfMemoryError: Java heap space
现象:部署后端大 war 时 /opt/bes/logs/server.log 报:
SEVERE deployment - Java heap space
com.bes.enterprise.appserv.deployment.exception.DeploymentException: Java heap space
Caused by: java.lang.OutOfMemoryError: Java heap space
原因:JeecgBoot 后端 war 较大(含全部模块,450MB+),BES 扫描注解时内存占用高,默认堆 -Xmx2048m 不够。
解决:调大 BES 堆后重启。编辑 conf/server.config 的 <java-config>,把 -Xmx 调大(如 3072m):
sed -i 's/-Xmx2048m/-Xmx3072m/' /opt/bes/conf/server.config
cd /opt/bes/bin && ./stopserver && nohup ./startserver > /opt/bes/logs/startserver.out 2>&1 &
调大
-Xmx前先确认服务器可用内存足够(本文 8G 内存同时跑 BCS + MySQL + MongoDB + BES 已较紧张);内存不足时可临时停掉 BCS 控制台(4901,缓存实例 6080 不受影响)腾出内存。
部署失败(如上面的 OOM)后,BES 会回滚该应用的部署项——重启后不会自动拉起,需要在控制台重新「部署」一次。