带有爆炸战的嵌入式Jetty,使用带注释的配置

我正在学习Java EE 7 Servlets并尝试使用嵌入式Jetty(v 9.3.7)从Java EE 7教程部署hello2 示例 ,但收效甚微。 hello2由两个servlet和一个图像文件组成。 配置已注释,项目没有任何web.xml。

在嵌入式Jetty 示例的WebAppContext部分之后,我创建了这个主类来启动我的嵌入式服务器:

 public class MyServer { public static void main(String[] args) throws Exception { Server server = new Server(8080); String webappPath = new File(MyServer.class.getProtectionDomain().getCodeSource().getLocation().getFile()) .getParentFile().getParentFile().getAbsolutePath(); WebAppContext webapp = new WebAppContext(webappPath, ""); webapp.setConfigurations(new Configuration[]{ new AnnotationConfiguration()}); server.setHandler(webapp); server.start(); server.join(); } } 

据我所知,由于Jetty是一个Java EE Web容器,它应该能够按原样提供示例Serlvet项目,我只需要指向war文件夹结构。 以下是项目的结构:

 -- hello2 \-- src \-- main +-- java │  +-- MyServer.java │  \-- javaeetutorial │  \-- hello2 │  +-- GreetingServlet.java │  \-- ResponseServlet.java \-- webapp +-- WEB-INF │  \-- classes │  +-- MyServer.class │  \-- javaeetutorial │  \-- hello2 │  +-- GreetingServlet.class │  \-- ResponseServlet.class +-- index.html \-- resources \-- images \-- duke.waving.gif 

hello2示例代码可以在这里找到。 以下是GreetingServlet一些部分

 @WebServlet("/greeting") public class GreetingServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { .... 

ResponseServlet

 @WebServlet("/response") public class ResponseServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { .... 

这些文件被编译为hello2/webapp/classes/从而使webapp文件夹成为爆炸式WAR。 index.html是我添加的,只是为了测试Jetty是否选择了它。 结果是当我访问localhost时出现错误404:8080,localhost:8080 / greeting或localhost:8080 / response

如果我使用webapp.setConfigurations()添加WebXmlConfiguration ,然后像webapp.setResourceBase(webappPath)那样设置资源库,我设法进入Jetty的静态文件服务器。 这是因为Jetty然后使用默认的web.xml ,它将自己的servlet添加到服务器以用于文件服务。 但即使这样,我的注释servlet也没有被选中。

我让Jetty读取带注释的servlet配置的方法是使用WebAppContext.getMetadata().setWebInfClassesDirs()显式设置WEB-INF目录WebAppContext.getMetadata().setWebInfClassesDirs()

 webapp.getMetaData().setWebInfClassesDirs( Arrays.asList(Resource.newResource( MyServer.class.getProtectionDomain().getCodeSource().getLocation()))); 

然后,servlet按预期响应,但这不会为我的index.html或图像文件提供服务。 我还将资源库设置为无用。 所以我想要的是Jetty在没有web.xml情况下为我的Web应用程序提供服务,只需将其指向爆炸的WAR目录即可。 显然我错过了一些东西。

用…

 webapp.setConfigurations(new Configuration[]{ new AnnotationConfiguration()}); 

将撤消所有现有的重要配置,并且仅启用AnnotationConfiguration

难怪它不适合你,使用该设置,缺少加载WEB-INF/web.xml的配置,缺少使用WEB-INF/lib的配置等。

您必须适当地修改现有的配置列表,并且有很多示例可以向您展示。

由于您没有指定是否有使用JNDI的注释,或者存在于Web片段中,或者来自webapp上下文之外(例如容器本身),因此您需要的确切配置很难指定。

有关完成此操作的完整项目,请参阅https://github.com/jetty-project/embedded-servlet-3.1项目。

 context.setConfigurations(new Configuration[] { new AnnotationConfiguration(), new WebInfConfiguration(), new WebXmlConfiguration(), new MetaInfConfiguration(), new FragmentConfiguration(), new EnvConfiguration(), new PlusConfiguration(), new JettyWebXmlConfiguration() }); 

这是一种常规设置,这是最常见的设置,但可能会让您接触到您可能不需要的额外配置。

即使您不想要其他组件,您仍然需要将它们留给已发现的Web应用程序。 否则你有一个100%的手动webapp,你专门调用.addServlet().addFilter()等。

您应该使用此语法。

 private void enableAnnotationScanning(Server server) { Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server); classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.annotations.AnnotationConfiguration"); } 

因为这将修改现有的配置列表以仅添加AnnotationConfiguration

如果要查看此格式的其他示例,请查看以下示例项目:

在与Joakim Erdfelt讨论之后,我进一步研究了Tomcat,我理解Jetty可能不是测试不同类型的Java EE Webfunction的最佳容器。 Jetty以其他方式实现Java EE的支持,而不是Glasshfish和Tomcat,后者又需要不同的设置方法,这在Joakims的回答中进行了详细阐述。

使用以下代码段使用Tomcat进行测试后

 public class MyServer { public static void main(String[] args) throws Exception { Tomcat tomcat = new Tomcat(); tomcat.setPort(8080); tomcat.addWebapp("","webapp"); tomcat.start(); tomcat.getServer().await(); } } 

它首先看起来像Tomcat不需要任何web.xml,但在进一步调查之后,Tomcat使用默认的web.xml(如果没有提供)。 此web.xml包含index.html和一个提供静态内容的DefaultServlet 。 这种方法类似于Jettys,我认为这也是Glassfish的工作原理。 所吸取的经验教训是,总有某种类型的DefaultServlet潜伏在Java EE Web服务器的后台,它可以完成一些神奇的工作。 即使web.xml对于服务器的用户是可选的,服务器仍然在幕后提供它以使其自己工作。