Posted on 2007-02-06 11:47
dennis 阅读(1377)
评论(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等等