Servlet For Serving Static Content

Servlet for serving static content

I ended up rolling my own StaticServlet. It supports If-Modified-Since, gzip encoding and it should be able to serve static files from war-files as well. It is not very difficult code, but it is not entirely trivial either.

The code is available: StaticServlet.java. Feel free to comment.

Update: Khurram asks about the ServletUtils class which is referenced in StaticServlet. It is simply a class with auxiliary methods that I used for my project. The only method you need is coalesce (which is identical to the SQL function COALESCE). This is the code:

public static <T> T coalesce(T...ts) {
for(T t: ts)
if(t != null)
return t;
return null;
}

Serving static resources at /static/* context while keeping my servlet handling /* context

Here's very clean solution to this problem: http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5:

Unfortunately after looking into DefaultServlet source I found that DefaultServlet takes only pathInfo part of requested URL, so if your request is /static/styles.css, container translates it into /styles.css. Servlet part is omitted by the DefaultServlet. If you want to access such css file you should use /static/static/styles.css request url.

The simple solution of our problem is to write DefaultFilter class and place it at the beginning of web.xml file. This filter will forward all static content calls to DefaultServlet.

Define a filter which will dispatch the request to the default servlet:

public class DefaultFilter implements Filter {  

private RequestDispatcher defaultRequestDispatcher;

@Override
public void destroy() {}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
defaultRequestDispatcher.forward(request, response);
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.defaultRequestDispatcher =
filterConfig.getServletContext().getNamedDispatcher("default");
}
}

Add the filter (ahead of the other filters) to web.xml:

<filter>  
<filter-name>default</filter-name>
<servlet-name>default</servlet-name>
<filter-class>pl.kuligowski.example.DefaultFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>default</filter-name>
<url-pattern>/static/*</url-pattern>
<url-pattern>*.ico</url-pattern>
</filter-mapping>

Only static content calls are matched to DefaultFilter, which simply breaks the filter chain and forwards the request to the DefaultServlet.

Serving static resources, via default servlet, in Jetty

Your @WebServlet defined at PathSpec of "/*" is preventing the default servlet from ever being executed.

You essentially said, "I know what I'm doing, I want all requests, for all paths, to route through me"

Consider setting up your Servlet at pathspec of "/sample", or "/sample/*", or something similar. Anything but "/" or "/*" as that will catch everything.

@WebServlet("/sample/*")

Otherwise, you can reference the default servlet in any container, not just Jetty (its a mandatory feature of the Servlet Spec) like this ...

getServletContext().getNamedDispatcher("default").forward(request, response);

Serving static content

Best to to use static files on the webserver document root. Storing and fetching from the database is not recommended for performance reasons if the files are indeed going to be static.

How to serve static files in my web application on Tomcat

I have some path problems, and I can't resolve them, I searched over
and over again and still not working, I get a 404 (Not Found) for
.../CpdApplication/Chart.js

Indeed, when writing <script src="/Chart.js"/> you are telling the browser to make its own, separate HTTP request to get the JavaScript file. For this to work:

  • The servlet container needs to be able to serve static files
  • To this end, you need to have a servlet-mapping inside your web.xml to serve static files (ie. the default servlet).

This should do:

<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/js/*</url-pattern>
</servlet-mapping>

Then place your Chart.js in the following folder: WebContent/js/ and it should work.

EDIT: Of course, you'll need to update the <script> tag in your HTML. Also, make sure that you redeploy your web app to update web.xml on your servlet container (Tomcat I presume).

Serving static content programmatically from Servlet - does the spec have anything available or i should roll a custom one?

While your problem is a fairly common one there isn't necessarily a standards based solution for every possible design challenge.

I don't think the #2 solution will be sufficient - what if two threads try to manipulate the file at the same time? If someone got the link to the file could they share it?

I've implemented something very similar to your #1 solution - the key there is that even if the link to the file got out no one could reuse the link as it requires security. You would just "return" a 401 or 403 for the resource.

Another possibility depends on how you're hosted. Amazon S3 allows you to generate a signed URL that has a limited time to live. In this way your server isn't sending the file directly. It is either sending a redirect or a URL to the front end to use. Keep the lifetime at like 15 seconds (depending on your needs) and then the URL is no longer valid.

I believe that the other cloud providers have a similar capability too.



Related Topics



Leave a reply



Submit