跳到主要内容

宝兰德AppServer部署(SpringBoot4)

积木报表版本:示例工程 jimureport-example(SpringBoot 4.1.0,jimureport-spring-boot4-starter 2.5.6)

JDK版本:17

宝兰德版本:BES Application Server Standard V11.0 SP5,安装介质 BES-APPSERVER-STANDARD-11.0-SP5-BN001.tar.gz

积木报表打成 war 包部署到宝兰德 BES AppServer(标准版),应用前缀为 /jimureport,部署后访问 http://<服务器IP>:8080/jimureport/jmreport/list。

环境说明​

项目版本
操作系统TencentOS Server 3.3(x86_64)
JDKOpenJDK 17.0.20
BES AppServerStandard V11.0(SP5 build 001.000),安装包自带试用授权
积木报表示例工程 jimureport-example(SpringBoot 4.1.0):积木报表 2.5.6、积木BI 2.5.4、ChatBI 1.2.0
数据库MySQL 8.0.46(与 BES 部署在同一台服务器)

SpringBoot 4 要求容器支持 Jakarta Servlet 6.1,BES 11.0 SP5 自带的 lib/jakartaee.jar 已提供 Servlet 6.1 API。

一、BES AppServer 安装​

服务器上已经装好 BES 的,跳过本节,直接看「二、积木报表打 war 包」。

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 没有顶层目录(第一层就是 bin/、conf/、lib/ 等),务必先创建安装目录再用 -C 指定解压位置,否则这些目录会散落到当前目录中。

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 不生效。请用上面的 sed '$a' 追加,或者用 vi 编辑。JAVA_HOME 按服务器上 JDK17 的实际路径填写。

3、启动 BES​

startserver 在前台运行,退出终端就会停止,需要用 nohup 放到后台:

cd /opt/bes/bin
nohup ./startserver > /opt/bes/logs/startserver.out 2>&1 &
tail -f /opt/bes/logs/startserver.out

看到 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),积木报表通过这个端口访问

5、登录管理控制台​

地址:https://<服务器IP>:1900/console
用户名:admin
默认密码:B#2008_2108#es(首次登录强制修改)

控制台端口 1900 是 HTTPS,必须用 https:// 访问,用 http:// 访问会被直接断开(浏览器报 ERR_CONNECTION_CLOSED)。

控制台默认开启 Host 头校验,用公网 IP 访问会返回 HTTP 400。推荐用 SSH 隧道访问:在本地执行 ssh -L 1900:127.0.0.1:1900 root@<服务器公网IP> 并保持窗口不关闭,然后浏览器访问 https://127.0.0.1:1900/console(自签名证书点「高级 → 继续前往」)。必须用公网 IP 直接访问的,见文末附录。

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

登录后进入「实例总览」,可以看到版本号、HTTP 端口、JAVA HOME 和授权信息:

二、积木报表打 war 包​

1、下载示例工程​

git clone https://github.com/jeecgboot/JimuReport.git
# 国内访问慢可以用 Gitee:git clone https://gitee.com/jeecg/JimuReport.git
cd JimuReport/jimureport-example

本文使用 SpringBoot4 版示例工程(pom.xml 的 parent 为 spring-boot-starter-parent 4.1.0,依赖 jimureport-spring-boot4-starter)。积木报表集成在自己项目里的,按下面同样的思路改造自己的项目即可。

2、修改pom.xml​

打包格式由 jar 改为 war(加在 <version> 下面):

<artifactId>jimureport-example</artifactId>
<version>2.5</version>
<!-- 由 jar 改为 war -->
<packaging>war</packaging>

<build> 中指定 war 包名为 jimureport,并注释掉 spring-boot-maven-plugin(war 部署到外部容器,不需要打成可执行包):

<build>
<!-- war 包名,BES 部署时默认用它作为应用名称和应用前缀 -->
<finalName>jimureport</finalName>
<plugins>
<!-- SpringBoot启动 -->
<!--<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>-->
</plugins>
</build>

内嵌 Tomcat(spring-boot-starter-tomcat,由 spring-boot-starter-webmvc 传递引入)保持默认 scope,不需要改成 provided:war 部署时内嵌 Tomcat 不会启动,本文按默认 scope 实测通过。

3、修改启动类​

JimuReportApplication 继承 SpringBootServletInitializer,BES 通过它拉起 Spring,不需要额外添加 web.xml:

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication(scanBasePackages = {"org.jeecg", "com.jeecg"})
public class JimuReportApplication extends SpringBootServletInitializer {

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(JimuReportApplication.class);
}

// main 方法保持不变
}

war 部署时不会执行 main 方法,控制台不会打印「JimuReport 积木报表平台 is running!」提示块,启动情况以日志为准(见「五、1」)。

4、登录页适配应用前缀​

示例工程自带的登录页是按根路径写的,部署到 /jimureport 这类应用前缀下时需要改下面 3 处。不改的话,未登录时会跳到服务器根路径的 /login/login.html(根路径下的其他应用或 404),登录成功后又会跳到 /jimureport/jimureport/jmreport/list 导致 404。

① src/main/resources/static/login/login.html,表单提交地址和口令检查接口改为相对路径:

<!-- 原来是 action="/doLogin" -->
<form class="form-signin" method="get" action="../doLogin">
// 原来是 fetch('/isDefaultCredentials')
fetch('../isDefaultCredentials')

② src/main/java/com/jeecg/modules/jmreport/extend/JimuReportTokenServiceImpl.java,verifyToken 方法中跳转登录页的两行改为带上应用前缀:

// 原来是:
// String redirect = URLEncoder.encode(request.getRequestURI(), StandardCharsets.UTF_8);
// JimuSpringContextUtils.getHttpServletResponse().sendRedirect("/login/login.html?redirect=" + redirect);
String contextPath = request.getContextPath();
String redirect = URLEncoder.encode(request.getRequestURI().substring(contextPath.length()), StandardCharsets.UTF_8);
JimuSpringContextUtils.getHttpServletResponse().sendRedirect(contextPath + "/login/login.html?redirect=" + redirect);

部署时应用前缀填 /(部署在根路径)的,可以不改这 3 处。

5、修改配置文件​

示例工程默认激活 dev 配置(见 application.yml 中的 spring.profiles.active),修改 src/main/resources/application-dev.yml:

spring:
datasource:
url: jdbc:mysql://${MYSQL-HOST:127.0.0.1}:${MYSQL-PORT:3306}/${MYSQL-DB:jimureport}?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: <数据库密码>
security:
user:
name: "${JIMU_ADMIN_USER:admin}"
# 登录口令,必须配置
password: "${JIMU_ADMIN_PASSWORD:<登录口令>}"

jeecg:
path:
# 上传文件的存放目录
upload: /opt/upload
jmreport:
# 自定义API接口的前缀 #{api_base_path}和#{domainURL}的值,改为部署后的访问地址
apiBasePath: http://<服务器IP>:8080/jimureport

登录口令必须配置。 口令留空或为 123456 时,每次启动都会随机生成一个口令。war 部署时没有启动提示块,随机口令只能到日志里找(见附录)。

war 部署时 server.port、server.servlet.context-path 不生效:访问端口由 BES 的 HTTP 监听器决定(8080),访问前缀由部署时填写的「应用前缀」决定。

示例工程已配置 spring.data.redis.listener.auto-startup: false,没有 Redis 也能正常启动(本文服务器上没有运行 Redis)。

正式上线前,参考《集成积木权限》中的「上线配置」调整 jeecg.jmreport.firewall 等安全配置,并替换示例中的 signatureSecret。

6、执行打包​

在 jimureport-example 目录执行:

mvn clean package -DskipTests

产物:target/jimureport.war(约 290MB)。

三、初始化数据库​

将示例工程中的初始化脚本 db/jimureport.mysql5.7.create.sql 上传到服务器并导入,脚本会自动创建 jimureport 库:

# 本地执行:上传脚本到服务器 /root
scp db/jimureport.mysql5.7.create.sql root@<服务器IP>:/root/

# 服务器执行(在 /root 目录下)
cd /root
mysql -uroot -p < jimureport.mysql5.7.create.sql

导入后执行下面的命令检查,jimureport 库中应有 58 张表:

mysql -uroot -p -e "show databases like 'jimureport'; select count(*) as table_count from information_schema.tables where table_schema='jimureport';"

脚本会先 DROP TABLE 再建表,库中已有积木报表数据的,导入前先备份。

本文 MySQL 配置了 lower_case_table_names=1,与示例工程 docker-compose.yml 中的 MySQL 配置一致。

四、部署到 BES​

1、上传 war 到服务器​

# 服务器执行:创建存放目录
mkdir -p /data/deployFile

# 本地执行:上传 war
scp target/jimureport.war root@<服务器IP>:/data/deployFile/

war 约 290MB,通过控制台在浏览器中上传容易超时。建议先用 scp/SFTP 上传到服务器,部署时在控制台直接选择服务器上的文件。

2、部署应用​

  1. 进入「应用管理 → 常用应用」,点击「部署」

  2. 部署类型选「部署为应用」。文件浏览器默认打开 /opt/bes/upload,点 3 次「返回上一级」回到根目录,依次进入 data → deployFile,选中 jimureport.war,点击「下一步」

  3. 应用名称 jimureport、应用前缀 /jimureport 默认取自文件名,类加载顺序保持默认的「子优先」

  4. 页面下拉到「支持组件」,勾选 JSONP,其余保持默认,点击「保存」

必须勾选 JSONP。 BES 是完整的 Jakarta EE 容器,会向应用暴露 JSON-B API;积木报表依赖的 Spring Data Redis(SpringBoot 4)启动时检测到 JSON-B,会创建 JsonbMessageConverter 并查找 JSON-P 实现。不勾选 JSONP 时找不到实现,应用启动失败,报错 Provider org.glassfish.json.JsonProviderImpl not found。这个报错与是否配置了 Redis 无关,完整报错见附录。支持组件只能在部署时设置。

  1. 十几秒后部署完成,「常用应用」列表中 jimureport 的部署状态为「已启动」

五、访问积木报表​

1、命令行验证​

积木报表运行在 BES 的 HTTP 端口 8080,应用前缀为 /jimureport。先在服务器本机验证:

# 未登录访问报表工作台,应返回 302 并跳转到 /jimureport/login/login.html
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" http://127.0.0.1:8080/jimureport/jmreport/list
# 登录页,应返回 200
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/jimureport/login/login.html
# 启动日志
grep "Started JimuReportApplication" /opt/bes/logs/jimureport-*.log

积木报表的日志写在 /opt/bes/logs/jimureport-日期.0.log:示例工程 logback-spring.xml 中的日志目录是 ../logs,相对的是 BES 的工作目录 /opt/bes/bin。日志同时也会输出到 BES 的 /opt/bes/logs/server.log。

2、浏览器访问​

要从公网访问,需在云服务器安全组入站规则中放行 TCP:8080(来源建议限定为你的公网 IP)。不想对公网开放的,也可以用 SSH 隧道:ssh -L 8080:127.0.0.1:8080 root@<服务器公网IP>,然后把下面地址中的 <服务器IP> 换成 127.0.0.1。

  1. 访问报表工作台 http://<服务器IP>:8080/jimureport/jmreport/list,未登录会跳到登录页,输入账号 admin 和「二、5」中配置的登录口令

  2. 登录后进入报表工作台

  3. 修改示例数据源的密码。初始化脚本中内置了「积木库」「本地积木库」「填报数据源」3 个数据源,都指向 127.0.0.1:3306/jimureport,账号 root,密码是示例环境的密码。数据库密码不同的,进入「系统配置 → 数据源维护」,逐个点击「编辑」,填写实际的数据库密码,「测试连接」成功后点击「确定」

不改的话,引用这些数据源的示例报表预览时页面空白,日志报 Access denied for user 'root'@'localhost'。

  1. 预览报表,例如示例模板「简单条件查询报表」(使用「积木库」数据源):http://<服务器IP>:8080/jimureport/jmreport/view/1338744112815411200,数据正常显示,导出 Excel、PDF、Word 正常

  2. 点击右上角「进入BI工作台」,或访问 http://<服务器IP>:8080/jimureport/drag/list,进入 BI 工作台,大屏、仪表盘可正常预览

至此积木报表部署到宝兰德 BES AppServer 完成。

附录:常见问题​

启动失败:Provider org.glassfish.json.JsonProviderImpl not found​

现象:「常用应用」中 jimureport 的部署状态为「启动失败」:

/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)
at org.springframework.data.redis.serializer.DefaultRedisMessageConverters$DefaultBuilder.build(DefaultRedisMessageConverters.java:131)
at org.springframework.data.redis.config.RedisListenerEndpointRegistrar.apply(RedisListenerEndpointRegistrar.java:229)
at org.springframework.data.redis.annotation.RedisListenerAnnotationBeanPostProcessor.afterSingletonsInstantiated(RedisListenerAnnotationBeanPostProcessor.java:149)
...
Caused by: java.lang.ClassNotFoundException: org.glassfish.json.JsonProviderImpl

原因:部署时「支持组件」没有勾选 JSONP。

解决:支持组件只能在部署时设置。在「常用应用」中勾选该应用,点击「解部署」,再按「四、2」重新部署,在「支持组件」中勾选 JSONP。

未登录时跳到了其他系统,或登录后 404​

现象:访问 /jimureport/jmreport/list 被跳到 http://<服务器IP>:8080/login/login.html(根路径下的其他应用或 404),或者登录后地址变成 /jimureport/jimureport/jmreport/list 并返回 404。

原因:示例工程的登录页按根路径编写,部署到应用前缀下时没有修改。

解决:按「二、4」修改 3 处后重新打包、部署。

不知道登录口令​

原因:没有配置 spring.security.user.password(或配置的是 123456),每次启动都会随机生成口令。

解决:在日志中查看本次启动的口令:

grep "登录口令" /opt/bes/logs/jimureport-*.log

建议按「二、5」配置固定口令后重新打包部署。

浏览器访问控制台返回 400​

原因:控制台默认开启 Host 头校验,Host 头为公网 IP 时被拒绝。

解决:推荐使用 SSH 隧道访问(见「一、5」),无需修改配置。必须用公网 IP 直接访问的,先在安全组放行 TCP:1900,再给控制台关闭 Host 头校验。先备份控制台的 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>

重启 BES 生效:

cd /opt/bes/bin && ./stopserver && nohup ./startserver > /opt/bes/logs/startserver.out 2>&1 &

关闭 Host 头校验会降低控制台安全性,安全组中 1900 端口的来源要限定为自己的 IP。

控制台上传 war 超时​

原因:war 约 290MB,浏览器上传容易超时。

解决:先用 scp/SFTP 上传到服务器(如 /data/deployFile),部署时在文件浏览器中直接选择。

部署时报 OutOfMemoryError: Java heap space​

原因:BES 默认堆为 -Xmx2048m,同一个 BES 中部署了多个应用时可能不够(本文环境与其他应用共用 BES,设置的是 -Xmx3072m)。

解决:先确认服务器可用内存足够,再编辑 conf/server.config 中 <java-config> 的 -Xmx 并重启 BES:

sed -i 's/-Xmx2048m/-Xmx3072m/' /opt/bes/conf/server.config
cd /opt/bes/bin && ./stopserver && nohup ./startserver > /opt/bes/logs/startserver.out 2>&1 &

部署失败后,BES 会回滚该应用的部署项,重启后不会自动拉起,需要在控制台重新「部署」一次。