庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

缓存filter及资源池模式

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

只有注册用户登录后才能发表评论。


网站导航: