Serving static files with embedded Jetty
I'm trying to build a simple demo app with embedded Jetty that serves static files from a "html" directory that's a subdirectory of the current working directory. The idea is that the directory with the demo jar and content can be moved to a new location and still work.
I've tried variations of the following, but I keep getting 404s.
ServletContextHandler context =
new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.getInitParams().put(
"org.eclipse.jetty.servlet.Default.resourceBase", "html");
context.addServlet(new ServletHolder(new DefaultServlet()), "/html");
Server jetty = new Server(8080);
jetty.setHandler(context);
jetty.start();
Update: Here's a solution as documented in the Jetty tutorial. As mentioned in the correct answer, it uses a ResourceHandler
instead of a ServletContextHandler
:
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(8080);
server.addConnector(connector);
ResourceHandler resource_handler = new ResourceHandler();
resource_handler.setDirectoriesListed(true);
resource_handler.setWelcomeFiles(new String[]{ "index.html" });
resource_handler.setResourceBase(".");
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
server.setHandler(handlers);
server.start();
server.join();
Solution 1:
Use a ResourceHandler
instead of ServletContextHandler
.
Solution 2:
There is an important difference between serving static content using a ResourceHandler
and using a DefaultServlet
(with a ServletContextHandler
).
When a ResourceHandler
(or a HandlerList
holding multiple ResourceHandler
instances) is set as a context handler, it directly processes requests and ignores any registered javax.servlet.Filter instances.
If you need filters, the only way to go about it is using a ServletContextHandler
, adding filters to it, then adding a DefaultServlet
and finally, setting the base Resource
.
The base Resource
represents a resourceBase path a ResourceHandler
would be initialised with. If serving static resources from multiple directories, use a ResourceCollection
(which is still a Resource
) and initialise it with an array of resourceBase strings:
ResourceCollection resourceCollection = new ResourceCollection();
resourceCollection.setResources(getArrayOfResourceBaseDirs());
Solution 3:
In my small web server I have two files, a index.html
and a info.js
locate under /src/webapp
and I want them to be served from the embedded jetty web server.
This is how I solve the problem with static content.
Server server = new Server(8080);
ServletContextHandler ctx = new ServletContextHandler();
ctx.setContextPath("/");
DefaultServlet defaultServlet = new DefaultServlet();
ServletHolder holderPwd = new ServletHolder("default", defaultServlet);
holderPwd.setInitParameter("resourceBase", "./src/webapp/");
ctx.addServlet(holderPwd, "/*");
ctx.addServlet(InfoServiceSocketServlet.class, "/info");
server.setHandler(ctx);
Worked like a charm!
Solution 4:
I managed to achieve something similar by adding a mapping for the "css" directory in web.xml. Explicitly telling it to use DefaultServlet:
<servlet>
<servlet-name>DefaultServlet</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>/css/*</url-pattern>
</servlet-mapping>