When working with static resources like CSS and HTML files in Tomcat, you might encounter frustrating caching behavior where changes don't appear even after:
- Browser cache clearing
- Different browser testing
- Different machine testing
- Hard refreshes (Ctrl+F5)
Tomcat implements caching through its DefaultServlet
with these default settings:
<!-- In conf/web.xml -->
<init-param>
<param-name>fileCaching</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cacheTTL</param-name>
<param-value>5000</param-value>
</init-param>
1. Modify web.xml Configuration
Update your application's web.xml:
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>cachingAllowed</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
2. Version Your Static Files
Add version parameter to resource URLs:
<link rel="stylesheet" href="/styles/main.css?v=1.0.23">
3. Use Cache-Control Headers
Create a filter to set headers:
public class NoCacheFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "0");
chain.doFilter(req, res);
}
// init() and destroy() methods...
}
4. Development-Specific Configuration
For Maven projects, add to pom.xml:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Confirm caching is disabled by:
- Checking response headers in browser dev tools
- Using curl:
curl -I http://yourserver/static/style.css
- Adding timestamp logging in your application
For complete control, serve static files through a custom servlet:
@WebServlet("/static/*")
public class StaticServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Your custom implementation without caching
}
}
Working with static files during web development can become frustrating when Tomcat's caching behavior prevents changes from appearing immediately. Many developers encounter situations where updated CSS/HTML files don't reflect changes until after a server restart - even across different browsers and machines.
Tomcat implements caching for static resources by default to improve performance in production environments. The default cache settings include:
- Static resource caching enabled
- Cache TTL (Time-To-Live) of 5000ms (5 seconds)
- Maximum cache size of 10240KB
For development environments, you can completely disable caching by modifying your context.xml file:
<Context>
<Resources cachingAllowed="false" />
</Context>
Alternatively, add this to your web.xml:
<filter>
<filter-name>NoCacheFilter</filter-name>
<filter-class>org.apache.catalina.filters.RestExpiresFilter</filter-class>
<init-param>
<param-name>ExpiresByType text/css</param-name>
<param-value>access plus 0 seconds</param-value>
</init-param>
</filter>
For production environments where you want some caching but still need control:
<Context>
<Resources
cachingAllowed="true"
cacheMaxSize="102400"
cacheTtl="60000"
cacheObjectMaxSize="51200" />
</Context>
Even after configuring Tomcat, browsers might still cache resources. Implement versioning for your static files:
<link rel="stylesheet" href="/css/styles.css?v=1.0.1">
To confirm caching is disabled, check HTTP headers in browser dev tools. You should see:
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0