將 WAR 檔案重新封裝成 JAR 檔案

如果您要遷移至最新支援的 Java 版本,且應用程式未使用舊版隨附服務,就必須將 App Engine 網頁應用程式重新封裝為可執行的 JAR 檔案。

應用程式必須有 Main 類別,可啟動網路伺服器,回應通訊埠 8080 的 HTTP 要求,這可能由 PORT 環境變數指定。

例如: <

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.Configuration.ClassList;
import org.eclipse.jetty.webapp.WebAppContext;

/** Simple Jetty Main that can execute a WAR file when passed as an argument. */
public class Main {

  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.err.println("Usage: need a relative path to the war file to execute");
      System.exit(1);
    }
    System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StrErrLog");
    System.setProperty("org.eclipse.jetty.LEVEL", "INFO");

    // Create a basic Jetty server object that will listen on port defined by
    // the PORT environment variable when present, otherwise on 8080.
    int port = Integer.parseInt(System.getenv().getOrDefault("PORT", "8080"));
    Server server = new Server(port);

    // The WebAppContext is the interface to provide configuration for a web
    // application. In this example, the context path is being set to "/" so
    // it is suitable for serving root context requests.
    WebAppContext webapp = new WebAppContext();
    webapp.setContextPath("/");
    webapp.setWar(args[0]);
    ClassList classlist = ClassList.setServerDefault(server);

    // Enable Annotation Scanning.
    classlist.addBefore(
        "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
        "org.eclipse.jetty.annotations.AnnotationConfiguration");

    // Set the the WebAppContext as the ContextHandler for the server.
    server.setHandler(webapp);

    // Start the server! By using the server.join() the server thread will
    // join with the current thread. See
    // "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()"
    // for more details.
    server.start();
    server.join();
  }
}

WAR 遷移範例 (Java 21)

以下操作說明示範如何將 App Engine hello-world WAR 應用程式重新封裝為 JAR,以便在 Java 21 執行階段中執行。

遷移作業會使用 appengine-simple-jetty-main 構件。這會提供 Main 類別,其中包含載入 WAR 檔案的簡單 Jetty 網路伺服器,並將應用程式封裝至可執行的 JAR 檔案:

  1. 將 Embedded Jetty Server 構件複製到本機電腦:

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples
    

    您也可以下載 zip 格式的範例檔案,然後將檔案解壓縮。

  2. 變更為包含程式碼範例的目錄:

    cd java-docs-samples/flexible/repacking-legacy-applications/appengine-simple-jetty-main/
    
  3. 建構 Jetty 執行器 JAR:

    mvn install
    

    這會在 target/ 目錄中產生 jetty-jar-with-dependencies.jar。

  4. 為 Jetty 伺服器設定 pom.xml 建構檔案:

    • 編譯器屬性 (Java 21):
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <jetty.version>9.4.57.v20241219</jetty.version>
      </properties>
    • 內嵌 Jetty 依附元件: <0x0A
      <dependencies>
        <!-- Embedded Jetty dependencies -->
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-server</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-webapp</artifactId>
          <version>${jetty.version}</version>
          <type>jar</type>
        </dependency>
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-util</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-annotations</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <!-- extra explicit dependency needed because there is a JSP in the sample-->
        <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>apache-jsp</artifactId>
          <version>${jetty.version}</version>
        </dependency>
      </dependencies>
    • maven-assembly-plugin 設定:
      
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
          <finalName>jetty</finalName>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.example.appengine.jetty.Main</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      
  5. 放置產生的 jetty-jar-with-dependencies.jar 和應用程式 WAR 檔案。例如,位於相同目錄的 helloworld.war。

  6. 在應用程式目錄中建立 app.yaml 檔案,指定 Java 21 執行階段,並建立 entrypoint 元素來呼叫 jetty-jar-with-dependencies.jar 檔案,然後將 WAR 檔案做為引數傳遞:

    runtime: java21
    entrypoint: 'java -jar jetty-jar-with-dependencies.jar helloworld.war'
    
  7. 如要在本機執行應用程式,請按照下列步驟操作:

    1. 以 WAR 檔案做為引數啟動伺服器:

      java -jar jetty-jar-with-dependencies.jar helloworld.war
      
    2. 在網路瀏覽器中,輸入下列網址:

      http://localhost:8080

  8. 如要部署您的應用程式:

    gcloud 工具

    gcloud app deploy

    Maven 外掛程式

    mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

    將 PROJECT_ID 替換為 Google Cloud 專案 ID。如果 pom.xml 檔案已指定專案 ID,則不需要在執行的指令中加入 -Dapp.deploy.projectId 屬性。