net.sf.ehcache.constructs.web.filter
Class SimpleCachingHeadersPageCachingFilter
java.lang.Object
net.sf.ehcache.constructs.web.filter.Filter
net.sf.ehcache.constructs.web.filter.CachingFilter
net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
net.sf.ehcache.constructs.web.filter.SimpleCachingHeadersPageCachingFilter
- All Implemented Interfaces:
- javax.servlet.Filter
public class SimpleCachingHeadersPageCachingFilter
- extends SimplePageCachingFilter
This Filter extends SimplePageCachingFilter, adding support for
the HTTP cache headers: ETag, Last-Modified and Expires.
Because browsers and other HTTP clients have the expiry information returned in the response headers,
they do not even need to request the page again. Even once the local browser copy has expired, the browser
will do a conditional GET.
So why would you ever want to use SimplePageCachingFilter, which does not set these headers? Because in some caching
scenarios you may wish to remove a page before its natural expiry. Consider a scenario where a web page shows dynamic
data. Under ehcache the Element can be removed at any time. However if a browser is holding expiry information, those
browsers will have to wait until the expiry time before getting updated. The caching in this scenario is more about
defraying server load rather than minimising browser calls.
It uses a Singleton CacheManager created with the default factory method. Override to use a different CacheManager
The meaning of page is:
- A complete response i.e. not a fragment.
- A content type suitable for gzipping. e.g. text or text/html
For jsp:included page fragme?nts see SimplePageFragmentCachingFilter.
calculateKey
Pages are cached based on their key. The key for this cache is the URI followed by the query string. An example
is /admin/SomePage.jsp?id=1234&name=Beagle.
This key technique is suitable for a wide range of uses. It is independent of hostname and port number, so will
work well in situations where there are multiple domains which get the same content, or where users access
based on different port numbers.
A problem can occur with tracking software such as Google AdWords, where unique ids are inserted into request query strings. Because
each request generates a unique key, there will never be a cache hit. For these situations it is better to
override SimplePageCachingFilter.calculateKey(javax.servlet.http.HttpServletRequest) with
an implementation that takes account of only the significant parameters.
Configuring the cacheName
A cache entry in ehcache.xml should be configured with the name of the filter.
Names can be set using the init-param cacheName, or by sub-classing this class and overriding the name.
Concurent Cache Misses
A cache miss will cause the filter chain, upstream of the caching filter to be processed. To avoid threads requesting
the same key to do useless duplicate work, these threads block behind the first thread.
The thead timeout can be set to fail after a certain wait by setting the init-param blockingTimeoutMillis.
By default threads wait indefinitely. In the event upstream processing never returns, eventually the web server
may get overwhelmed with connections it has not responded to. By setting a timeout, the waiting threads will only block
for the set time, and then throw a LockTimeoutException. Under either
scenario an upstream failure will still cause a failure.
Gzipping
Significant network efficiencies can be gained by gzipping responses.
Whether a response can be gzipped depends on:
- Whether the user agent can accept GZIP encoding. This feature is part of HTTP1.1.
If a browser accepts GZIP encoding it will advertise this by including in its HTTP header:
All common browsers except IE 5.2 on Macintosh are capable of accepting gzip encoding. Most search engine
robots do not accept gzip encoding.
- Whether the user agent has advertised its acceptance of gzip encoding. This is on a per request basis. If they
will accept a gzip response to their request they must include the following in the HTTP request header:
Accept-Encoding: gzip
Responses are automatically gzipped and stored that way in the cache. For requests which do not accept gzip
encoding the page is retrieved from the cache, ungzipped and returned to the user agent. The ungzipping is
high performance.
Caching Headers
This filter sets the HTTP cache headers: ETag, Last-Modified and Expires. It supports conditional GET.
Because browsers and other HTTP clients have the expiry information returned in the response headers,
they do not even need to request the page again. Even once the local browser copy has expired, the browser
will do a conditional GET.
So why would you ever want to use SimplePageCachingFilter, which does not set these headers?
The answer is that in some caching
scenarios you may wish to remove a page before its natural expiry. Consider a scenario where a web page shows dynamic
data. Under ehcache the Element can be removed at any time. However if a browser is holding expiry information, those
browsers will have to wait until the expiry time before getting updated. The caching in this scenario is more about
defraying server load rather than minimising browser calls.
Init-Params
The following init-params are supported:
- cacheName - the name in ehcache.xml used by the filter.
- blockingTimeoutMillis - the time, in milliseconds, to wait for the filter chain to return with a response on a cache
miss. This is useful to fail fast in the event of an infrastructure failure.
Reentrance
Care should be taken not to define a filter chain such that the same CachingFilter class is reentered.
The CachingFilter uses the BlockingCache. It blocks until the thread which
did a get which results in a null does a put. If reentry happens a second get happens before the first put. The second
get could wait indefinitely. This situation is monitored and if it happens, an IllegalStateException will be thrown.
- Author:
- Craig Andrews, Greg Luck
- See Also:
SimplePageCachingFilter
|
Field Summary |
static java.lang.String |
NAME
The name of the filter. |
|
Method Summary |
protected PageInfo |
buildPage(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
javax.servlet.FilterChain chain)
Builds the PageInfo object by passing the request along the filter chain |
protected long |
calculateTimeToLiveMilliseconds()
Get the time to live for a page, in milliseconds |
protected HttpDateFormatter |
getHttpDateFormatter()
|
protected void |
writeResponse(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
PageInfo pageInfo)
Writes the response from a PageInfo object. |
| Methods inherited from class net.sf.ehcache.constructs.web.filter.CachingFilter |
buildPageInfo, checkNoReentry, doDestroy, doFilter, doInit, setCacheNameIfAnyConfigured, setContentType, setCookies, setHeaders, setStatus, writeContent |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
NAME
public static final java.lang.String NAME
- The name of the filter. This should match a cache name in ehcache.xml
- See Also:
- Constant Field Values
SimpleCachingHeadersPageCachingFilter
public SimpleCachingHeadersPageCachingFilter()
buildPage
protected PageInfo buildPage(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
javax.servlet.FilterChain chain)
throws AlreadyGzippedException,
java.lang.Exception
- Builds the PageInfo object by passing the request along the filter chain
The following headers are set:
- Last-Modified
- Expires
- Cache-Control
- ETag
Any of these headers aleady set in the response are ignored, and new ones generated. To control
your own caching headers, use SimplePageCachingFilter.
- Overrides:
buildPage in class CachingFilter
- Parameters:
request - response - chain -
- Returns:
- a Serializable value object for the page or page fragment
- Throws:
AlreadyGzippedException - if an attempt is made to double gzip the body
java.lang.Exception
getHttpDateFormatter
protected final HttpDateFormatter getHttpDateFormatter()
- Returns:
- A lazily created HttpDateFormatter instance scoped to this filter
writeResponse
protected void writeResponse(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
PageInfo pageInfo)
throws java.io.IOException,
java.util.zip.DataFormatException,
ResponseHeadersNotModifiableException
- Writes the response from a PageInfo object.
This method actually performs the conditional GET and returns 304
if not modified, short-circuiting the normal writeResponse.
Indeed, if the short cicruit does not occur it calls the super method.
- Overrides:
writeResponse in class CachingFilter
- Throws:
java.io.IOException
java.util.zip.DataFormatException
ResponseHeadersNotModifiableException
calculateTimeToLiveMilliseconds
protected long calculateTimeToLiveMilliseconds()
- Get the time to live for a page, in milliseconds
- Returns:
- time to live in milliseconds
Copyright ? 2003-2010 Terracotta, Inc.. All Rights Reserved.