【问题标题】:Configure embedded jetty with web.xml?使用 web.xml 配置嵌入式码头?
【发布时间】:2014-01-14 05:12:59
【问题描述】:

我正在尝试生成与我的 Web 应用程序的战争以及带有嵌入式码头的自包含 jar 文件。对于嵌入式码头(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();
}

war 文件分发使用 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 时,我只想在一个位置配置它。我可以从嵌入式码头加载和使用 web.xml 文件吗?

【问题讨论】:

    标签: java maven jakarta-ee jetty embedded-jetty


    【解决方案1】:

    使用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 一起使用。

    如果你有Annotation扫描或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");
    

    有关 WebAppContext 中的更长示例,请参阅 ServerWithAnnotations 示例。

    还请注意,您也将使用此技术获得所有 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);
    

    另见:

    【讨论】:

    • 谢谢,乔金!使用您的方法,我唯一改变的是我将 WebAppContext 指向 webapp 文件夹。在下面的答案中查看我的主要方法。
    • 有没有办法在 servlet 配置上设置一个额外的/不同的 init-param(即设置一个工作目录)。当我列出 webapp 具有的 servlet 时,它只显示我以编程方式添加的一次(我怀疑它需要先启动,但为时已晚)。
    【解决方案2】:

    我最终使用了 Joakim 的方法,但指向的是 webapp 目录而不是 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 文件夹结构之外运行它,而是使用已编译的工件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多