Using web.xml with WebAppContext in Jetty

2019-06-06 11:38发布

问题:

This is my first web application, I am just trying to follow guides and launch my server with servlets specified at web.xml, but it seems that my actions don't change functionality of the server and the result is 404 error. But if I programmatically specify servlets its OK. Could anyone figure it out how this all should work? Here is my code for server

public class Launcher
{
    public static void main(String[] args) throws Exception
    {
        Server server = new Server(8080);
        WebAppContext web = new WebAppContext();
        web.setContextPath("/");
        web.setWar("src/main/web/WEB-INF/web.xml");
        //web.addServlet(MyServlet.class,"/"); This line works just fine
        server.setHandler(web);
        server.start();
        server.join();
    }
}

And my web.xml looks like this

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>lab3.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>*</url-pattern>
    </servlet-mapping>
</web-app>

回答1:

The WEB-INF/web.xml is the descriptor.

The call to WebAppContext.setWar(String) is for the base resource location.

Note: The Base Resource location is mandatory. You must set it to a valid location so that the ServletContext can function properly.

There are alternate APIs for setting the base resource location: you can use WebAppContext.setBaseResource(Resource) and WebAppContext.setResourceBase(String) as well, they mean the same thing.

If you want to specify the web descriptor location use WebAppContext.setDescriptor(String).

For your code example, it appears you want to use

    Server server = new Server(8080);
    WebAppContext web = new WebAppContext();
    web.setContextPath("/");
    web.setWar("src/main/web"); // TODO: resolve this to a an absolute path or URI!
    server.setHandler(web);
    server.start();
    server.join();

About that TODO, see the examples at jetty-project/embedded-jetty-cookbook, specifically ...

  • WebAppContextFromFileSystem.java
  • WebAppContextFromClasspath.java

It's important to recognize that by default the classpath will be based off of the Base Resource location.

The classes will be looked up from ${base.resource.uri}/classes.

I point this out, because we see the path src/main/web in your example, I suspect you are trying to make a live (unbuilt) project in an IDE work. This kind of setup will require more manual work for you, as the base resource, and classes are in different locations.

In that case you'll need to specify where the classes are manually.

aka.

    Server server = new Server(8080);
    WebAppContext web = new WebAppContext();
    web.setContextPath("/");

    Path baseResource = new File("src/main/web").toPath();
    Path classesDir = new File("target/thewebapp/WEB-INF/classes").toPath();

    if (!Files.exists(baseResource))
        throw new FileNotFoundException("Unable to find Base Resource Dir: " + baseResource);
    if (!Files.exists(classesDir))
        throw new FileNotFoundException("Unable to find Classes Dir: " + classesDir);

    web.setBaseResource(new PathResource(baseResource.toAbsolutePath()));
    web.setExtraClasspath(classesDir.toAbsolutePath().toString());
    server.setHandler(web);
    server.start();
    server.join();

Finally I want to point out some other ways you can package a webapp up in embedded-jetty ...

embedded-jetty-uber-jar

https://github.com/jetty-project/embedded-jetty-uber-jar

This uses the ServletContextHandler to manually build up a webapp, no WEB-INF/web.xml is used, no bytecode scanning, no annotation scanning, and its blazingly fast to startup.

The above project builds a single jar with everything you need to run your webapp.

embedded-jetty-live-war

https://github.com/jetty-project/embedded-jetty-live-war

This project is a bit more complex, it builds 3 parts (webapp, server, bootstrap) and then assembles them together into a single war file.

This starts with a simple war, but then enhances it with a server preconfigured the way you want it. This new "live-war" is assembled as a new war file in a separate sub-project.

This war file can be deployed as normal, and it can be run directly as a standalone self-executing war file, complete with a full server instance.