Posted on 2007-02-06 11:47
dennis 阅读(1380)
评论(0) 编辑 收藏 所属分类:
模式与架构
一。缓存过滤器模式
1。概念:缓存过滤器模式是通过使用servlet的filter来动态地缓存生成的页面,从而提高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。概念:一个资源池就是一组预先生成的对象,它们可以被出借以便节省多次chuang创建它们所花费的时间。典型的如:EJB池(Service Locator一般都有一个ejb的home接口池),数据库连接池。
2。优点:A。提高了应用的可伸缩性,使资源的创建和开销不至于失控。B,产生了一个统一的有效微调点,通过运行时修改池参数来影响应用的性能等因素。
3。简单实现:
(1)首先一个创建对象的工厂:
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等等