I deploy a webapp on two different containers (Tomcat and Jetty), but their default servlets for serving the static content have a different way of handling the URL structur
I've had good results with FileServlet, as it supports pretty much all of HTTP (etags, chunking, etc.).
Judging from the example information above, I think this entire article is based on a bugged behavior in Tomcat 6.0.29 and earlier. See https://issues.apache.org/bugzilla/show_bug.cgi?id=50026. Upgrade to Tomcat 6.0.30 and the behavior between (Tomcat|Jetty) should merge.
There is no need for completely custom implementation of the default servlet in this case, you can use this simple servlet to wrap request to the container's implementation:
package com.example;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DefaultWrapperServlet extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
RequestDispatcher rd = getServletContext().getNamedDispatcher("default");
HttpServletRequest wrapped = new HttpServletRequestWrapper(req) {
public String getServletPath() { return ""; }
};
rd.forward(wrapped, resp);
}
}
I had the same problem and I solved it by using the code of the 'default servlet' from the Tomcat codebase.
https://github.com/apache/tomcat/blob/master/java/org/apache/catalina/servlets/DefaultServlet.java
The DefaultServlet is the servlet that serves the static resources (jpg,html,css,gif etc) in Tomcat.
This servlet is very efficient and has some the properties you defined above.
I think that this source code, is a good way to start and remove the functionality or depedencies you don't need.
See StaticFile in JSOS: http://www.servletsuite.com/servlets/staticfile.htm
I did this by extending the tomcat DefaultServlet (src) and overriding the getRelativePath() method.
package com.example;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.servlets.DefaultServlet;
public class StaticServlet extends DefaultServlet
{
protected String pathPrefix = "/static";
public void init(ServletConfig config) throws ServletException
{
super.init(config);
if (config.getInitParameter("pathPrefix") != null)
{
pathPrefix = config.getInitParameter("pathPrefix");
}
}
protected String getRelativePath(HttpServletRequest req)
{
return pathPrefix + super.getRelativePath(req);
}
}
... And here are my servlet mappings
<servlet>
<servlet-name>StaticServlet</servlet-name>
<servlet-class>com.example.StaticServlet</servlet-class>
<init-param>
<param-name>pathPrefix</param-name>
<param-value>/static</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>StaticServlet</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>