分享

缓存filter及资源池模式

 风中的眼睛_ 2013-05-14
一。缓存过滤器模式
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等等

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多