这个最小的嵌入式Jetty项目正确启动,扫描注释并查找和映射带注释的TestServlet。
项目结构:
|-src/main/java/test
| |-Test.java
|-webapp/
| |-test.zul
|-pom.xmlTest.java:
package test;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
public class Test {
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/test");
webapp.setBaseResource(Resource.newResource(new File("webapp").getCanonicalFile()));
// https://www.eclipse.org/jetty/documentation/jetty-9/index.html#configuring-webapps
// the order is important
webapp.setConfigurations(new Configuration[] { //
new WebInfConfiguration(), //
new WebXmlConfiguration(), //
new MetaInfConfiguration(), //
new FragmentConfiguration(), //
// new EnvConfiguration(), // not needed
// new PlusConfiguration(), // not needed
new AnnotationConfiguration(), //
// new JettyWebXmlConfiguration(), // no jetty-web.xml
});
webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*");
server.setHandler(webapp);
server.setDumpAfterStart(true);
server.start();
java.awt.Desktop.getDesktop().browse(new URI("http://localhost:8080/test/TestServlet")) /* working */;
java.awt.Desktop.getDesktop().browse(new URI("http://localhost:8080/test/test.zul")) /* not working */;
}
@WebServlet(urlPatterns = {"/TestServlet"})
public static final class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Test 1");
}
}
}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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>9.4.30.v20200611</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zkbind</artifactId>
<version>9.6.0.1</version>
</dependency>
</dependencies>
</project>test.zul:
<zk><label value="hello"/></zk>zk的网页片段似乎在某种程度上被“注意到”:
| +@ org.eclipse.jetty.webFragments.cache = java.util.concurrent.ConcurrentHashMap@bb35baa5{size=30}
| | +@ file:///C:/Users/r.hoehener/.m2/repository/org/zkoss/common/zcommon/9.6.0.1/zcommon-9.6.0.1.jar = org.eclipse.jetty.util.resource.EmptyResource@3fc39309
| | +@ file:///C:/Users/r.hoehener/.m2/repository/org/eclipse/jetty/jetty-annotations/9.4.30.v20200611/jetty-annotations-9.4.30.v20200611.jar = org.eclipse.jetty.util.resource.EmptyResource@3fc39309
| | +@ file:///C:/Users/r.hoehener/.m2/repository/org/eclipse/jetty/jetty-io/9.4.30.v20200611/jetty-io-9.4.30.v20200611.jar = org.eclipse.jetty.util.resource.EmptyResource@3fc39309
| | +@ file:///C:/Users/r.hoehener/.m2/repository/org/apache-extras/beanshell/bsh/2.0b6/bsh-2.0b6.jar = org.eclipse.jetty.util.resource.EmptyResource@3fc39309
| | +@ file:///C:/Users/r.hoehener/.m2/repository/org/zkoss/zk/zkwebfragment/9.6.0.1/zkwebfragment-9.6.0.1.jar = jar:file:///C:/Users/r.hoehener/.m2/repository/org/zkoss/zk/zkwebfragment/9.6.0.1/zkwebfragment-9.6.0.1.jar!/META-INF/web-fragment.xml
...但是test.zul是以纯文本形式显示的。ZK引擎没有初始化。
知道为什么吗?
编辑:为了防止我的配置方式:这直接来自9.x文档,其中说“您有许多选项可以让Jetty使用不同的配置列表”,包括“直接在WebAppContext上设置列表”:
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="war"><SystemProperty name="jetty.base" default="."/>/webapps/my-cool-webapp</Set>
<Set name="configurationClasses">
<Array type="java.lang.String">
<Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
<Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
<Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
<Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
<Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
</Array>
</Set>
</Configure>发布于 2021-12-20 19:14:01
首先,不要使用Jetty9.4.30,它现在需要一些安全警告。
请参阅:reports.php
至少使用Jetty 9.4.44.v20210927。
接下来,查看Jetty转储中的zk servlet.
org.zkoss.zk.au.http.DHtmlUpdateServletorg.zkoss.zk.ui.http.DHtmlLayoutServlet如果这些数据存在于WebAppContext转储中,那么Jetty正确地发现并加载了您的zkwebfragment-<ver>.jar。此时,您要做的是如何使用zk技术正确配置zk库(从现在起可以忽略Jetty特定的细节)。
如果它们不存在,那么首先确保您自己的webapp使用Servlet3.0(在WEB-INF/web.xml中声明)或更新来支持适当的Web片段(旧的Servlet规范不支持Web片段)。
接下来,确保zkwebfragment-<ver>.jar存在于WebApp类加载器上,因为每个规范都不会从任何其他类加载器加载web片段,甚至连应用程序/服务器/容器类加载器都不会加载。
如果您仍然没有看到它们,请返回到调整默认的Configuration列表,而不是您的代码片段中的硬编码列表。(您的列表缺少所需的配置,并且成功的顺序不对,不要更改默认列表,不要在webapp上设置列表,只更改服务器级别的默认值)。
问问自己,zk需要什么?(如果它需要jndi,那么您也需要jndi特定的配置部分)。
如果您没有停留在Java 8上,请使用Jetty 10,因为整个Configuration层已经被重新处理,不再允许糟糕的配置(实际上,旧的setConfiguration()方法甚至不在那里,仅仅是支持jars的存在就足以表明您希望得到这种支持,并在正确的位置使用正确的父依赖项启用它)。
发布于 2021-12-21 07:15:16
添加配置的方法是:
Configuration.ClassList classList = Configuration.ClassList.setServerDefault(server);
classList.addAfter(
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration");更新:
我试过了
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>10.0.7</version>
</dependency>zul不需要添加任何配置即可工作。
发布于 2021-12-21 09:23:45
因此,正如Joakim所指出的,Servlet规范3.1说:
如果一个框架希望它的META/web-frament.xml能够增强web应用程序的web.xml,那么该框架必须捆绑在web应用程序的within /lib目录中。..。换句话说,只有绑定在web应用程序的WEB-INF/lib目录中的JAR文件,而不是类加载委托链上的那些文件,需要扫描web-片段.JAR。
因此,我必须确保WebAppContext的类路径上存在zkwebfragments.jar。
我更改了部署策略,如下所示:
/myapp/
|-bin/
| |- project jar (including annotated servlets and listeners)
| |- all maven dependency jars (including jetty and zk libs)
|-webapp/
| |-WEB-INF/
| | |-lib/ (EMTPY!)
| | |-web.xml
| | |-zk.xml
| |-index.zul
| |-other static resources
|-data/
|-application data (docker mounted host volume)在主类中,将zkwebfragment.jar添加到WebAppContext类路径:
Server server = new Server(port);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/myapp");
webapp.setBaseResource(Resource.newResource(new File(isDocker ? "/myapp/webapp" : "./webapp").getCanonicalFile()));
// order important: https://www.eclipse.org/jetty/documentation/jetty-9/index.html#configuring-webapps
webapp.setConfigurations(new Configuration[] { //
new WebInfConfiguration(), //
new WebXmlConfiguration(), //
new MetaInfConfiguration(), //
new FragmentConfiguration(), //
new AnnotationConfiguration(), //
});
// servlet spec: fragments are only loaded if they are bundled in WEB-INF/lib
webapp.setExtraClasspath(Arrays.asList(((URLClassLoader) MyAppMain.class.getClassLoader()).getURLs()).stream().filter(
u -> u.toString().contains("zkwebfragment")).findAny().get().toString());
// scan for annotations in the container classpath (AppClassLoader)
webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*");
server.setHandler(webapp);
server.setDumpAfterStart(true);
server.start();当从IDE运行主类时,所有项目类和所有maven依赖项都会自动添加到AppClassLoader中。
当作为码头容器运行时,应用程序将以以下方式启动:
ENTRYPOINT ["java", "-cp", "/myapp/bin/*", "myapp.MyAppMain"]它还将项目jar和所有maven依赖jar添加到AppClassLoader中。
通过将所有jars从/myapp/webapp/META-INF/lib/*中移出/myapp/bin/*,所有jars在类加载器层次结构中只存在一次,这也解决了复制资源警告。除了存在两次的zkwebfragment.jar之外。码头转储摘录:
| | +> WebAppClassLoader{1509563803}@59fa1d9b
| | | +> URLs size=1
| | | | +> file:/myapp/bin/zkwebfragment-9.6.0.1.jar
| | | +> sun.misc.Launcher$AppClassLoader@2ff4acd0再往下看:
| +> sun.misc.Launcher$AppClassLoader@2ff4acd0
| +> URLs size=52
| | +> file:/myapp/bin/myapp.jar
| | +> file:/myapp/bin/jetty-annotations-9.4.44.v20210927.jar
| | +> file:/myapp/bin/zkwebfragment-9.6.0.1.jar
| | +> ...
| +> sun.misc.Launcher$ExtClassLoader@4ee285c6
| +> URLs size=9
| +> file:/opt/java/openjdk/lib/ext/sunpkcs11.jar
| +> ...如果我使用Jetty安装并将我的应用程序作为标准WAR捆绑起来,所有这些都是不必要的。但是我真的很想尝试这种简单的Java方法(来自Jetty ):
Jetty有一个口号,“不要在Jetty中部署应用程序,在应用程序中部署Jetty!”这意味着,作为将应用程序捆绑为部署在Jetty中的标准WAR的替代方案,Jetty被设计为可以像任何POJO一样在Java程序中实例化和使用的软件组件。
https://stackoverflow.com/questions/70426380
复制相似问题