如何部署 Java 应用 #如何部署 Java 应用 Flynn 需要使用 [JAVA](https://github.com/heroku/heroku-buildpack-java) 或 [Gradle](https://github.com/heroku/heroku-buildpack-gradle) 构建包, 利用 [Maven](http://maven.apache.org/) 或者 [Gradle](http://www.gradle.org/) 来完成 JAVA 应用的自动构建和部署。 Flynn 使用 [OpenJDK](http://openjdk.java.net/) 来运行 JAVA 应用。 ##应用检测 Flynn 使用下面的规则检测 JAVA 应用: - 在应用的根目录下的 `pom.xml` 文件,表明此 JAVA 应用使用 Maven 构建工具。 - 在应用的根目录下的`gradlew`,`build.gradle`,或`settings.gradle`文件,表明此 JAVA 应用使用 Gradle 构建工具。 ##环境依赖 ###Maven 当使用 Maven 的时候,将所依赖的软件包加入`pom.xml`文件的`<dependencies>`配置项里。 例如,下面的`pom.xml`配置文件说明编译环境需要`log4j`的支持: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>io.flynn.example</groupId> <artifactId>flynn-example</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>flynn-example</name> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> <scope>compile</scope> </dependency> </dependencies> </project> 当包含此配置文件的应用部署到 Flynn 时,系统会自动执行如下的 Maven 命令: mvn -B -DskipTests=true clean install 上述命令会下载编译依赖的软件包,并将编译结果输出到`target`目录。 Flynn 默认使用最新版本的 Maven。如果想使用特定版本的 Maven,需要在根目录下创建`system.properties`文件,在此文件指定 Maven 的版本: maven.version=3.2.3 *使用 Maven 时,关于环境依赖的更多信息,可以参见 [Maven 环境依赖](http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html)文档。* ###Gradle 使用 Gradle 时,需要使用它的 [Java 插件](http://www.gradle.org/docs/current/userguide/java_plugin.html) ,按插件要求的格式在根目录下的`build.gradle`文件里配置所依赖的软件包。 Flynn 在编译和部署应用的过程中,会运行一系列预定义的`stage`任务。 例如,下面是一个`build.gradle`文件,里面声明了编译期间依赖`log4j`,并且定义了一个`stage`任务,完成编译清理工作: apply plugin: "java" repositories { mavenCentral() } dependencies { compile group: "log4j", name: "log4j", version: "1.2.17" } task stage (dependsOn: ["clean", "jar"]) 当包含上述配置文件的应用部署到 Flynn 时,系统自动执行下面的命令: ./gradlew stage 会下载所依赖的软件,执行编译,并将编译结果放在`build`目录中。 *注意:建议在应用里包含`gradlew`脚本,这个脚本能检测使用的 Gradle 版本。如果系统中没有,Flynn 会自动安装。但此版本是不确定的。参见 [Gradle Wrapper 页面](https://docs.gradle.org/current/userguide/gradle_wrapper.html)获取更多信息* 使用 Gradle 时,关于环境依赖的更多信息,可以参见 [Gradle 环境依赖](http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html)文档。 ###JAVA 运行环境 运行 JAVA 应用时,Flynn 默认使用 OpenJDK 8。OpenJDK 6 和 7 也是可用的。可以修改根目录下的`system.properties`文件,修改其中的`java.runtime.version`来更换版本: ! OpenJDK 6 java.runtime.version=1.6 ! OpenJDK 7 java.runtime.version=1.7 ##应用类型 可以在应用根目录下的 `Procfile` 里声明应用的类型,声明的格式是:`TYPE: COMMAND`。 ###web 一般情况下 WEB 类型的应用会包含 HTTP 路由,通信端口(`port`)等环境变量,会为应用启动一个 HTTP 服务器。 ####内嵌 Jetty 内嵌 Jetty 服务器的应用会使用环境变量中定义的端口(`port`)来启动应用,例如: import javax.servlet.http.HttpServlet; import org.eclipse.jetty.server.Server; public class MyServlet extends HttpServlet { // handler definitions public static void main(String[] args) throws Exception { Server server = new Server(Integer.valueOf(System.getenv("PORT"))); // code to set handlers and start the server } } 想了解更多关于 Jetty 嵌入的信息,请参见[嵌入 Jetty 页面](https://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty)。 假如一个应用使用 Gradle 构建工具,通过 Gradle 应用插件创建了名为`example`的应用,应用的类型在 `Procfile` 里按如下格式定义: web: build/install/example/bin/example ###外部 Jetty + WAR 包 打包成 WAR 格式的 JAVA 应用需要使用外部的 Servlet 容器来运行。 也可以让 [Marven Dependency 插件](http://maven.apache.org/plugins/maven-dependency-plugin/) 自动拷贝一个 `jetty-runner` JAR 文件的副本到`target/dependency` 目录,这需要在`pom.xml`里增加如下配置: <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.3</version> <executions> <execution> <phase>package</phase> <goals><goal>copy</goal></goals> <configuration> <artifactItems> <artifactItem> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-runner</artifactId> <version>7.5.4.v20111024</version> <destFileName>jetty-runner.jar</destFileName> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> 将应用打包成 WAR 格式,存储到 `target` 目录,在 `Procfile ` 文件里定义应用类型: web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war