How to Create a Servlet for Serving Static Content in a Web Application

Question

How can I develop a servlet that serves static content in a web application deployed on both Tomcat and Jetty containers?

Answer

In this guide, we will create a simple servlet to serve static content such as images, CSS, and JavaScript files effectively across Tomcat and Jetty web containers. This servlet will accommodate custom URL routing and leverage caching mechanisms like If-Modified-Since headers for optimized performance.

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;

public class StaticContentServlet extends HttpServlet {
    private String staticPath;

    @Override
    public void init() throws ServletException {
        staticPath = getServletContext().getRealPath("/static");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        File file = new File(staticPath, request.getPathInfo());
        if (!file.exists()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        // Handle If-Modified-Since
        long lastModified = file.lastModified();
        response.setDateHeader("Last-Modified", lastModified);
        if (request.getDateHeader("If-Modified-Since") == lastModified) {
            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            return;
        }
        response.setContentType(getServletContext().getMimeType(file.getName()));
        response.setContentLength((int) file.length());
        try (FileInputStream in = new FileInputStream(file);
             OutputStream out = response.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
    }
}

Causes

  • Tomcat and Jetty have different behaviors regarding static file handling, causing compatibility issues.
  • Need for custom URL patterns to route requests properly to the main servlet and static files.

Solutions

  • Create a dedicated servlet for static content serving.
  • Implement caching support with If-Modified-Since for efficient loading.
  • Optionally include gzip encoding and ETags for compressing responses and supporting cache validation.

Common Mistakes

Mistake: Forgetting to map the servlet correctly in web.xml.

Solution: Ensure correct servlet mappings are defined for both the main and static content servlets.

Mistake: Not checking for file existence before reading.

Solution: Always verify if the requested file exists to avoid server errors.

Mistake: Ignoring cache headers leading to unnecessary file transfers.

Solution: Implement cache control using If-Modified-Since and Last-Modified headers.

Helpers

  • Java servlet
  • serve static content servlet
  • Tomcat Jetty static content
  • If-Modified-Since header
  • gzip encoding servlet

Related Questions

⦿How to Convert a Byte Array to an InputStream in Java?

Learn how to convert a byte array into an InputStream in Java with code examples and solutions for common issues.

⦿Understanding the Java `final` Method: What Guarantees Does It Offer?

Learn what the final keyword promises in Java methods and its implications from an ObjectOriented Programming OOP perspective.

⦿What Are Bytecode Features Not Accessible in the Java Language?

Explore bytecode features in Java that are unavailable in the Java language and learn about distinguished bytecode functionalities in Java programming.

⦿How to Prevent a White Screen During Android App Startup?

Learn how to avoid a white screen during your Android app startup by optimizing your Application class and splash screen implementation.

⦿How to Convert an Array of Primitive Longs to a List of Longs in Java?

Learn how to properly convert an array of primitive longs to a List of Longs in Java with detailed examples and common pitfalls.

⦿How to Specify the JDK Version in Android Studio for Gradle Builds?

Learn how to set the correct JDK version in Android Studio to avoid Gradle build errors ensuring a smooth development experience.

⦿How to Identify and Troubleshoot Memory Leaks in Java Using JHat

Learn effective methods to find memory leaks in Java with JHat including techniques for analyzing heap dumps and identifying large object trees.

⦿How to Properly Return a Void Type in Java

Learn the correct approach to return a Void type in Java including code examples and common mistakes.

⦿Best Practices for Naming Utility Classes in Java

Discover effective naming conventions for utility classes in Java including guidance on using Util vs Utils and Helper vs Utility.

⦿How to Print Line Numbers in Java Logs: A Comprehensive Guide

Learn how to print line numbers in Java logs efficiently. Explore methods to include line numbers in your Java logging output for better debugging.

© Copyright 2025 - CodingTechRoom.com