使用web.xml配置嵌入式Jetty?

32

我试图生成一个包含嵌入式jetty的自包含jar文件,以及与我的Web应用程序一起使用的war文件。对于嵌入式jetty(jar文件分发),我会添加一个servlet,如下所示:

public static void main(String[] args) throws Exception {
    Server server = new Server(8080);

    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    server.setHandler(context);

    context.addServlet(new ServletHolder(new HelloServlet()),"/*");

    server.start();
    server.join();
}

战争文件分发使用一个web.xml文件,在web-app部分包含以下内容:

<servlet>
    <servlet-class>com.example.HelloServlet</servlet-class>
    <servlet-name>SimplestServer</servlet-name>
</servlet>
<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

这个方案有效。但是,我希望消除两种方法之间的重复。也就是说,当我添加一个新的servlet时,我只想在一个位置进行配置。我能否从嵌入的jetty中加载并使用web.xml文件?

2个回答

24

使用org.eclipse.jetty.webapp.WebAppContext

示例:

package jetty;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;

public class OnWebApp
{
    public static void main(String[] args) throws Exception
    {
        // Create a basic jetty server object that will listen on port 8080.
        // Note that if you set this to port 0 then a randomly available port
        // will be assigned that you can either look in the logs for the port,
        // or programmatically obtain it for use in test cases.
        Server server = new Server(8080);

        // The WebAppContext is the entity that controls the environment in
        // which a web application lives and breathes. In this example the
        // context path is being set to "/" so it is suitable for serving
        // root context requests and then we see it setting the location of
        // the war. A whole host of other configurations are available,
        // ranging from configuring to support annotation scanning in the
        // webapp (through PlusConfiguration) to choosing where the webapp
        // will unpack itself.
        WebAppContext webapp = new WebAppContext();
        webapp.setContextPath("/");
        webapp.setWar("path/to/my/test.war");

        // A WebAppContext is a ContextHandler as well so it needs to be set to
        // the server so it is aware of where to send the appropriate requests.
        server.setHandler(webapp);

        // Start things up! By using the server.join() the server thread will
        // join with the current thread.
        // See http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()
        // for more details.
        server.start();
        server.join();
    }
}

注意,您将构建一个普通的WAR文件,并使用它与Jetty一起使用。
如果您有特殊要求,例如注释扫描或JNDI,则需要进行配置规范。
// Enable parsing of jndi-related parts of web.xml and jetty-env.xml
org.eclipse.jetty.webapp.Configuration.ClassList classlist =
   org.eclipse.jetty.webapp.Configuration.ClassList.setServerDefault(server);

// Enable JNDI
classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
   "org.eclipse.jetty.plus.webapp.EnvConfiguration",
   "org.eclipse.jetty.plus.webapp.PlusConfiguration");

// Enable Annotation Scanning
classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
  "org.eclipse.jetty.annotations.AnnotationConfiguration");

查看ServerWithAnnotations示例,可以更好地了解在WebAppContext中的实际应用。

还要注意,使用这种技术时,所有的webapp类加载器规则也会被应用,这意味着你将拥有一个用于webapp的类加载器和另一个用于服务器的类加载器。这一点很重要。

WebAppContext有一些调整类加载器的方法,但你无法消除它们,只能控制它们的行为。

WebAppContext webapp = new WebAppContext();
// ... various setup of the webapp ...
// Flip the classloader priority from servlet spec where webapp is first to
// Standard java behavior of parent (aka Server classloader) is first.
webapp.setParentLoaderPriority(true);

参见:


谢谢,Joakim!使用您的方法,我唯一改变的是将WebAppContext指向webapp文件夹。请查看下面答案中的我的主要方法。 - Stephan
1
有没有一种方法可以在servlet配置中设置额外/不同的init-param(即设置工作目录)。当我列出webapp拥有的servlet时,它仅显示我以编程方式添加的那些(我怀疑它需要首先启动,但那时为时已晚)。 - eckes

19

我最终采用了Joakim的方法,但是指向的是web应用程序目录而不是war文件。

public static void main(String[] args) throws Exception {
    Server server = new Server(8080);

    String rootPath = SimplestServer.class.getClassLoader().getResource(".").toString();
    WebAppContext webapp = new WebAppContext(rootPath + "../../src/main/webapp", "");
    server.setHandler(webapp);

    server.start();
    server.join();
}

这对我很有帮助。这里发生的情况是,您已经在路径中拥有了这些类。如果您使用包含另一个/WEB-INF/classes副本的路径,则在使用Spring时会出现重复资源异常。此解决方案仅在您已经加载的现有类之上添加缺少的webapp文件夹。这种方法的问题在于可移植性。您无法在maven文件夹结构之外运行它,而是要使用编译后的工件。 - user2957009

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接