Sem reinventar a roda, cache de páginas com EhCache e ServletFilter

Não faz muito tempo, surgiu a necessidade de aumentar o desempenho de uma aplicação JEE, e começamos a ver profile daqui, examina relatórios dali, nisso um amigo de projeto, que a pouco tempo havia se enturmado com Rails, teve uma idéia: "Por que não fazemos cache das páginas mais frequentes, podemos criar um pequeno framework, e fazer como o Rails faz", explicando... em Rails basta colocar no controller as páginas que você deseja que sejam "cacheadas". Ex:

RUBY:
  1. caches_page :noticias

Pronto, a primeira chamada à action "noticias" cria o cache, e será usada pelas chamadas subsequentes. Para expirar o cache basta chamar:

RUBY:
  1. expire_page(:controller => 'public', :action => 'noticias')

Mais detalhes e excelente tutorial no Rails Envy.

Eu gosto muito de criar coisas novas, mas como dito no último post, criar mais um mini-framework para dar manutenção em uma aplicação já não muito pequena... bem, não obrigado. Foi por isso que eu disse: "Cara, dá uma pesquisada, com certeza alguém já fez isso." E pra variar, sim alguém já fez isso.

O excelente e bem conhecido EhCache possui esta funcionalidade e muitas outras.

Este mini tutorial parte do pressuposto que já se tem conhecimento do EhCache e de ServletFilter, para quem não conhece qualquer um dos dois, sem pânico, são muito fáceis de serem utilizados, vale uma pesquisada por tutoriais.

Para facilitar a vida, podem baixar este anexo com a aplicação-exemplo que fiz, basta colocá-lo em seu container web predileto, no meu caso testei no Tomcat, e acessar as URLs de teste:

http://localhost:8080/cache/semcache/teste.jsp

http://localhost:8080/cache/comcache/teste.jsp

O exemplo, mostra a hora atual em milesegundos. A página com cache, após acessada, terá 10 seg de vida.

Para implementar bastou os seguintes passos:

- Baixar e instalar os jars EhCache (ehcache-1.3.0-beta.jar), EhCache Constructors (ehcache-constructs-0.7.3.jar) e Commons-logging (dependência requerida) no diretório lib.

- Incluir no arquivo ehcache.xml as configurações para cache de página, as propriedades falam por si, configurem a gosto:

XML:
  1. <cache name="SimplePageCachingFilter"
  2.     maxElementsInMemory="10000"
  3.     maxElementsOnDisk="1000"
  4.     eternal="false"
  5.     overflowToDisk="true"
  6.     timeToIdleSeconds="10"
  7.     timeToLiveSeconds="10"
  8.     memoryStoreEvictionPolicy="LRU"
  9. >

- Configurar um ServletFilter no web.xml, para a implementação de filtro SimplePageCachingFilter

XML:
  1. <filter>
  2.    <filter-name>SimplePageCachingFilter</filter-name>
  3.    <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter</filter-class>
  4.    <init-param>
  5.        <param-name>suppressStackTraces</param-name>
  6.        <param-value>false</param-value>
  7.        <description>Whether to suppress stack traces in the filter</description>
  8.    </init-param>
  9. </filter>

- Indicar para quais páginas fazer cache a partir do ServletFilter definido acima, dentro do web.xml. No exemplo, tudo que estiver abaixo do diretório "comcache".

XML:
  1. <filter-mapping>
  2.    <filter-name>SimplePageCachingFilter</filter-name>
  3.    <url-pattern>/comcache/*</url-pattern>
  4. </filter-mapping>

Pronto, é somente isso, a página será devidamente cacheada, seguindo as configurações do ehcache.xml.

Caso queira fazer cache de apenas uma parte da página, no caso de quem utiliza jsp:include, basta utilizar a outra implementação PageFragmentCachingFilter

Essa pequena implementação já garantiu um bom desempenho em várias páginas e sem reinventar a roda criando um mini-framework para esta função.

Se alguém souber de outro meio para fazer cache de página em Java, por favor esteja a vontade para comentar, gostaria muito de conhecer outras implementações.

Deixe seu comentário