如何在没有 web.xml 的情况下将 App Engine 项目更新到 Java 11?

2024-03-18

我有一个应用程序引擎项目。Here https://github.com/KevinWorkman/GoogleCloudExamples/tree/master/hello-world是一个示例存储库,但它只包含几个文件:

pom.xml

<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.happycoding</groupId>
  <artifactId>google-cloud-hello-world</artifactId>
  <version>1</version>
  <packaging>war</packaging>

  <properties>
    <!-- App Engine currently supports Java 8 -->
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <failOnMissingWebXml>false</failOnMissingWebXml>
  </properties>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>com.google.appengine</groupId>
        <artifactId>appengine-maven-plugin</artifactId>
        <version>1.9.71</version>
      </plugin>
    </plugins>
  </build>
</project>

appengine-web.xml

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>MY_PROJECT_ID_HERE</application>
  <version>1</version>
  <threadsafe>false</threadsafe>
  <sessions-enabled>true</sessions-enabled>
  <runtime>java8</runtime>
</appengine-web-app>

HelloWorldServlet.java

package io.happycoding.servlets;

import java.io.IOException;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloWorldServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    response.setContentType("text/html;");
    response.getOutputStream().println("<h1>Hello world!</h1>");
  }
}

我没有 web.xml 文件因为我正在使用@WebServlet改为注释。多年来,这一直非常有效。

唯一的问题是我只能使用 Java 8,所以我很高兴看到 App Engineannounce https://cloud.google.com/blog/products/application-development/turn-it-up-to-eleven-java-11-runtime-comes-to-app-engine对 Java 11 的支持。我现在正在尝试将我的 App Engine 项目升级到 Java 11。

我首先改变了appengine-web.xml文件包含这一行:

<runtime>java11</runtime>

我也改变了pom.xml file:

<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>

I run mvn appengine:devserver(在此更改之前工作正常),我收到此错误:

ClassLoader is jdk.internal.loader.ClassLoaders$AppClassLoader@78308db1, not a URLClassLoader.

I gather https://stackoverflow.com/questions/55490900/unable-to-build-bookshelf-app-for-java-on-app-engine-standard-environment-exam这是因为 App Engine Maven 插件本身需要 Java 8。我还了解到App Engine Maven 插件已弃用 https://cloud.google.com/appengine/docs/standard/java/tools/migrate-maven,并且我应该升级到 Cloud SDK Maven 插件。好的。

我跟随本指南 https://cloud.google.com/appengine/docs/standard/java11/using-maven我改变了我的插件pom.xml文件到此:

<plugin>
   <groupId>com.google.cloud.tools</groupId>
   <artifactId>appengine-maven-plugin</artifactId>
   <version>2.2.0</version>
</plugin>

然后我跑mvn package appengine:run(当然,因为运行开发服务器的命令也发生了变化),但现在我收到此错误:

 java.io.FileNotFoundException: /home/kevin/gcloud-tutorials/hello-world/target/hello-world-1/WEB-INF/web.xml (No such file or directory)

该错误表示找不到web.xml文件,但我不需要这个文件,因为我正在使用@WebServlet注解!我的pom.xml文件还包含一个<failOnMissingWebXml>false</failOnMissingWebXml>属性,但我不知道这是否对新插件有任何作用。

我错过了一个步骤或财产吗?如何升级我的 App Engine 项目以使用 Java 11,而不需要web.xml file?


App Engine 的 Java 8 运行时和 Java 11 运行时之间存在一些相当巨大的差异。

具体来说,Java 8 运行时包含一个自动运行代码的 Jetty Web 服务器,但 Java 11 运行时不再包含它,因此您必须自己包含它。

有一个迁移指南here https://cloud.google.com/appengine/docs/standard/java11/java-differences但我发现这非常令人困惑,所以我将尝试在此处概述步骤:

第 1 步:迁移自appengine-web.xml to app.yaml.

删除你的appengine-web.xml文件,并创建一个新的app.yaml文件。我的app.yaml文件仅包含一行:

runtime: java11

步骤 2:添加运行 Web 服务器的主入口点类。

有很多方法可以做到这一点,但我就是这么做的:

package io.happycoding;

import java.net.URL;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;

/**
 * Starts up the server, including a DefaultServlet that handles static files,
 * and any servlet classes annotated with the @WebServlet annotation.
 */
public class ServerMain {

  public static void main(String[] args) throws Exception {

    // Create a server that listens on port 8080.
    Server server = new Server(8080);
    WebAppContext webAppContext = new WebAppContext();
    server.setHandler(webAppContext);

    // Load static content from inside the jar file.
    URL webAppDir =
        ServerMain.class.getClassLoader().getResource("META-INF/resources");
    webAppContext.setResourceBase(webAppDir.toURI().toString());

    // Enable annotations so the server sees classes annotated with @WebServlet.
    webAppContext.setConfigurations(new Configuration[]{ 
      new AnnotationConfiguration(),
      new WebInfConfiguration(), 
    });

    // Look for annotations in the classes directory (dev server) and in the
    // jar file (live server)
    webAppContext.setAttribute(
        "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", 
        ".*/target/classes/|.*\\.jar");

    // Handle static resources, e.g. html files.
    webAppContext.addServlet(DefaultServlet.class, "/");

    // Start the server! ????
    server.start();
    System.out.println("Server started!");

    // Keep the main thread alive while the server is running.
    server.join();
  }
}

此类使用 Jetty 运行 Web 服务器,然后将其余代码添加到该 Web 服务器。此代码假设所有内容都将打包在同一个中.jar file.

第三步:修改pom.xml

Your pom.xml需要一些东西:

  1. 您正在运行的 Web 服务器的依赖项。我用的是码头。
  2. 用于打包代码的插件。我选择将我的打包为一个 uber jar,所以我使用maven-resources-plugin and maven-shade-plugin.
  3. 用于在本地运行代码的插件。老人appengine-maven-plugin不适用于本地部署,因为它仍然需要appengine-web.xml因为某些原因。因为我选择了 uber jar 方法,所以我使用exec-maven-plugin.
  4. The appengine-maven-plugin仍然可以用于部署到实时服务器,因此您仍然需要它。

如果这听起来令人困惑,那么你是对的。但把所有这些放在一起,这就是我的想法:

<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.happycoding</groupId>
  <artifactId>app-engine-hello-world</artifactId>
  <version>1</version>

  <properties>
    <!-- App Engine currently supports Java 11 -->
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <jetty.version>9.4.31.v20200723</jetty.version>

    <!-- Project-specific properties -->
    <mainClass>io.happycoding.ServerMain</mainClass>
    <googleCloudProjectId>YOUR_PROJECT_ID_HERE</googleCloudProjectId>
  </properties>

  <dependencies>
    <!-- Java Servlets API -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>

    <!-- Jetty -->
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-server</artifactId>
      <version>${jetty.version}</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-annotations</artifactId>
      <version>${jetty.version}</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <!-- Copy static resources like html files into the output jar file. -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.7</version>
        <executions>
          <execution>
            <id>copy-web-resources</id>
            <phase>compile</phase>
            <goals><goal>copy-resources</goal></goals>
            <configuration>
              <outputDirectory>
                ${project.build.directory}/classes/META-INF/resources
              </outputDirectory>
              <resources>
                <resource><directory>./src/main/webapp</directory></resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>

      <!-- Package everything into a single executable jar file. -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals><goal>shade</goal></goals>
            <configuration>
              <createDependencyReducedPom>false</createDependencyReducedPom>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>${mainClass}</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>

      <!-- Exec plugin for deploying the local server. -->
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>${mainClass}</mainClass>
        </configuration>
      </plugin>

      <!-- App Engine plugin for deploying to the live site. -->
      <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>appengine-maven-plugin</artifactId>
        <version>2.2.0</version>
        <configuration>
          <projectId>${googleCloudProjectId}</projectId>
          <version>1</version>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

我将所有这些放入一个可用的示例项目中here https://github.com/KevinWorkman/HappyCoding/tree/gh-pages/examples/google-cloud/google-cloud-example-projects/app-engine-hello-world.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在没有 web.xml 的情况下将 App Engine 项目更新到 Java 11? 的相关文章

  • 为什么这不会绘制图像?

    我想做的是 当我运行应用程序时 它会启动线程并且图像显示 3 秒 3000 毫秒 然后线程停止运行 图片路径正确 图片文件存在 线程本身运行 但是 图像似乎没有显示 可能出什么问题了 这是我的代码 package org main impo
  • Java Swing透明JPanel问题

    我有一个 JLayeredPane 其中添加了 3 个 JPanel 我将 JPanel 设为透明 未设置背景并 setOpaque false 我在 JPanel 上绘制线条 只有最后添加的 JPanel 上的线条可见 其他 JPanel
  • 使用 Java 的 OpenId 提供者/服务器

    我正在尝试使用 OpenId 服务增强现有的 Java Web 应用程序 以便登录用户可以使用我的 Web 应用程序作为 OpenId 提供程序登录另一个启用 OpenId 的应用程序 My first attempt was to use
  • 通过 RMI 的服务器,无需注册

    我有一个可以通过 RMI 连接的服务对象 目前我正在这样做 Server Registry r LocateRegistry createRegistry 1234 r bind server UnicastRemoteObject exp
  • 32 位数字中 1 的数量

    我正在寻找一种在 32 位数字中包含 1 数量的方法 之间不使用循环 任何人都可以帮助我并向我提供代码或算法吗 这样做 提前致谢 See Integer bitCount int http java sun com javase 6 doc
  • 可以显式删除 lambda 的序列化支持

    As 已经知道 https stackoverflow com a 22808112 2711488很容易添加序列化当目标接口尚未继承时支持 lambda 表达式Serializable 就像 TargetInterface Seriali
  • Encog - 如何加载神经网络的训练数据

    The NeuralDataSet我在实际中看到的对象除了 XOR 之外什么都没有 它只是两个小数据数组 我无法从文档中找出任何内容MLDataSet 似乎所有内容都必须立即加载 但是 我想循环遍历训练数据 直到到达 EOF 然后将其算作
  • java.lang.IllegalArgumentException:比较方法违反了其一般契约[重复]

    这个问题在这里已经有答案了 您好 下面是我的比较器的比较方法 我不确定出了什么问题 我在堆栈溢出上查找了其他类似标题的问题和答案 但不确定我的方法出了什么问题 但我不断收到 java lang IllegalArgumentExceptio
  • 正则表达式或用单个空格替换多个空格的方法

    你能告诉我有没有办法在java或spring中用单个空格替换多个空格 有相同的 stringUtils 函数吗 like 1 test test test test 2 test test test test 3 test test tes
  • Cloud Functions for Firebase 中的套接字挂起错误

    我有一个由 Pub Sub 事件触发的云函数 它用请求 承诺 https github com request request promise从我用于数据的 API 发出多个 GET 请求 它在 Cloud Functions Emulat
  • Spring Data (JPA) 多个存储库,没有很多类

    在我当前的项目中 我使用 Spring Data JPA 并且有 20 多个 Entity类 我想为它们创建存储库 但创建另一个类 每个类适用于任何模型 Repository注释似乎是某种矫枉过正和大量 重复 代码 所有存储库类将如下所示
  • kafka消费端Offsets的一致性

    我有复制因子为 3 的卡夫卡主题min insync replicas 2 一个向该主题发送 X 条消息的生产者acks all 一段时间后 1 分钟内 在所有消息发送到主题后 将使用 java kafka 客户端为此主题创建新的消费者 使
  • Java ZIP - 如何解压缩文件夹?

    是否有任何示例代码 如何将 ZIP 中的文件夹部分解压到我想要的目录中 我已将文件夹 FOLDER 中的所有文件读取到字节数组中 如何从其文件结构创建 我不确定你所说的部分是什么意思 您的意思是在没有 API 帮助的情况下自己完成吗 如果您
  • 如何在生产中安全地更改会话 cookie 域或名称?

    我们最近意识到我们的会话 cookie 正在被写入我们网站的完全限定域名 www myapp com 例如 MYAPPCOOKIE 79D5DB83 domain www myapp com 我们希望将其切换为可以跨子域共享的cookie
  • 测试 Hessian remoting-servlet.xml

    我们使用 Hessian 来实现富客户端和服务器之间的通信 由于移动和重命名 remoting servlet xml 中的条目有时会与实际的类名不匹配 因此 我正在寻找一种简单的方法来测试远程处理 xml 有没有简单的方法可以做到这一点
  • 飞碟中的外部 CSS

    我想知道如何在 Flying Saucer 中包含外部 CSS 在此之前THB我检查了所有可用的链接StackOverflow但它们没有帮助 这就是为什么我自己做这个的原因 TestCSS xhtml重命名版本TestCSS html 所以
  • 用于验证 InetSocketAddresses 的正则表达式(ipv4/v6 + 端口地址)

    我在寻找testedipv4 和 ipv6 的正则表达式InetSocket地址 http download oracle com javase 6 docs api java net InetSocketAddress html toSt
  • 使用从 java 程序调用的 Windows 命令提示符将具有多个连续空格的字符串作为参数传递给 jar 文件

    我想使用在另一个java程序中调用的Windows命令提示符将带有多个连续空格的字符串作为参数传递给jar文件 java 文件是这样的 它打印它的所有参数 package src public class myClass public st
  • 为什么ArrayList的非静态内部类SubList有一个成员变量“parent”?

    java util ArrayList SubList 是 java util ArrayList 的非静态内部类 这意味着它保存对其封闭类的引用 我们可以使用ArrayList this来访问java util ArrayList的成员
  • Java:将秒转换为分钟、小时和天[重复]

    这个问题在这里已经有答案了 任务是 输出应如下所示 最好回显输入 您输入了 500 000 秒 即 5 天 18 小时 53 分钟 20 秒 5天18 53 20小时 我该怎么做呢 最容易理解和做到的方法是什么 讲师还说 没有硬编码 我不太

随机推荐

  • 是否可以使用 owl carousel 实现圆形/无限轮播? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在使用猫头鹰旋转木马 它工作完美 只是它不支持循环 无限滚动 我确实在谷歌和 stackoverflow 上搜索过想法 但没有运气
  • 自定义元素上的 Angular 非常奇怪的错误

    我制作了一个自定义选择元素 但出现了一个奇怪的错误 我在这里重现了这个错误 https stackblitz com edit angular ff7i5j https stackblitz com edit angular ff7i5j
  • 我想做的是 FreezableCollection.AddRange(collectionToAdd)

    我想做的是FreezableCollection AddRange collectionToAdd 每次我添加到 FreezableCollection 时 都会引发一个事件并发生一些事情 现在我有一个新的收藏 我想添加 但这次我想要集合更
  • R - 改变列表结构

    我有一些文本数据 在读入 R 后以以下格式呈现 gt lst lt list A c aa bb cc B c aa bb cc dd 1 1 A 2 1 aa 3 1 bb 4 1 cc 5 1 B 6 1 aa 7 1 bb 8 1 c
  • 更新到 Spring Boot 2.2.1 后出现 NoSuchBeanDefinitionException

    将现有代码从 Spring Boot 2 2 0 升级到 2 2 1 后 我遇到了一个奇怪的问题 看来我的 spring data jdbc 存储库不再以某种方式被扫描 Caused by org springframework beans
  • 我可以使用协议相关的 标签吗?

    协议相关 URL http www paulirish com 2010 the protocol relative url 可以方便地包含使用与原始请求相同的架构 HTTP 或 HTTPS 的资源 图像 CSS JS 同时仅保留缓存页面的
  • 鼠标在图像上单击的位置

    我有一个 GWT 容器 里面有一些东西和一个添加了点击处理程序的图像 我尝试做的是获取相对于图像的确切鼠标事件 X 和 Y 坐标 我看到帖子了here https stackoverflow com questions 1726137 tr
  • 跨编译单元的 OCaml 递归模块

    我试图将以下递归模块拆分为单独的编译单元 具体来说 我希望 B 位于它自己的 b ml 中 以便能够与其他 A 一起重用它 module type AT sig type b type t Foo of b Bar val f t gt b
  • PL/SQL:从表中选择到关联数组中

    我正在尝试在一个查询中将数据选择到 pl sql 关联数组中 我知道我可以使用硬编码密钥来做到这一点 但我想看看是否有某种方法可以引用另一列 密钥列 DECLARE TYPE VarAssoc IS TABLE OF varchar2 2
  • 在拉斐尔·JS

    我需要做类似的事情 paper text Left Top this p Label paper text Left Top nbsp this p Label 但前置空格不会显示或显示为 nbsp 在文本中 我试过了 label attr
  • Laravel 模型工厂播种机将两个模型分配给一个模型

    我正在开发 Laravel 9 项目 需要创建大量测试数据 我有一些模型 我想通过我的模型工厂自动将它们链接起来 这是我的模型关系 User Company 用户可以拥有一家公司 但他们可能没有一家 Affiliate 附属机构拥有user
  • scikit 多标签分类:ValueError:错误的输入形状

    我相信SGDClassifier with loss log 支持多标签分类 我不必使用 OneVsRestClassifier 检查这个 https stackoverflow com questions 15036630 batch g
  • Gui 工具包,我应该使用哪个? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在编写一个相当大且复杂的数据分析程序 我认为是时候为该程序构建一个 GUI 了 所以我的问题是 我应该使用哪个 GUI 工具包 我对编码和构建 G
  • Phonegap 1.7中的Childbrowser插件只能第一次打开

    Phonegap 1 7 中的 Childbrowser 插件只能在第一次打开 我正在使用 Phonegap 1 7 和 Childbrowser 仅在子浏览器第一次工作时 当我关闭 Childbrowser 按下完成按钮 后 当我尝试打开
  • 如何仅删除父表中由子表中的外键引用的行

    我想从父表中删除行 元组 但它抛出错误消息 因为它的子表中有外键引用 但是 就我而言 我想仅删除父表中的记录并保留子表中的数据 有可能实现这一目标吗 我知道的用法ON DELETE CASCADE https stackoverflow c
  • ExtJS“日期字段”验证覆盖

    我需要一个具有一些自定义行为的日期列 特别是我需要能够在同一字段中输入日期或年龄 年龄保持呈现为年龄 日期保持呈现为日期 例如 输入 23 将使 23 在字段中保留为有效值 或者输入 22 1 88 将使 22 1 88 保留为有效值 所以
  • 在第一行有 rowspan 的情况下,在表格的第一行设置 css 样式

    我有很多表 想要在表的第一行设置 css 样式 前提是第一行有行跨度 table tbody tr td width 110 Name td td width 110 Size td td width 110 Status td tr tr
  • Vega-Lite 中的平行坐标?

    是否可以创建平行坐标维加精简版 https vega github io vega lite 我正在寻找一个简单但功能强大的 JavaScript 绘图库 并且需要支持平行坐标 I have googled https www google
  • 如何使用 PHP 将 RSS XML 提要转换为数组

    我希望标题代表全部 如何使用 PHP 将 RSS XML 提要转换为数组 如何才能做到这一点 例如 我正在使用以下网址 这导致了 XML 模式 我需要使用 PHP 将其转换为数组格式 任何帮助将不胜感激和感激 提前致谢 一步步 How to
  • 如何在没有 web.xml 的情况下将 App Engine 项目更新到 Java 11?

    我有一个应用程序引擎项目 Here https github com KevinWorkman GoogleCloudExamples tree master hello world是一个示例存储库 但它只包含几个文件 pom xml