这是我在 Eclipse 中的设置:
有2个项目....clinixwip11Appl和clinixwip11Jtty
clinixwip11Jtty 的目的是启动 Jetty 的实例...如下...
public class JttyMain{
public static void main(String[] args) throws Exception {
int iPort = 0;
ClassList clssList = null;
Server jttySrvr = null;
ServletHolder srvtHldr = null;
WebAppContext wappCtxt = null;
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");
iPort = Integer.parseInt(System.getenv().getOrDefault("PORT", "8080"));
jttySrvr = new Server(iPort);
System.out.println("jttySrvr created and listening at 8080");
jttySrvr.addLifeCycleListener(new CustomLifeCycleListener());
wappCtxt = new WebAppContext();
wappCtxt.setContextPath("/");
wappCtxt.setWar(args[0]);
wappCtxt.setConfigurations(new Configuration[] {
new AnnotationConfiguration(),
new WebInfConfiguration(),
});
wappCtxt.setAttribute ("org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern", ".*/target/classes/|.*/classes/.");
System.out.println("wappCtxt created");
srvtHldr = wappCtxt.addServlet(DefaultServlet.class, "/");
srvtHldr.setInitParameter("jersey.config.server.provider.packages", "com.applix.cliniX.serverApp");
srvtHldr.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.applix.cliniX.serverApp.filter.ResponseFilter");
srvtHldr.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", "com.applix.cliniX.serverApp.filter.RequestFilter");
System.out.println("srvtHldr created and initialized");
clssList = ClassList.setServerDefault(jttySrvr);
clssList.addBefore (
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration"
);
jttySrvr.setHandler(wappCtxt);
System.out.println("before starting jttySrvr");
jttySrvr.start();
System.out.println("after starting jttySrvr");
jttySrvr.join();
System.out.println("after joining with main thread");
}
public static class CustomLifeCycleListener implements LifeCycle.Listener {
@Override
public void lifeCycleStarting(LifeCycle event) {
System.out.println("JTTYMAIN Starting at " + new Date(System.currentTimeMillis()) + " : " + event);
}
@Override
public void lifeCycleStarted(LifeCycle event) {
System.out.println("JTTYMAIN Started: at " + new Date(System.currentTimeMillis()) + " : " + event);
}
@Override
public void lifeCycleFailure(LifeCycle event, Throwable cause) {
System.out.println("JTTYMAIN Failure: at " + new Date(System.currentTimeMillis()) + " : " + event);
cause.printStackTrace(System.out);
}
@Override
public void lifeCycleStopping(LifeCycle event) {
System.out.println("JTTYMAIN Stopping: at " + new Date(System.currentTimeMillis()) + " : " + event);
}
@Override
public void lifeCycleStopped(LifeCycle event) {
System.out.println("JTTYMAIN Stopped: at " + new Date(System.currentTimeMillis()) + " : " + event);
}
}
}
因为这应该在 Google App Engine 上运行,所以
app.yaml
中有 clinixwip11Appl/src/main/appengine
文件:
runtime: java11
instance_class: F2
entrypoint: 'java -cp "*" com.applix.clinix.clinixwip11Jtty.JttyMain clinixwip11Appl.war'
当 maven 构建 2 个项目时,有两个输出部署到 Google App Engine:
(1)
clinixwip11Jtty.jar
(包含 JttyMain.class)
(2)clinixwip11Appl.war
(包含我的appl代码)....如下:
部署代码后,我可以看到 Jetty 实例启动,并且我能够成功访问位于
/index.html
根目录的 /main.html
和 clinixwip11Appl.war
。
但是,当访问
classes
的 clinixwip11Appl.war
文件夹中的任何类时,我会收到 404。
classes 文件夹包含许多已编译的类......我已经从下面的类之一复制了相关代码......
@Path("/estbStaffCard")
public class EstbStaffCardController {
@Context
private HttpServletRequest request = null;
private static Logger logger = Logger.getLogger("EstbStaffCardController");
@GET
@Path("/getEstbForEstbStaffIden")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.TEXT_PLAIN)
public synchronized Response getEstbForEstbStaffIden (@QueryParam("queryString") String paramQueryString) {
logger.info("//////////////////////////////////////////////////////////////////////////////////////");
logger.info("begin new method: " + new Object(){}.getClass().getEnclosingMethod().getName());
.......
}
}
因此,当访问
{URL to app engine}/estbStaffCard/getEstbForEstbStaffIden...
时,我会得到 404。
我尝试了各种在 JttyMain 类中指定配置选项的选项,这些选项在网络上的众多线程中指定,特别是在 stackoverflow 上,但没有效果。
您知道需要在上面的 JttyMain 类中指定什么配置,以便
clinixwip11Appl.war
的类文件夹中的类得到尊重吗?过去三天我一直在做这个。请帮忙。
在战争中的这个地点...
web.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="4.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
<!--
<init-param>
<param-name>org.glassfish.jersey.server.ServerProperties.DisableWADL</param-name>
<param-value>true</param-value>
</init-param>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="*" />
</customHeaders>
</httpProtocol>
-->
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>
org.glassfish.jersey.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.applix.cliniX.serverApp</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.applix.cliniX.serverApp.filter.RequestFilter</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.applix.cliniX.serverApp.filter.ResponseFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>_ah_sessioncleanup</servlet-name>
<servlet-class>com.google.apphosting.utils.servlet.SessionCleanupServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>_ah_sessioncleanup</servlet-name>
<url-pattern>/_ah/sessioncleanup</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>*</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<listener>
<listener-class>com.applix.cliniX.serverApp.listener.SessionListener</listener-class>
</listener>
</web-app>
我知道我没有做一些我需要做的关键事情,或者在
JttyMain
代码的这一部分中做得太过分:
wappCtxt.setConfigurations(new Configuration[] {
new AnnotationConfiguration(),
new WebInfConfiguration(),
});
wappCtxt.setAttribute ("org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern", ".*/target/classes/|.*/classes/.");
System.out.println("wappCtxt created");
srvtHldr = wappCtxt.addServlet(DefaultServlet.class, "/");
srvtHldr.setInitParameter("jersey.config.server.provider.packages", "com.applix.cliniX.serverApp");
srvtHldr.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.applix.cliniX.serverApp.filter.ResponseFilter");
srvtHldr.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", "com.applix.cliniX.serverApp.filter.RequestFilter");
System.out.println("srvtHldr created and initialized");
clssList = ClassList.setServerDefault(jttySrvr);
clssList.addBefore (
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration"
);
任何帮助将不胜感激。
发现扫描哪些 Jar 文件以查找发现的注释 这里。所以现在我想知道我哪里出了问题?有什么提示、线索、帮助吗?
更新: 看来 Jetty 只使用一个类路径,命名为 war 文件的根目录,因为 index.html 和 main.html 以及位于其中的所有其他资源....css/、images/、html/ 等正在加载。只有 WEB-INF/类不被尊重。所以问题归结为让 Jetty 知道 WEB-INF/classes 和 WEB-INF/lib 也需要被视为类路径的一部分。
问题是......如何让 Jetty 知道这一点??
++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++在实验后于 2024 年 1 月 30 日星期二添加了以下内容 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++
我的目标: 按照 Google App Engine 的要求从 Java8 升级到 Java11
问题: 通过 Java8,Google App Engine 用于提供 RESTful 服务器的预构建实现
使用 Java11,Google App Engine 将不会提供这样的服务器,开发人员有责任构建提供这样的服务器
我的结论(关于maven和版本的东西)经过上述实验...... (1) 对于上述目标,我将能够使用 Java11 编译器,但我必须将目标设置为 Java8 (2) 我将不得不使用 2.25 版本的球衣服务器和 10.0.19 版本的其他工件
但是还有更多...... 我的应用程序有许多由前端使用 REST 访问的服务。我的应用程序也有很多静态资源。 因此,为了提供这两种资源,如果我使用以下设置,
HandlerCollection handlerCollection = new HandlerCollection();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
handlerCollection.addHandler(context);
jettyServer.setHandler(handlerCollection);
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "com.rest.test");
ServletHolder staticHolder = new ServletHolder(new DefaultServlet());
staticHolder.setInitParameter("pathInfoOnly", "true");
URL webAppDir = App.class.getClassLoader().getResource("META-INF/resources");
staticHolder.setInitParameter("resourceBase", webAppDir.toURI().toString());
context.addServlet(staticHolder, "/*");
jettyServer.start();
我在服务器启动时收到此错误......
Exception in thread "main" java.lang.IllegalStateException: Multiple servlets map to path /*
但是如果我使用以下设置......
HandlerCollection handlerCollection = new HandlerCollection();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
handlerCollection.addHandler(context);
jettyServer.setHandler(handlerCollection);
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/");
jerseyServlet.setInitOrder(0);
jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "com.rest.test");
ServletHolder staticHolder = new ServletHolder(new DefaultServlet());
staticHolder.setInitParameter("pathInfoOnly", "true");
URL webAppDir = App.class.getClassLoader().getResource("META-INF/resources");
staticHolder.setInitParameter("resourceBase", webAppDir.toURI().toString());
context.addServlet(staticHolder, "/*");
I can only access static content but not the REST content
如果我使用以下设置......
HandlerCollection handlerCollection = new HandlerCollection();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
handlerCollection.addHandler(context);
jettyServer.setHandler(handlerCollection);
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/rest/*");
jerseyServlet.setInitOrder(0);
jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "com.rest.test");
ServletHolder staticHolder = new ServletHolder(new DefaultServlet());
staticHolder.setInitParameter("pathInfoOnly", "true");
URL webAppDir = App.class.getClassLoader().getResource("META-INF/resources");
staticHolder.setInitParameter("resourceBase", webAppDir.toURI().toString());
context.addServlet(staticHolder, "/*");
**I can access static content and also the REST content**
经过上述实验后我的问题(关于提供静态和 REST 内容)...... 我现在是否必须去更改我的源代码(基本上每个 REST 资源都带有 /rest 前缀)才能使上述内容正常工作? 我知道,使用 Java8 和 GAE 提供的默认 REST 实现,我能够在 /
提供静态和 REST 资源您的
org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern
设置仅对开发/测试/IDE时间有效。摆脱它进行生产。
你的主类没有做任何特别的事情。为什么有它?
WAR 文件本身就包含了它所需要的一切
WEB-INF/web.xml
。
我会跳过自定义入口点、跳过主类、跳过入口点 jar,然后将该 WAR 文件部署到 GAE。