尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

JeecgBoot项目迁移宝兰德BES全流程:从Spring Boot改造到生产部署实战

JeecgBoot项目迁移宝兰德BES全流程:从Spring Boot改造到生产部署实战 1. 项目概述与核心价值最近在帮一个客户做项目迁移他们之前用的是Spring Boot内嵌Tomcat的部署方式现在因为一些合规和性能监控的硬性要求需要将JeecgBoot项目部署到国产的宝兰德应用服务器上。这个需求其实挺有代表性的现在很多政企、金融项目都在往国产化信创环境迁移宝兰德作为国内主流的应用服务器之一和JeecgBoot这个快速开发框架的结合就成了一个必须趟过去的“坑”。简单来说这个方案就是把我们熟悉的、打成jar包直接java -jar就能跑的Spring Boot应用重新打包成传统的war包然后丢到宝兰德AppServer后面简称BES这个“大容器”里跑起来。听起来好像就是换个部署方式但实际操作起来从项目配置、打包脚本、服务器部署到问题排查每一步都有不少细节需要注意。网上关于Spring Boot部署到Tomcat的教程一抓一大把但针对宝兰德这种特定国产中间件的、结合JeecgBoot这种复杂框架的详细步骤还真不多见踩坑的几率不小。这篇文章我就把自己从零开始把一个完整的JeecgBoot单体应用成功部署到宝兰德BES 10.1上的全过程包括中间遇到的各类“奇葩”报错和解决方案毫无保留地分享出来。无论你是刚开始接触信创部署的开发者还是正在为项目迁移发愁的运维希望这篇近万字的实录能给你一条清晰的路径节省你大量摸索的时间。2. 环境准备与项目改造2.1 基础环境清单在动手之前得先把“战场”打扫干净工具备齐。下面这个清单是我实际验证过的组合版本兼容性上比较稳妥开发框架JeecgBoot 3.5.0基于Spring Boot 2.6.13。选择这个版本是因为它相对稳定且Spring Boot 2.6.x与宝兰德BES 10.1的兼容性测试更充分。不建议一上来就用最新的3.x或Spring Boot 3.x兼容性问题会让你头疼。应用服务器宝兰德应用服务器 BES 10.1.0.0。务必从官网获取对应版本并确认其支持的Java EE或Jakarta EE规范版本。BES 10.1通常对应Java EE 7或8。JDKOracle JDK 1.8.0_281 或 OpenJDK 8同等版本。这是JeecgBoot 3.x和BES 10.1共同兼容的主流版本。关键点必须确保开发环境、打包环境和服务器运行环境的JDK版本一致避免因class文件版本差异导致无法启动。构建工具Maven 3.6.3 或 Gradle。本文以Maven为例。数据库根据项目需要MySQL 5.7/8.0 Oracle 11g/19c等。提前准备好数据库驱动jar包。注意宝兰德BES的安装和域创建不是本文重点但请确保你已经成功安装BES并创建了一个用于部署的应用域Domain知道其管理控制台默认端口19090的访问地址、用户名和密码。同时记下该域对应的实际部署目录如/home/bes/domains/mydomain/applications。2.2 JeecgBoot项目改造关键步骤JeecgBoot默认是打包成可执行jar的Spring Boot应用要部署到外部容器需要做几个关键改造。2.2.1 修改打包方式与排除内嵌容器首先打开项目根目录的pom.xml文件。修改打包类型找到packaging标签将其值从jar改为war。packagingwar/packaging排除内嵌Tomcat在spring-boot-starter-web依赖中排除掉内嵌的Tomcat。因为我们要用外部的宝兰德服务器。dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId !-- 排除内嵌tomcat -- exclusions exclusion groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-tomcat/artifactId /exclusion /exclusions /dependency添加Servlet API依赖作用域为provided因为war包运行在外部容器中容器本身会提供Servlet API所以我们只需要在编译时引入打包时不需要包含进去。dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version !-- 版本需与BES支持的Servlet规范匹配 -- scopeprovided/scope /dependency2.2.2 改造Spring Boot启动类这是最关键的一步。我们需要让启动类继承SpringBootServletInitializer并重写configure方法。这样当war包被外部容器加载时才能正确引导Spring Boot应用启动。找到你的主启动类通常是JeecgApplication或Application进行如下改造import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; SpringBootApplication public class JeecgApplication extends SpringBootServletInitializer { // 1. 继承 public static void main(String[] args) { SpringApplication.run(JeecgApplication.class, args); } Override // 2. 重写configure方法 protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { // 指向原有的启动类这是告诉外部容器如何启动Spring Boot应用 return builder.sources(JeecgApplication.class); } }2.2.3 处理静态资源与配置文件路径Spring Boot内嵌容器时静态资源如图片、前端文件和配置文件如application.yml有默认的加载规则。部署到外部容器后这些规则可能失效尤其是涉及到文件上传路径、模板引擎路径等。文件上传路径检查代码中所有文件上传保存的路径。避免使用相对路径如./upload推荐使用绝对路径或者通过配置文件配置一个基础路径在代码中拼接。例如在application.yml中配置jeecg: upload: path: /home/bes/upload/ # BES服务器上的一个绝对路径然后在代码中引用Value(${jeecg.upload.path})。务必确保BES的运行用户对该路径有读写权限。前端资源访问JeecgBoot前后端分离版本通常前端独立部署问题不大。如果是单体混合部署确保你的静态资源src/main/resources/static/下的内容能被正确打包到war包的根目录或WEB-INF外。可以通过配置spring.mvc.static-path-pattern和spring.web.resources.static-locations来调整但通常继承SpringBootServletInitializer后默认规则在外部容器中也能工作。配置文件application.yml或application.properties必须放在war包的WEB-INF/classes目录下这通常由Maven标准结构保证。确保生产环境的配置如数据库连接、Redis地址已正确配置在application-prod.yml中并通过激活prodprofile来使用。2.3 生成War包改造完成后在项目根目录下执行Maven打包命令mvn clean package -DskipTests -P prod-DskipTests跳过测试加快打包速度。-P prod激活prodprofile使用生产环境配置。打包成功后在target目录下会生成一个{你的项目名}.war文件例如jeecg-boot-3.5.0.war。这个war包就是我们最终要部署到宝兰德上的产物。实操心得第一次打包后建议用解压软件如7-Zip打开生成的war包检查一下结构。重点看1.WEB-INF/classes/下是否有你的配置文件2.WEB-INF/lib/下是否包含了所有必要的依赖jar包应该没有spring-boot-starter-tomcat3. 根目录下是否有META-INF/MANIFEST.MF文件。正确的结构是成功部署的第一步。3. 宝兰德BES服务器配置与部署3.1 部署前服务器检查把war包上传到BES服务器之前先对服务器环境做一次体检。JDK环境变量登录BES服务器检查JAVA_HOME环境变量是否指向正确的JDK 8路径。可以通过echo $JAVA_HOME和java -version命令验证。BES域状态确保你计划部署的那个BES应用域Domain处于运行状态。可以进入BES安装目录下的bin文件夹使用./startManagedServer.sh或.cmd启动对应的受管服务器Managed Server。端口与防火墙确认BES服务器的HTTP监听端口默认8080和管理端口默认19090在防火墙中是放行的。如果你修改了默认端口请相应调整。文件权限确保你用于上传war包和BES运行的用户如bes或root对BES的域目录、应用部署目录有读写和执行权限。3.2 通过管理控制台部署War包这是最常用的部署方式通过Web界面操作比较直观。登录控制台在浏览器访问http://服务器IP:19090/console使用管理员账号登录宝兰德BES管理控制台。进入部署页面在左侧导航栏找到“部署”或“Applications”模块点击进入。安装新应用点击“安装”或“Deploy”按钮。通常会让你选择部署源。上传War文件选择“上传文件”或类似选项点击浏览选择你从本地上传到服务器某个临时目录的war包或者直接在本地选择上传。点击“下一步”。选择部署目标在接下来的页面选择部署目标为你的“受管服务器”或你创建的那个集群而不是管理服务器。然后继续下一步。配置部署设置应用名称可以保持默认即war包名也可以改为一个更简短易懂的名字如jeecg-app。这个名称将用于后续管理和访问上下文路径。上下文根这是关键默认可能是/你的war包名。如果你希望通过根路径访问如http://ip:port/这里可以改为/。但要注意如果BES上部署了多个应用根路径可能会冲突。我建议保留一个明确的上下文根比如/jeecg这样访问地址就是http://ip:port/jeecg。JeecgBoot的前端路由需要与此匹配。安全模型选择DD Only仅使用部署描述符即可除非你有特别的安全需求。其他高级设置如类加载器顺序、启动顺序可以先保持默认。完成并启动检查摘要信息无误后点击“完成”。部署完成后通常会在应用列表里看到你的应用状态可能是“准备就绪”或“已停止”。选中它点击“启动”-“为所有请求提供服务”。3.3 命令行与自动部署对于生产环境或需要CI/CD自动化的场景通过命令行或直接文件部署更高效。3.3.1 使用WLSTWebLogic Scripting Tool命令行部署WLST是宝兰德仿照WebLogic提供的强大脚本工具。你可以编写一个Python脚本来完成部署。# deploy.py connect(weblogic, your_password, t3://localhost:19090) # 连接管理服务器 deploy(jeecg-app, /path/to/your/jeecg-boot-3.5.0.war, targetsManagedServer_1) startApplication(jeecg-app) disconnect() exit()然后通过BES自带的wlst.sh执行这个脚本cd /home/bes/bes10.1/wlserver_10.3/common/bin/ ./wlst.sh /path/to/deploy.py3.3.2 直接文件系统部署自动部署目录宝兰德BES支持“自动部署”。你可以直接将war包复制到特定目录BES会自动检测并部署。找到你创建的应用域下的autodeploy目录。路径通常像/home/bes/domains/mydomain/autodeploy/。将你的jeecg-boot-3.5.0.war文件直接复制到这个目录。BES的部署管理器会定期扫描此目录或立即触发自动将war包部署到对应的受管服务器上。部署后的应用文件会展开在applications目录下。注意事项自动部署虽然方便但在生产环境要谨慎使用因为缺乏部署过程的确认和回滚机制。更推荐通过控制台或WLST脚本进行可控的部署。3.4 关键配置调优应用部署上去能跑只是第一步要跑得稳、跑得快还需要针对BES和JeecgBoot做一些调优。JVM参数调整在BES控制台中找到你的受管服务器配置在“服务器启动”-“参数”中可以设置JVM启动参数。对于JeecgBoot这种内存消耗较大的Java应用建议调整-Xms2048m -Xmx4096m -XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m根据服务器实际内存调整堆大小。-Dfile.encodingUTF-8也最好加上避免乱码。数据源配置强烈建议在BES控制台中配置JNDI数据源而不是在JeecgBoot的application.yml里直接写JDBC URL。这样做的好处是连接池由应用服务器统一管理支持热部署且配置与代码分离。在控制台“服务”-“数据源”中创建新的数据源。填写数据库驱动类名、URL、用户名、密码。测试连接成功后记下你设置的JNDI名称例如jdbc/jeecgDB。在JeecgBoot的application.yml中将原来的spring.datasource.url等配置注释掉改为spring: datasource: jndi-name: java:comp/env/jdbc/jeecgDB同时需要在src/main/webapp/WEB-INF/下如果不存在则创建创建一个web.xml文件声明资源引用Spring Boot通常省略web.xml但外部容器JNDI查找可能需要?xml version1.0 encodingUTF-8? web-app ... resource-ref descriptionDB Connection/description res-ref-namejdbc/jeecgDB/res-ref-name res-typejavax.sql.DataSource/res-type res-authContainer/res-auth /resource-ref /web-app会话超时与持久化在BES控制台的应用配置中可以设置会话超时时间。对于管理系统通常设置为30分钟或更长。如果有多实例集群需求还需要配置会话持久化如持久化到数据库或Redis。4. 启动故障排查与常见问题部署过程很少一帆风顺下面是我遇到和收集的一些典型问题及解决方法。4.1 应用启动失败类问题问题1控制台报错ClassNotFoundException或NoClassDefFoundError涉及Spring Boot或Tomcat相关类。原因分析最可能的原因就是内嵌Tomcat没有排除干净。虽然你在spring-boot-starter-web中排除了但其他依赖可能间接引入了Tomcat组件例如spring-boot-starter-undertow如果存在。另外scope为provided的Servlet API被意外打包进去了或者BES提供的版本与编译版本冲突。解决方案在项目根目录下执行mvn dependency:tree tree.txt生成依赖树搜索tomcat、undertow、jetty等关键词检查是否有漏网之鱼。如果有找到对应的依赖将其排除。检查所有javax.servlet或jakarta.servlet相关的依赖确保其scope为provided。解压生成的war包查看WEB-INF/lib/下是否有spring-boot-starter-tomcat-*.jar或tomcat-embed-*.jar如果有说明排除不成功。问题2应用启动时卡住日志停留在Starting Servlet Engine或没有任何错误但访问不了。原因分析可能是应用初始化特别是数据库连接、Redis连接、Spring Bean加载过慢或失败导致服务器认为应用没有成功启动。也可能是端口冲突。解决方案查看BES受管服务器的日志文件通常位于domains/your_domain/servers/ManagedServer_1/logs/ManagedServer_1.log。这是排查问题的第一现场仔细查看最后的错误或警告信息。在JeecgBoot的application-prod.yml中增加Spring Boot的详细日志级别以便看到更详细的启动过程logging: level: org.springframework: DEBUG com.jeecg: DEBUG重新打包部署查看BES日志中是否有数据库连接失败、Bean创建失败等信息。检查服务器端口占用。使用netstat -tlnp | grep :8080你的应用端口查看端口是否被正确监听。问题3应用能启动但访问首页或接口出现404错误。原因分析上下文根Context Root配置不正确。可能你在BES控制台设置的上下文根是/jeecg但前端代码或你访问时用的路径是/或者反过来。解决方案确认BES控制台中该应用的“上下文根”设置。访问时使用完整的URL如http://ip:port/上下文根/。如果是前后端分离项目确保前端配置的baseURL或proxy设置指向了正确的后端上下文路径。对于单体项目检查JeecgBoot中是否有配置server.servlet.context-path如果配置了需要与BES的上下文根保持一致或者更佳实践是删除JeecgBoot配置文件中的server.servlet.context-path完全由BES控制台的上下文根设置来决定避免冲突。4.2 运行时类问题问题4文件上传失败提示“找不到路径”或“权限不足”。原因分析在外部容器中应用的当前工作目录user.dir可能不是你所期望的。使用相对路径进行文件读写极易出错。解决方案绝对路径如2.2.3所述在配置文件中配置一个绝对路径并确保BES进程用户有读写权限。使用BES域内的目录可以将上传目录设置在BES域目录下如/home/bes/domains/mydomain/upload/权限相对好管理。代码检查避免使用File类的相对路径方法使用Paths.get(绝对路径字符串)。问题5日志文件没有输出到指定位置或者乱码。原因分析Spring Boot默认的日志配置Logback在外部容器中可能不会自动加载其配置文件如logback-spring.xml或者编码不匹配。解决方案确保logback-spring.xml文件在src/main/resources目录下并且被打包到war包的WEB-INF/classes中。在logback-spring.xml中使用绝对路径来定义日志文件的输出位置或者使用相对路径时明确基于一个已知的系统属性如catalina.base对于Tomcat但BES是bes.home或user.dir。更稳妥的方法是读取自定义的系统属性或环境变量。在BES的JVM启动参数中可以强制指定日志配置文件和编码-Dlogging.config/path/to/your/logback-spring.xml -Dfile.encodingUTF-8问题6使用JNDI数据源连接数据库失败。原因分析JNDI名称查找失败、数据源配置错误、数据库驱动未放入BES类路径。解决方案确认BES控制台中的数据源配置正确且状态为“运行中”。确认JeecgBoot中spring.datasource.jndi-name的值与BES中配置的JNDI名称完全一致包括java:comp/env/前缀取决于BES的全局还是应用级JNDI。将数据库驱动jar包如mysql-connector-java-8.0.xx.jar放入BES域的lib目录下如/home/bes/domains/mydomain/lib/然后重启受管服务器。不要把驱动jar包打到war包里。检查web.xml中的resource-ref配置是否正确。4.3 性能与稳定性问题问题7应用运行一段时间后内存持续增长最终OOMOutOfMemory。原因分析可能是内存泄漏也可能是JVM堆内存设置过小。JeecgBoot应用本身占用内存就不小加上BES容器的开销。解决方案首先按3.4节调整JVM参数给予足够的堆内存和元空间。使用BES或JDK自带的监控工具如JConsole、VisualVM连接BES的JVM监控内存使用情况观察是哪个区域Heap, Metaspace在持续增长。在BES的JVM参数中添加OOM时生成Heap Dump的选项便于后续分析-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/path/to/dump.hprof检查应用代码特别是缓存的使用如Ehcache、本地Map缓存是否有不当的引用导致无法GC。问题8应用响应变慢线程阻塞。原因分析数据库连接池耗尽、Redis连接异常、存在慢SQL、或应用内部有同步锁竞争。解决方案检查BES中配置的数据源连接池参数如最大连接数、最小连接数、超时时间等根据实际并发量调整。查看BES日志和数据库慢查询日志定位慢SQL并进行优化。如果使用了Redis检查Redis连接是否稳定网络是否有延迟。使用jstack命令或Arthas等工具在应用响应慢时抓取线程栈分析是否有线程长时间阻塞在某个锁或IO操作上。5. 进阶部署与维护建议5.1 集群与负载均衡部署对于高可用、高并发的生产环境单节点部署显然不够。JeecgBoot部署到宝兰德集群是常见需求。BES集群配置首先需要在BES管理控制台中创建集群Cluster并将多个受管服务器Managed Server加入这个集群。这个过程涉及节点发现、通信端口配置等需参考宝兰德官方文档仔细操作。应用部署在部署应用时部署目标选择你创建好的集群而不是单个服务器。BES会自动将应用同步部署到集群中的所有节点。会话共享这是集群部署的核心。默认情况下用户的会话HttpSession是存在单个服务器内存中的。如果用户下次请求被负载均衡到另一台服务器会话就会丢失。解决方案是配置会话持久化数据库持久化在BES控制台中可以配置会话持久化到数据库。你需要创建一个专用的表来存储会话数据。Redis集中式缓存更推荐的方式。利用JeecgBoot已经集成的Redis通过Spring Session将HttpSession存储到Redis中。确保集群中的所有节点都连接到同一个Redis实例或集群。需要在pom.xml中添加spring-session-data-redis依赖并在配置文件中启用Spring Session。文件共享如果应用有文件上传功能上传的文件必须存储在一个所有集群节点都能访问的共享存储中如NAS、对象存储OSS或分布式文件系统如FastDFS。绝对不能在本地磁盘。5.2 持续集成与自动化部署将打包和部署过程脚本化是提升效率、减少人为错误的关键。CI/CD流水线设计代码提交触发Jenkins/GitLab CI等工具。构建阶段执行mvn clean package -DskipTests -P prod生成war包。部署阶段通过SCP或SFTP将war包上传到BES服务器的指定目录如/tmp。控制部署通过SSH连接到BES服务器执行WLST脚本如3.3.1节所示进行部署更新。或者更优雅的方式是调用BES提供的REST管理接口如果支持。健康检查部署后脚本自动访问一个预定的健康检查接口如/jeecg-boot/actuator/health验证应用是否成功启动。版本管理与回滚在WLST脚本或部署流程中实现旧版本war包的备份和新版本war包的部署。如果健康检查失败自动触发回滚脚本将备份的旧版本重新部署。5.3 监控与日志收集生产环境没有监控就是“裸奔”。BES服务器监控利用宝兰德自带的监控控制台监控JVM内存、CPU使用率、线程池、连接池等关键指标。应用性能监控APM集成SkyWalking、Pinpoint等APM工具。以SkyWalking为例需要在BES的JVM启动参数中添加Agent-javaagent:/path/to/skywalking-agent/skywalking-agent.jar -DSW_AGENT_NAMEjeecg-bes -DSW_AGENT_COLLECTOR_BACKEND_SERVICESyour.collector.ip:11800这样可以在SkyWalking UI上看到JeecgBoot应用的拓扑图、接口响应时间、慢追踪等详细信息。日志集中收集将BES服务器日志和各应用节点的业务日志通过FileBeat、Logstash等工具收集到ELKElasticsearch, Logstash, Kibana或Graylog等集中日志平台方便统一检索和分析。5.4 安全加固建议BES控制台安全修改默认的管理端口19090、管理员用户名和密码。限制管理控制台的访问IP。应用服务器安全定期更新BES的补丁。在服务器层面配置防火墙只开放必要的端口如应用端口8080、管理端口19090。应用自身安全确保JeecgBoot中的Shiro或Spring Security配置正确不存在未授权访问漏洞。对上传文件进行严格的类型和内容检查防止上传恶意文件。数据库安全使用BES的JNDI数据源避免在应用配置文件中明文暴露数据库密码。定期更换数据库密码。整个集成部署的过程从项目改造到生产上线是一个系统工程。最深的体会就是“耐心看日志”和“理解原理”是解决所有问题的万能钥匙。BES的日志、Spring Boot的启动日志里面包含了绝大部分问题的答案。遇到报错不要慌先逐字逐句把错误信息读明白然后根据错误关键词去搜索或者对照本文提到的常见问题列表十有八九能找到方向。
返回列表