如何将基于GlassFish 3.1.2.2的Maven企业级应用(EJB+WAR)部署到Heroku?
部署基于Maven的EJB+WAR企业级应用到Heroku的可行方案
我来分享几个经过验证的方案,帮你把这套基于GlassFish 3.1.2.2的Maven多模块应用部署到Heroku:
核心前提先说明
Heroku的Java运行环境默认主打Tomcat、Jetty这类轻量Servlet容器,而GlassFish 3.1.2.2是完整的Java EE 6容器,直接在Heroku dyno上跑老版本GlassFish会有资源适配和官方支持的问题。所以更务实的方向是调整应用适配Heroku的主流环境,或者用容器化绕开环境限制。
方案一:把EJB嵌入到WAR包中(推荐,成本最低)
GlassFish本身支持将EJB打包进WAR文件里(不用单独的EJB模块或EAR包),这样整个应用可以作为单个WAR部署到Heroku的Tomcat/Jetty环境,不需要完整的GlassFish容器。具体步骤如下:
调整Maven项目结构
- 如果是多模块项目:修改WAR模块的
pom.xml,添加EJB模块的依赖,设置type为ejb,确保EJB的类会被打包到WAR的WEB-INF/lib或WEB-INF/classes目录里。 - 嫌麻烦的话,直接把EJB模块的代码合并到WAR模块中,把EJB模块的打包类型改成
war,同时添加Servlet API的provided依赖:<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency>
- 如果是多模块项目:修改WAR模块的
移除GlassFish私有API依赖
- 确保所有EJB代码只用Java EE 6标准API,别用GlassFish独有的类(比如特定的数据源配置类)。把EJB相关依赖换成Java EE 6 API的provided依赖:
<dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>6.0</version> <scope>provided</scope> </dependency>
- 确保所有EJB代码只用Java EE 6标准API,别用GlassFish独有的类(比如特定的数据源配置类)。把EJB相关依赖换成Java EE 6 API的provided依赖:
配置Heroku Maven插件
- 在根项目的
pom.xml里加入Heroku Maven插件,用来自动打包部署:<plugin> <groupId>com.heroku.sdk</groupId> <artifactId>heroku-maven-plugin</artifactId> <version>3.0.0</version> <configuration> <appName>你的Heroku应用名称</appName> <processTypes> <web>java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT target/*.war</web> </processTypes> </configuration> </plugin> - 这里用
webapp-runner启动Tomcat,Heroku会自动处理动态端口和环境变量,不用手动配置。
- 在根项目的
一键部署
- 先装Heroku CLI并登录,然后在项目根目录执行:
mvn heroku:deploy,插件会自动完成打包、上传、启动的全流程。
- 先装Heroku CLI并登录,然后在项目根目录执行:
方案二:容器化部署(保留完整GlassFish环境)
如果必须要保留GlassFish 3.1.2.2的完整环境,可以用Docker打包整个应用,再部署到Heroku的容器注册表:
编写Dockerfile
- 基于OpenJDK 7(因为GlassFish 3.1.2.2只支持JDK 7)构建镜像,示例如下:
FROM openjdk:7-jre RUN apt-get update && apt-get install -y wget unzip WORKDIR /opt # 下载GlassFish 3.1.2.2安装包(注意:如果官方链接失效,换个可靠的镜像源) RUN wget http://download.oracle.com/glassfish/3.1.2.2/release/glassfish-3.1.2.2.zip RUN unzip glassfish-3.1.2.2.zip ENV GLASSFISH_HOME /opt/glassfish3 ENV PATH $PATH:$GLASSFISH_HOME/bin # 复制你的EAR/WAR包到GlassFish自动部署目录 COPY target/你的应用包.ear $GLASSFISH_HOME/domains/domain1/autodeploy/ # 启动GlassFish,绑定到0.0.0.0并使用Heroku动态端口 CMD ["asadmin", "start-domain", "--verbose", "--port", "$PORT"] - 注意:需要修改GlassFish的
domain.xml,把HTTP监听端口改成读取$PORT环境变量,不然会和Heroku的动态端口冲突。
- 基于OpenJDK 7(因为GlassFish 3.1.2.2只支持JDK 7)构建镜像,示例如下:
容器部署流程
- 安装Heroku容器插件:
heroku plugins:install heroku-container-registry - 登录容器注册表:
heroku container:login - 构建并推送镜像:
heroku container:push web - 发布容器到应用:
heroku container:release web
- 安装Heroku容器插件:
几个关键注意事项
- JDK版本强制指定:GlassFish 3.1.2.2依赖JDK 7,所以必须在项目根目录创建
system.properties文件,添加:java.runtime.version=1.7 - 资源限制:GlassFish本身比较吃内存,Heroku免费dyno可能不够用,建议测试时用付费dyno保证稳定性。
- 数据源适配:如果之前用GlassFish的domain.xml配置数据源,要改成读取Heroku提供的环境变量(比如PostgreSQL的
DATABASE_URL),用代码或Maven配置来初始化数据源,别依赖GlassFish的容器配置。
内容的提问来源于stack exchange,提问作者Bilal Dekar
相关产品推荐
相关产品推荐

