<s1 title="Server Caching">

<p>Server caching can speed dynamic pages to
near-static speeds.   Many pages created by database
queries only change every 15 minutes or so, e.g. CNN or Slashdot.
Resin can cache the results and serve them like static pages.</p>

<p>Resin's caching operates like a proxy cache.  Every user 
shares the same cached page.</p>

<s2 title='Expires'>

<p>Setting the <var>Expires</var> header will cache the results
until the time expires.  For heavily loaded pages, even setting short
expires times can significantly improve performance.  Sessions should
be disabled for caching.</p>

<p>The following example sets expiration for 15 seconds.  So the
counter should update slowly.</p>

<example title='Expires'>
&lt;%@ page session=false %>
&lt;%! int counter; %>
&lt;%
long now = System.currentTimeMillis();
response.setDateHeader("Expires", now + 15000);
%>
Count: &lt;%= counter++ %>
</example>

<p><var/Expires/> is useful for database generated pages which are
continuously, but slowly updated.  To cache based on something with a known
modified date, like a file, you can use <var/If-Modified/>.</p>

</s2>

<s2 title='If-Modified'>

<p>The <var>If-Modified</var> headers let you cache based on an
underlying change date.  For example, the page may only change when an
underlying source page changes.  Resin lets you easily use 
<var>If-Modified</var> by overriding methods in HttpServlet or
in a JSP page.</p>

<p>The following page only changes when the underlying 'test.xml'
page changes.</p>

<example>
&lt;%@ page session=false %>
&lt;%!
int counter;

public long getLastModified(HttpServletRequest req)
{
  String path = req.getRealPath("test.xml");
  return new File(path).lastModified();
}
%>
Count: &lt;%= counter++ %>
</example>

</s2>

<s2 title='Included Pages'>

<p>Resin can cache subpages even when the top page can't be cached.
Sites allowing user personalization will often design pages with
<var/jsp:include/> subpages.  Some subpages are user-specific and can't
be cached.  Others are common to everybody and can be cached.</p>

<p>Resin treats subpages as independent requests, so they can be
cached independent of the top-level page.  Try the following, use the
first <var/expires/> counter example as the included page.  Create a
top-level page that looks like:</p>

<example>
&lt;%@ page session=true %>
&lt;% if (! session.isNew()) { %>
&lt;h1>Welcome back!&lt;/h1>
&lt;% } %>

&lt;jsp:include page="expires.jsp"/>
</example>

</s2>
</s1>
