- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
tl;博士:为什么这在本地有效,但在我部署到我的实时 App Engine 项目时无效?
我正在尝试使用 Java 11 版本的 App Engine 创建一个基于 servlet 的准系统 Web 应用程序。在 this guide 之后,我正在将一些项目从 Java 8 更新到 Java 11 .我也在用 this guide和 this example .我的目标是使用 Jetty 运行一个非常简单的 Web 应用程序,该应用程序在 App Engine 中提供单个静态 HTML 文件和单个 servlet 文件。
当我在本地运行时,我的网络应用程序运行良好:
mvn clean install
mvn exec:java -Dexec.args="target/app-engine-hello-world-1.war"
当我运行这些命令时,我的
index.html
并且我的 servlet URL 工作正常。
mvn package appengine:deploy
...命令成功,但是当我导航到我的实时 URL 时,HTML 文件和 servlet URL 均出现此错误:
"Error: Server Error. The server encountered an error and could not complete your request. Please try again in 30 seconds."
如果我查看 Cloud 控制台中的日志,则会看到以下错误:
Error: Could not find or load main class io.happycoding.Main
Caused by: java.lang.ClassNotFoundException: io.happycoding.Main
我的设置有问题,但我没有看到任何明显的错误。
<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>
<packaging>war</packaging>
<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>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<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>io.happycoding.Main</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<projectId>happy-coding-gcloud</projectId>
<version>1</version>
</configuration>
</plugin>
</plugins>
</build>
</project>
src/main/appengine/app.yaml
runtime: java11
entrypoint: 'java -cp "*" io.happycoding.Main app-engine-hello-world-1.war'
src/main/java/io/happycoding/Main.java
package io.happycoding;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.webapp.Configuration.ClassList;
import org.eclipse.jetty.webapp.WebAppContext;
import io.happycoding.servlets.HelloWorldServlet;
/** 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");
Server server = new Server(8080);
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");
server.setHandler(webapp);
server.join();
}
}
src/main/webapp/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Google Cloud Hello World</title>
</head>
<body>
<h1>Google Cloud Hello World</h1>
<p>This is a sample HTML file. Click <a href="/hello">here</a> to see content served from a servlet.</p>
<p>Learn more at <a href="https://happycoding.io">HappyCoding.io</a>.</p>
</body>
</html>
src/main/java/io/happycoding/servlets/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>");
}
}
我猜我如何设置实时站点的类路径有问题,但我没有看到任何明显的错误。
packaging
房产在
pom.xml
设置为
war
, 我得到一个
.war
包含以下内容的文件:
index.html
META-INF/MANIFEST.MF
META-INF/maven/io.happycoding/app-engine-hello-world/pom.properties
META-INF/maven/io.happycoding/app-engine-hello-world/pom.xml
WEB-INF/classes/io/happycoding/Main.class
WEB-INF/classes/io/happycoding/servlets/HelloWorldServlet.class
WEB-INF/classes/lib/asm-7.3.1.jar
WEB-INF/classes/lib/asm-analysis-7.3.1.jar
WEB-INF/classes/lib/asm-commons-7.3.1.jar
WEB-INF/classes/lib/asm-tree-7.3.1.jar
WEB-INF/classes/lib/javax.annotation-api-1.3.jar
WEB-INF/classes/lib/javax.servlet-api-4.0.1.jar
WEB-INF/classes/lib/jetty-annotations-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-http-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-io-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-jndi-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-plus-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-security-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-server-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-servlet-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-util-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-webapp-9.4.31.v20200723.jar
WEB-INF/classes/lib/jetty-xml-9.4.31.v20200723.jar
如果我更改
packaging
房产在
pom.xml
至
jar
,然后我得到一个
.jar
包含以下内容的文件:
io/happycoding/Main.class
io/happycoding/servlets/HelloWorldServlet.class
META-INF/MANIFEST.MF
META-INF/maven/io.happycoding/app-engine-hello-world/pom.properties
META-INF/maven/io.happycoding/app-engine-hello-world/pom.xml
我在实时站点的日志中收到此错误:
Error: Unable to initialize main class io.happycoding.Main
Caused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/server/Handler
这感觉像是进步,但后来我的实时服务器也出现了 404 错误,所以我觉得很卡。
pom.xml
文件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>copy</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/appengine-staging
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
然后我在 App Engine 调试器中看到这些文件:
Main
引起的类(class)在
.war
内对类路径没有影响的文件,这就是找不到它的原因。
最佳答案
我认为您的问题是您包含了 Main
war 本身中的类,而 App Engine 无法找到它。
正如您在 GCP migration guide 中看到的那样, Main
类在名为 simple-jetty-main
的外部依赖项中定义.
随着 maven-dependency-plugin
的执行这个依赖被复制到 appengine-staging
目录,使其可以从 Java 类路径访问。
这就是为什么Main
执行来自 app.yaml
的命令时,可以在指南中建议的示例中找到类。 entrypoint
:
entrypoint: 'java -cp "*" com.example.appengine.demo.jettymain.Main helloworld.war'
因此,解决方案将包括您的
Main
另一个库中的类,独立于您需要部署的 war 文件。
simple-jetty-main
所做的那样- 可以在您的 GCP 项目中重复用于此任务。
simple-jetty-main
库本身(您可以从
https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/appengine-java11/appengine-simple-jetty-main 克隆所需的代码)。安装它,在你的
pom.xml
中包含依赖项,还包括
maven-dependency-plugin
,并定义您的
entrypoint
如下:
entrypoint: 'java -cp "*" com.example.appengine.demo.jettymain.Main app-engine-hello-world-1.war'
对于您的评论,您将不希望
Main
之间有分隔符。类和其余代码。
Main
类以便 Jetty 可以服务
HelloWorldSevlet
和静态内容。该代码实际上与您提供的代码非常相似。请原谅设置的简单性,它基于
web.xml
文件;如有必要,可以进行进一步的开发以处理注释或任何认为合适的内容:
package io.happycoding;
import java.net.URL;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
public class Main {
public static final String WEBAPP_RESOURCES_LOCATION = "META-INF/resources";
public static void main(String[] args) throws Exception {
System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StrErrLog");
System.setProperty("org.eclipse.jetty.LEVEL", "INFO");
Server server = new Server(8080);
URL webAppDir = Thread.currentThread().getContextClassLoader().getResource(WEBAPP_RESOURCES_LOCATION);
if (webAppDir == null) {
throw new RuntimeException(String.format("Unable to find %s directory into the JAR file", WEBAPP_RESOURCES_LOCATION));
}
WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/");
webAppContext.setDescriptor(WEBAPP_RESOURCES_LOCATION + "/WEB-INF/web.xml");
webAppContext.setResourceBase(webAppDir.toURI().toString());
webAppContext.setParentLoaderPriority(true);
server.setHandler(webAppContext);
server.start();
server.join();
}
}
静态资源可以从您选择的目录加载(它将在
pom.xml
中参数化)。
src/main/webapp
存放静态内容的文件夹。
WEB-INF
与此目录
web.xml
里面的文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>HelloWorldServlet</servlet-name>
<servlet-class>io.happycoding.servlets.HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
这是一个
tree
我的源代码设置:
pom.xml
文件与您提供的文件非常相似。我只包括了
maven-resources-plugin
将 Web 应用程序静态内容复制到 jar 文件,以及
maven-shade-plugin
生成一个 UberJar:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<packaging>jar</packaging>
<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>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- Directory where static content resides -->
<webapp.dir>./src/main/webapp</webapp.dir>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>9.4.31.v20200723</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>9.4.31.v20200723</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<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>io.happycoding.Main</mainClass>
</configuration>
</plugin>
<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>${webapp.dir}</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<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>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.happycoding.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<projectId>happy-coding-gcloud</projectId>
<version>1</version>
</configuration>
</plugin>
</plugins>
</build>
</project>
通过此设置,您可以通过执行以下命令在本地运行应用程序:
mvn exec:java
您还可以直接从 java 工具在本地运行该程序:
java -jar appengine-deploy-sample-1.jar
抱歉,我无法在 GCP 中测试设置,但我认为,根据迁移指南,您可以尝试在不指明
entrypoint
的情况下部署应用程序。在您的
app.yaml
.
entrypoint
来运行该应用程序。类似于以下内容:
entrypoint: 'java -jar appengine-deploy-sample-1.jar'
或者可能:
entrypoint: 'java -cp "*" -jar appengine-deploy-sample-1.jar'
关于java - App Engine Java 11 无法在实时服务器上找到或加载主类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63333073/
例如,我有一个父类Author: class Author { String name static hasMany = [ fiction: Book,
代码如下: dojo.query(subNav.navClass).forEach(function(node, index, arr){ if(dojo.style(node, 'd
我有一个带有 Id 和姓名的学生表和一个带有 Id 和 friend Id 的 Friends 表。我想加入这两个表并找到学生的 friend 。 例如,Ashley 的 friend 是 Saman
我通过互联网浏览,但仍未找到问题的答案。应该很容易: class Parent { String name Child child } 当我有一个 child 对象时,如何获得它的 paren
我正在尝试创建一个以 Firebase 作为我的后端的社交应用。现在我正面临如何(在哪里?)找到 friend 功能的问题。 我有每个用户的邮件地址。 我可以访问用户的电话也预订。 在传统的后端中,我
我主要想澄清以下几点: 1。有人告诉我,在 iOS 5 及以下版本中,如果您使用 Game Center 设置多人游戏,则“查找 Facebook 好友”(如与好友争夺战)的功能不是内置的,因此您需要
关于redis docker镜像ENTRYPOINT脚本 docker-entrypoint.sh : #!/bin/sh set -e # first arg is `-f` or `--some-
我是一名优秀的程序员,十分优秀!