Posted on 2007-02-06 11:47
dennis 閱讀(1381)
評論(0) 編輯 收藏 所屬分類:
模式與架構
?一。緩存過濾器模式
1。概念:緩存過濾器模式是通過使用servlet的filter來動態(tài)地緩存生成的頁面,從而提高web層的性能和伸縮性。工作原理非常簡單,當第一次請求到來時,判斷是否可以緩存,可以的話就放在緩存里。當下次請求時,直接從緩存中取出,而不是再次請求。
2。一個簡單實現對html頁面的緩存:
package?cfexample.controller;

import?java.io.*;
import?javax.servlet.*;
import?javax.servlet.http.*;


/**?*//**
?*用來替代HttpServletReponse的新對象,以提供緩存能力
?*/

public?class?CacheResponseWrapper?extends?HttpServletResponseWrapper?
{

????private?CacheOutputStream?outStream;
????
????//替換OutputStream和PrintWriter
????private?ServletOutputStream?stream;
????private?PrintWriter?writer;
????
???

????class?CacheOutputStream?extends?ServletOutputStream?
{
?
????????private?ByteArrayOutputStream?bos;
?

????????CacheOutputStream()?
{
????????????bos?=?new?ByteArrayOutputStream();
????????}
????????
????

????????public?void?write(int?param)?throws?IOException?
{
????????????bos.write(param);
????????}
????????

????????public?void?write(byte[]?b,?int?off,?int?len)?throws?IOException?
{
????????????bos.write(b,?off,?len);
????????}
????????

????????protected?byte[]?getBytes()?
{
????????????return?bos.toByteArray();
????????}
????}
????

?????public?CacheResponseWrapper(HttpServletResponse?original)?
{
????????super(original);
????}
????
????protected?ServletOutputStream?createOutputStream()?
????????throws?IOException

????
{
????????outStream?=?new?CacheOutputStream();
????????return?outStream;
????}
????
????public?ServletOutputStream?getOutputStream()
????????throws?IOException?

????
{

????????if?(stream?!=?null)?
{
????????????return?stream;
????????}
????????

????????if?(writer?!=?null)?
{
????????????throw?new?IOException("Writer?already?in?use");
????????}
????????
????????stream?=?createOutputStream();
????????return?stream;
????}
????

?????public?PrintWriter?getWriter()?throws?IOException?
{

????????if?(writer?!=?null)?
{
????????????return?writer;
????????}
????????

????????if?(stream?!=?null)?
{
????????????throw?new?IOException("OutputStream?already?in?use");
????????}
????????
????????writer?=?new?PrintWriter(new?OutputStreamWriter(createOutputStream()));
????????return?writer;
????}

????protected?byte[]?getBytes()?throws?IOException?
{

????????if?(outStream?!=?null)?
{
????????????return?outStream.getBytes();
????????}
????????
????????return?null;
????}
}

//CacheFilter.java?過濾器:
package?cfexample.controller;

import?java.io.*;
import?java.net.*;
import?java.util.*;
import?java.text.*;
import?javax.servlet.*;
import?javax.servlet.http.*;

import?javax.servlet.Filter;
import?javax.servlet.FilterChain;
import?javax.servlet.FilterConfig;
import?javax.servlet.ServletContext;
import?javax.servlet.ServletException;
import?javax.servlet.ServletRequest;
import?javax.servlet.ServletResponse;

public?class?CacheFilter?implements?Filter?
{

????private?FilterConfig?filterConfig?=?null;
????
????//緩存池
????private?HashMap?cache;
????

????public?CacheFilter()?
{
????}
????public?void?doFilter(ServletRequest?request,?
?????????????????????????ServletResponse?response,
?????????????????????????FilterChain?chain)
????????throws?IOException,?ServletException

????
{
????????HttpServletRequest?req?=?(HttpServletRequest)?request;
????????HttpServletResponse?res?=?(HttpServletResponse)?response;
???????
????????//緩存子中的鍵URI+查詢字符串
????????String?key?=?req.getRequestURI()?+?"?"?+?req.getQueryString();
????????
????????//只緩存get請求的內容

????????if?(req.getMethod().equalsIgnoreCase("get")?&&?isCacheable(key))?
{
????????????byte[]?data?=?(byte[])?cache.get(key);
????????????
???????????//池中沒有,生成并存入

????????????if?(data?==?null)?
{
????????????????CacheResponseWrapper?crw?=?new?CacheResponseWrapper(res);
????????????????chain.doFilter(request,?crw);
????????????????data?=?crw.getBytes();
????????????????cache.put(key,?data);
????????????}?
????????????
????????????//?如果有的話,直接得到返回

????????????if?(data?!=?null)?
{
????????????????res.setContentType("text/html");
????????????????res.setContentLength(data.length);
????????????????

????????????????try?
{
????????????????????OutputStream?os?=?res.getOutputStream();
????????????????????os.write(data);
????????????????????os.flush();
????????????????????os.close();

????????????????}?catch(Exception?ex)?
{
????????????????????ex.printStackTrace();
????????????????}
????????????}

????????}?else?
{
????????????//?generate?the?data?normally?if?it?was?not?cacheable
????????????chain.doFilter(request,?response);
????????}
????}
????
????//判斷是否可以緩存,考慮一個配置文件配置哪些可以緩存,此處省去

????private?boolean?isCacheable(String?key)?
{
????????return?true;
????}
????
????

????public?void?init(FilterConfig?filterConfig)?
{
????????this.filterConfig?=?filterConfig;
????????
????????cache?=?new?HashMap();
????}

????public?void?destroy()?
{
????????cache.clear();
????????
????????cache?=?null;
????????filterConfig?=?null;
????}
}

3.實際應用例子:oscache是很好的解決web層緩存的方案!!準備認真讀讀它的源代碼。
二。資源池模式:
1。概念:一個資源池就是一組預先生成的對象,它們可以被出借以便節(jié)省多次chuang創(chuàng)建它們所花費的時間。典型的如:EJB池(Service Locator一般都有一個ejb的home接口池),數據庫連接池。
2。優(yōu)點:A。提高了應用的可伸縮性,使資源的創(chuàng)建和開銷不至于失控。B,產生了一個統(tǒng)一的有效微調點,通過運行時修改池參數來影響應用的性能等因素。
3。簡單實現:
(1)首先一個創(chuàng)建對象的工廠:
package?pool;


public?interface?ResourceFactory?
{
????public?Object?createResource();
????
????//驗證返回的資源,并提供還原
????public?boolean?validateResource(Object?o);
}(2)資源池:

package?pool;

import?java.util.*;


public?class?ResourcePool?
{
????private?ResourceFactory?factory;
????
???//參數
????private?int?maxObjects;
????private?int?curObjects;
????private?boolean?quit;
????
????//出借的資源
????private?Set?outResources;
????
????//可以使用的資源
????private?List?inResources;
????

????public?ResourcePool(ResourceFactory?factory,?int?maxObjects)?
{
????????this.factory?=?factory;
????????this.maxObjects?=?maxObjects;
????????
????????curObjects?=?0;
????????
????????outResources?=?new?HashSet(maxObjects);
????????inResources?=?new?LinkedList();
????}
????
???//從池中取資源

????public?synchronized?Object?getResource()?throws?Exception?
{

????????while(!quit)?
{
????????

?????????????if?(!inResources.isEmpty())?
{
????????????????Object?o?=?inResources.remove(0);
????????????????
???????????????if(!factory.validateResource(o))
????????????????????o?=?factory.createResource();
????????????????
????????????????outResources.add(o);
????????????????return?o;
????????????}
????????????
????????????//放入出借池

????????????if(curObjects?<?maxObjects)?
{
????????????????Object?o?=?factory.createResource();
????????????????outResources.add(o);
????????????????curObjects++;
????????????????
????????????????return?o;
????????????}
????????????
????????????//沒有可用的,等待

????????????try?
{?wait();?}?catch(Exception?ex)?
{}
????????}
????
???????//池子已經銷毀
????????return?null;
????}
????
????//歸還資源

????public?synchronized?void?returnResource(Object?o)?
{
????????
????????if(!outResources.remove(o))
????????????return;
????????
????????inResources.add(o);
????????notify();
????}
????

????public?synchronized?void?destroy()?
{
????????quit?=?true;
????????notifyAll();
????}
}

4.實例:很多開源的數據庫連接池,ejb模式中的Service Locator等等