| 
				
 公告 
				日历 
			
			
				
	 |  | 日 | 一 | 二 | 三 | 四 | 五 | 六 | 
|---|
 | 26 | 27 | 28 | 29 | 30 | 31 | 1 |  | 2 | 3 | 4 | 5 | 6 | 7 | 8 |  | 9 | 10 | 11 | 12 | 13 | 14 | 15 |  | 16 | 17 | 18 | 19 | 20 | 21 | 22 |  | 23 | 24 | 25 | 26 | 27 | 28 | 29 |  | 30 | 1 | 2 | 3 | 4 | 5 | 6 |  
  | 
			 
			 
				
				
				
导航
				
		随笔分类(86)
		
				
			
	
		随笔档案(85)
		
				
			
	
搜索
最新评论
	 
阅读排行榜
评论排行榜
				
				  
		 | 
		
				
					
	
	OSCache使用 
我们网站在优化之前速度是很慢的,后来采用了OScache,网站性能才得以大幅度提升。下面把心得体会写下来备忘。 
因为现在的项目以.jsp结尾的已经不多了。所以直接在jsp页面里加cache的形式已经不常。最常用的还是在web.xml里使用oscache的过滤器(com.opensymphony.oscache.web.filter.CacheFilter).基本的配置也很方便:  
<filter> 
  <filter-name>CacheFilter_yedian</filter-name> 
  <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> 
  <init-param> 
   <param-name>time</param-name> 
   <param-value>3600</param-value> 
  </init-param> 
  <init-param> 
      <param-name>scope</param-name> 
      <param-value>session</param-value> 
  </init-param> 
 </filter> 
<filter-mapping> 
  <filter-name>CacheFilter_yedian</filter-name> 
  <url-pattern>/ystore!allStores.do</url-pattern> 
 </filter-mapping> 
 <filter-mapping> 
  <filter-name>CacheFilter_yedian</filter-name> 
  <url-pattern>/ystore!storedetail.do</url-pattern> 
 </filter-mapping> 
1.scope是cache的范围。有request,session,application几种选项。request范围太短,用了性能不会提高多少,几乎没用。 
可以把cache想像成一个池子。 
session是针对一个用户有一个cache,在请求的url相同的情况下,cache住的页面内容和其他用户是不一样的。一个用户使用一个池子。比request级缓存更省资源。 
application是针对所有用户的一个cache,打开一个url后,所有的用户看见的内容都一样。大家都共用这个池子。比session级更节省资源。速度也相当于静态化的html页。 
2.深层问题:cache是根据什么来缓存内容的呢? 
    <filter-mapping> 
  <filter-name>CacheFilter_yedian</filter-name> 
  <url-pattern>/ystore!allStores.do</url-pattern> 
 </filter-mapping> 
 <filter-mapping> 
  <filter-name>CacheFilter_yedian</filter-name> 
  <url-pattern>/ystore!storedetail.do</url-pattern> 
 </filter-mapping> 
 过滤器当然会过滤所有的url,但在这个例子中,oscache只cache住包含ystore!allStores.do和ystore!storedetail.do字串的url内容。具体过程是这样: 
    (1.它过滤到符合条件的url后,把/ystore!storedetail.do***之后的字串进行BASE32位编码,得到一个key。 
    (2.拿着这个key去内容中进行hashMap查找,如果找到了,就把value返回给客户端,否则,把这个key与服务器返回的内容作为一个HashMap(kay-->value)存进内存。  
    (3.当再次过滤到符合条件的url后,把/ystore!storedetail.do***之后的字串进行BASE32位编码,得到一个key,然后重复第2步。 
看个实际例子: 
/movo/space!index.do?domainname=baibai33的key是: 
/movo/space!index.do_GET__XlqMV1F+oEsiCojKiHblVA== 
/movo/space!index.do?domainname=baibai33¤tLanguage=en的key 是: 
/movo/space!index.do_GET__aIkteNEKWe9Vn4jnBGGs6A== 
所以,这种缓存不适用于用Session或者request传递查询条件的情况。它只认url,相信这一点并记住这一点。 
3.缓存的手工清除。 
   当用户登陆自己的页面或者发表了一个评论,我们就应该手工清除(刷新)cache中的缓存,而不应该靠设定的时间来清除了。   这时要使用ServletCacheAdministrator类。ServletCacheAdministrator.getInstance(request.getSession().getServletContext()).flushAll();目前它只有一个.flushAll()可用。普通cache管理类GeneralCacheAdministrator类对过滤的cache是不管用的。 
4.下面是了key级cache刷新的代码  
 
  可以展开 
  1 BaseAction里 
  2   public void flushCache() { 
  3         //ServletCacheAdministrator sevletCacheAdmin = ServletCacheAdministrator.getInstance(ServletActionContext.getServletContext()); 
  4         //sevletCacheAdmin.flushAll(); 
  5         //分析: 
  6          /** *//** 
  7          * url:/movo/space!index.do?domainname=baibai33 
  8          * url:/movo/space!index.do?domainname=baibai33¤tLanguage=en|ko|ja|zh 
  9          * url:/movo/space!index.do?suserid=ff80808118e144960118e3a112650009 
 10          * url:/movo/space!index.do?suserid=ff80808118e144960118e3a112650009¤tLanguage=en|ko|ja|zh 
 11          * 需要的东西有:suserid,domainname 
 12          * **/ 
 13          String domainname=null; 
 14          String suserid =null; 
 15          suserid = WebUtils.getCookieValue(ServletActionContext.getRequest(), Constants.COOKIE_BLOGER_ID); 
 16          domainname = WebUtils.getCookieValue(ServletActionContext.getRequest(), Constants.COOKIE_BLOGER_DOMAINNAME); 
 17          if(suserid!=null||domainname!=null) 
 18          WebOSCacheUtil.flushKey(suserid, domainname, 4); 
 19           
 20           
 21     } 
 22 package com.movo.tv.common.util; 
 23 import java.util.ArrayList; 
 24 import java.util.Iterator; 
 25 import java.util.List; 
 26 import java.util.Map; 
 27 import java.util.Set; 
 28 import java.util.TreeMap; 
 29 import javax.servlet.http.HttpServletRequest; 
 30 import javax.servlet.jsp.PageContext; 
 31 import org.apache.log4j.Logger; 
 32 import com.opensymphony.oscache.base.Cache; 
 33 import com.opensymphony.oscache.web.ServletCacheAdministrator; 
 34 import com.opensymphony.webwork.ServletActionContext; 
 35  
 36  /** *//** 
 37  * osCache缓存工具类. 
 38  * cacheScope:page Level:1,request Level:2,Session Level:3,Application Level:4 
 39  * @version 1.0 
 40  */ 
 41  public class WebOSCacheUtil  { 
 42   private static final Logger log = Logger.getLogger( WebOSCacheUtil.class ); 
 43   public static final int ALL_SCOPE = 0; 
 44   public static final int SESSION_SCOPE = PageContext.SESSION_SCOPE; 
 45   public static final int APPLICATION_SCOPE = PageContext.APPLICATION_SCOPE; 
 46   public final static String SESSION_SCOPE_NAME = "session"; 
 47   public final static String APPLICATION_SCOPE_NAME = "application"; 
 48   public final static String HASH_KEY_SCOPE = "scope"; 
 49   public final static String HASH_KEY_SESSION_ID = "sessionId"; 
 50   public final static String HASH_KEY_CONTEXT_TMPDIR = "context.tempdir"; 
 51   private final static String FILE_SEPARATOR = "/"; 
 52   private final static char FILE_SEPARATOR_CHAR = FILE_SEPARATOR.charAt(0); 
 53   private final static short AVERAGE_KEY_LENGTH = 30; 
 54   private static final String m_strBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
 55   private boolean useHostDomainInKey = false; 
 56   private static ServletCacheAdministrator admin = null; 
 57    private WebOSCacheUtil() {} 
 58  
 59    /** *//** 
 60    * 刷新osCache组 
 61    * @param group Cache组名 
 62    * @param cacheScope Cache范围,只能是SESSION_SCOPE或APPLICATION_SCOPE 
 63    */ 
 64    public static void flushGroup( String group, int cacheScope ) { 
 65     initCacheAdmin(); 
 66      if ( cacheScope == SESSION_SCOPE || cacheScope == APPLICATION_SCOPE ) { 
 67       Cache cache = admin.getCache( ServletActionContext.getRequest(), 
 68                                     cacheScope ); 
 69       cache.flushGroup( group ); 
 70     } 
 71     else 
 72       { 
 73       log.warn( "A cache group was specified for flushing, but the scope wasn't supplied or was invalid" ); 
 74     } 
 75   } 
 76  
 77    
 78    public static List<String> getBaseKeys(String uri,String suserid,String domainname) { 
 79       List<String> keys = new ArrayList<String>(); 
 80       String url1=null,url2,url3,url4,url5=null,url6,url7,url8,url9,url10; 
 81        if(suserid!=null&&!suserid.equals("")) { 
 82           url1 = "suserid="+suserid; 
 83           url2 ="currentLanguage=zh&"+url1; 
 84           String url2_page="currentLanguage=zh&pageNo=1&"+url1; 
 85           url3 ="currentLanguage=en&"+url1; 
 86           String url3_page="currentLanguage=en&pageNo=1&"+url1; 
 87           url4 ="currentLanguage=ko&"+url1; 
 88           String url4_page="currentLanguage=ko&pageNo=1&"+url1; 
 89           url5 ="currentLanguage=ja&"+url1; 
 90           String url5_page="currentLanguage=ja&pageNo=1&"+url1; 
 91           String actualKey1 = WebOSCacheUtil.getURlKey(uri,url1); 
 92           String actualKey2 = WebOSCacheUtil.getURlKey(uri,url2); 
 93           String actualKey3 = WebOSCacheUtil.getURlKey(uri,url3); 
 94           String actualKey4 = WebOSCacheUtil.getURlKey(uri,url4); 
 95           String actualKey5 = WebOSCacheUtil.getURlKey(uri,url5); 
 96           keys.add(actualKey1); 
 97           keys.add(actualKey2); 
 98           keys.add(WebOSCacheUtil.getURlKey(uri, url2_page)); 
 99           keys.add(actualKey3); 
100           keys.add(WebOSCacheUtil.getURlKey(uri, url3_page)); 
101           keys.add(actualKey4); 
102           keys.add(WebOSCacheUtil.getURlKey(uri, url4_page)); 
103           keys.add(actualKey5); 
104           keys.add(WebOSCacheUtil.getURlKey(uri, url5_page)); 
105           
106       } 
107        if(domainname!=null&&!domainname.equals("")) { 
108           url6="domainname="+domainname; 
109           url7="currentLanguage=zh&"+url6; 
110           url8="currentLanguage=en&"+url6; 
111           url9="currentLanguage=ko&"+url6; 
112           url10="currentLanguage=ja&"+url6; 
113           String actualKey6 = WebOSCacheUtil.getURlKey(uri,url6); 
114           String actualKey7 = WebOSCacheUtil.getURlKey(uri,url7); 
115           String actualKey8 = WebOSCacheUtil.getURlKey(uri,url8); 
116           String actualKey9 = WebOSCacheUtil.getURlKey(uri,url9); 
117           String actualKey10 = WebOSCacheUtil.getURlKey(uri,url10); 
118           keys.add(actualKey6); 
119           keys.add(actualKey7); 
120           keys.add(actualKey8); 
121           keys.add(actualKey9); 
122           keys.add(actualKey10); 
123       } 
124        
125       return keys; 
126        
127   } 
128    
129    
130    public  static List<String> getKeys(String suserid,String domainname) { 
131       List<String> keys = new ArrayList<String>(); 
132       
133       String uri ="/movo/space!index.do"; 
134       String uri2="/movo/musicIndex!initPage.do"; 
135       String uri3="/movo/blogClass!initPage.do"; 
136       String uri4="/movo/blogClass!initPage.do"; 
137       keys.addAll(WebOSCacheUtil.getBaseKeys(uri, suserid, domainname)); 
138      // keys.addAll(WebOSCacheUtil.getBaseKeys(uri2, suserid, domainname)); 
139      // keys.addAll(WebOSCacheUtil.getBaseKeys(uri3, suserid, domainname)); 
140      // keys.addAll(WebOSCacheUtil.getBaseKeys(uri4, suserid, domainname)); 
141       return keys; 
142   }  
143    /** *//**flush a key 
144    * @param key String 
145    * @param cacheScope Cache范围,只能是SESSION_SCOPE或APPLICATION_SCOPE 
146    */ 
147    public static void flushKey(String suserid,String domainname,  int cacheScope ) { 
148      if ( cacheScope == SESSION_SCOPE || cacheScope == APPLICATION_SCOPE ) { 
149           initCacheAdmin(); 
150           HttpServletRequest request_ = ServletActionContext.getRequest(); 
151           Cache cache = admin.getCache(request_, cacheScope ); 
152           List li = WebOSCacheUtil.getKeys(suserid,domainname); 
153            for(int i=0;i<li.size();i++) { 
154               cache.flushEntry((String)li.get(i)); 
155           } 
156            
157      }else { 
158       log.warn( "A cache key was specified for flushing, but the scope wasn't supplied or was invalid" ); 
159     } 
160   } 
161  
162    /** *//** *//** *//** 
163    * 刷新所有的osCache 
164    * @param cacheScope Cache范围,可以是SESSION_SCOPE,APPLICATION_SCOPE,ALL_SCOPE 
165    */ 
166   public static void flushAll( int cacheScope ) 
167     { 
168     initCacheAdmin(); 
169  
170     if ( cacheScope == SESSION_SCOPE || cacheScope == APPLICATION_SCOPE ) 
171       { 
172       admin.setFlushTime( cacheScope ); 
173     } 
174     else 
175       { 
176       admin.flushAll(); 
177     } 
178   } 
179  
180  
181   private static void initCacheAdmin() 
182     { 
183     if ( admin == null ) 
184       { 
185       admin = ServletCacheAdministrator.getInstance( ServletActionContext. 
186           getServletContext() ); 
187     } 
188   } 
189    /** *//** 
190    *jar包中的生成key的代码 
191    */ 
192     public String generateEntryKey(String serverName,String RequestURI,String requestMethod,Map ParameterMap,int scope)  { 
193         /** *//** 
194        * Used for generating cache entry keys.  
195        * key,language,suffix  maybe is null; 
196        */ 
197        StringBuffer cBuffer = new StringBuffer(AVERAGE_KEY_LENGTH); 
198  
199        // Servers for multiple host domains need this distinction in the key 
200         if (useHostDomainInKey)  { 
201            cBuffer.append(FILE_SEPARATOR).append(serverName); 
202        } 
203  
204            String generatedKey = RequestURI; 
205  
206             if (generatedKey.charAt(0) != FILE_SEPARATOR_CHAR)  { 
207                cBuffer.append(FILE_SEPARATOR_CHAR); 
208            } 
209  
210            cBuffer.append(generatedKey); 
211            cBuffer.append("_").append(requestMethod).append("_"); 
212  
213            generatedKey = getSortedQueryString(ParameterMap); 
214  
215             if (generatedKey != null)  { 
216                 try  { 
217                    java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); 
218                    byte[] b = digest.digest(generatedKey.getBytes()); 
219                    cBuffer.append('_'); 
220  
221                    // Base64 encoding allows for unwanted slash characters. 
222                    cBuffer.append(toBase64(b).replace('/', '_')); 
223                 } catch (Exception e)  { 
224                    // Ignore query string 
225                } 
226            } 
227        return cBuffer.toString(); 
228    } 
229  
230     /** *//** 
231    * jar包中生成查询的代码 
232    */ 
233     protected String getSortedQueryString( Map paramMap)  { 
234  
235         if (paramMap.isEmpty())  { 
236            return null; 
237        } 
238        Set paramSet = new TreeMap(paramMap).entrySet(); 
239        StringBuffer buf = new StringBuffer(); 
240        boolean first = true; 
241         for (Iterator it = paramSet.iterator(); it.hasNext();)  { 
242            Map.Entry entry = (Map.Entry) it.next(); 
243            String[] values = (String[]) entry.getValue(); 
244             for (int i = 0; i < values.length; i++)  { 
245                String key = (String) entry.getKey(); 
246                 if ((key.length() != 10) || !"jsessionid".equals(key))  { 
247                     if (first)  { 
248                        first = false; 
249                     } else  { 
250                        buf.append('&'); 
251                    } 
252                    buf.append(key).append('=').append(values[i]); 
253                } 
254            } 
255        } 
256  
257        // We get a 0 length buffer if the only parameter was a jsessionid 
258         if (buf.length() == 0)  { 
259            return null; 
260         } else  { 
261            return buf.toString(); 
262        } 
263    } 
264    
265     /** *//** 
266     * Convert a byte array into a Base64 string (as used in mime formats) 
267     */ 
268      private static String toBase64(byte[] aValue)  { 
269         int byte1; 
270         int byte2; 
271         int byte3; 
272         int iByteLen = aValue.length; 
273         StringBuffer tt = new StringBuffer(); 
274  
275          for (int i = 0; i < iByteLen; i += 3)  { 
276             boolean bByte2 = (i + 1) < iByteLen; 
277             boolean bByte3 = (i + 2) < iByteLen; 
278             byte1 = aValue[i] & 0xFF; 
279             byte2 = (bByte2) ? (aValue[i + 1] & 0xFF) : 0; 
280             byte3 = (bByte3) ? (aValue[i + 2] & 0xFF) : 0; 
281  
282             tt.append(m_strBase64Chars.charAt(byte1 / 4)); 
283             tt.append(m_strBase64Chars.charAt((byte2 / 16) + ((byte1 & 0x3) * 16))); 
284             tt.append(((bByte2) ? m_strBase64Chars.charAt((byte3 / 64) + ((byte2 & 0xF) * 4)) : '=')); 
285             tt.append(((bByte3) ? m_strBase64Chars.charAt(byte3 & 0x3F) : '=')); 
286         } 
287  
288         return tt.toString(); 
289     } 
290      /** *//** 
291      * 根据查询生成唯一的key 
292      * @param urlQuery 
293      * @return 
294      */ 
295      public static String getURlKey(String URI,String queryString) { 
296         String testUrlQuery=queryString; 
297         StringBuffer cBuffer = new StringBuffer(AVERAGE_KEY_LENGTH); 
298          if (false)  { 
299           //  cBuffer.append(FILE_SEPARATOR).append(serverName); 
300         } 
301        String generatedKey = URI;// 
302  
303              if (generatedKey.charAt(0) != FILE_SEPARATOR_CHAR)  { 
304                 cBuffer.append(FILE_SEPARATOR_CHAR); 
305             } 
306  
307             cBuffer.append(generatedKey); 
308             cBuffer.append("_").append("GET").append("_"); 
309  
310             generatedKey = testUrlQuery;//"";//getSortedQueryString(ParameterMap); 
311               
312              if (generatedKey != null)  { 
313                  try  { 
314                     java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); 
315                     byte[] b = digest.digest(generatedKey.getBytes()); 
316                     cBuffer.append('_'); 
317  
318                     // Base64 encoding allows for unwanted slash characters. 
319                     cBuffer.append(toBase64(b).replace('/', '_')); 
320                  } catch (Exception e)  { 
321                     // Ignore query string 
322                 } 
323             } 
324         return cBuffer.toString(); 
325          
326     } 
327    
328 } 
 
 
下面是转抄的网上的一些资源作为补充。 
 
    
        
            | 
             一.OSCache简介  
            OSCache是OpenSymphony这个开源项目众多Projects中的一个。他是一个高效的J2EE缓存框架,能够很好的解决动态网站速度的问题。下面来  
            看下OSCache解决了动态网站的哪些令人郁闷的问题。  
            1.缓存动态内容:其实我们的动态网页上一般只有一部分是动态的(表头,表尾一般是不变的),如果我们缓存整个网页显然不成,因为有部分是  
            随着请求有可能变的。OSCache提供的方式是允许我们只缓存一部分网页。  
             
            2.缓存2进制内容:产生的图片和PDF文件在服务器加载的时候非常的耗时。OSCache解决这个问题是通过一个Servlet2.3的缓存过滤功能,然后能  
            够缓存任意的URI(比如一个完整的页面或者是一个产生的图片/PDF文件)  
             
            3.容错:有这种情况或许我们会遇到,就是当一个动态的网页出现错误。即便我们的页面有95%都加载完毕,但就是由于这个错误,整个页面就会  
            返回错误的提示或页面。OSCache允许我们提供出现错误时的缓存内容,如果出现就适时的提示出来了。  
             
            除了上面的这些Servlet的特征外,OSCache完全可以充当任何一个java程序的缓存方案。OSCache 的一般特征如下:  
            1.缓存任意对象:可以不受限制的缓存JSP的一部分或是Http请求,任何的Java对象都可以被缓存。  
             
            2.全面的API:通过API可以完完全全的控制OSCache的任何特性。  
             
            3.持久缓存:我们可以把认为重要的数据缓存到硬盘上。  
             
            4.支持集群:集群缓存数据能被单个的进行参数配置,不需要修改代码。  
             
            5.缓存记录的过期:你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。  
             
            二.OSCache运行环境  
            如果用到OSCache Tag Library的话,需要Servlet2.3和JSP1.2的支持。如果是直接用OSCache API的话那么就不需要Servlet容器的支持。  
            目前可以正常运行的Web容器:  
            1.OrionServer(版本1.4.0和更高)  
            2.JRun(3.0或更好)  
            3.WebLogic(8.1或以上)  
            4.Websphere(5.0或以上)  
            5.Resin(1.2.3或以上)  
            6.TomCat(4.0或以上)  
            7.iPlanet(6.0或以上)  
            用到缓存过滤需要Servlet2.3支持.目前知道的可以个工作在OrionServer,WebLogic,Tomcat上.  
            OSCache需要Java的版本至少是java 1.4.  
             
            三.OSCache的安装  
            1.解压oscache-2.4.1-full后发现他下面有如下文件:  
             
            2.把oscache-2.4.1.jar放到/WEB-INF/lib下.  
            3.要确保commons-logging.jar也在环境变量中.一般情况下他也放在/WEB-INF/lib下.  
            4. 把/etc/oscache.properties放入/WEB-INF/classes下.如果用的Eclipse的话,建议新建一个 Source Folder比如叫Src_Config,然后就这个OSCache的属性文件放在其中.通过修改这个OSCache的配置文件可以改变文件缓存的磁盘路径,配置持久侦听等等.  
            5.把etc/META-INF/oscache.tld也放在/WEB-INF/classes下.  
            你的目录结构如下:  
             
             
            四.OSCache应用学习  
            1.JSP的应用  
            要是想应用OSCache的标签,我们必须先要引入进来.方式有两种.  
            其一.在web.xml中加入:  
            <taglib>  
            <taglib-uri>oscache</taglib-uri>  
            <taglib-location>/WEB-INF/classes/oscache.tld</taglib-location>  
            </taglib>  
            然后我们在JSp中就可以<%@ taglib uri="oscache" prefix="os"%>这样来引用了.  
            其二,直接引用.直接在JSp中加入OSCache的标签库引用  
            <%@ taglib uri="/WEB- INF/classes/oscache.tld" prefix="os"%>.如果要进入官方的标签库的话也行.& lt;%@ taglib uri="http://www.opensymphony.com/oscache" prefix="cache" %& gt;这样就不用再把oscache.tld放在/WEB-INF/classes下了.  
            目前OSCache有5个标签.他们是cache, usecached, flush, addgroup, addgroups.下面我们来分别介绍一下他们的属性和用法.  
            <cache></cache>  
            他是OSCache中最主要的标签了.括起来的内容将根据属性的设置来缓存起来.第一次执行的时候,OSCache会把cache标签中的JSp执行并且缓存起来,以后再执行的话,他会首先判断缓存的内容是否过期,如果过期那么会从新执行并缓存.否则就直接从缓存中读取.判定过期的条件如下:  
            i.缓存的内容超过了属性time所指定的时间.  
            ii.不符合cron设置的时间间隔.  
            iii.如果scope指定的范围刷新的话,则认为过期了.如Session过期.  
            属性如下:  
            key   : 缓存的Key,可以是任何的字符,用来寻找缓存的内容用的.可以理解成HashMap中的Key.不能把2个要缓存的东东定义成一个名字,那样后一个会覆盖前一个的内容.默认情况,如果不指定Key的话,OSCache也会自动生成一个Key,规则是请求的URI+当前页面的Query String.  
            scope : 缓存的范围.有2个, application和session.默认值是application.  
            time   : 缓存内容的时间.以秒为单位,默认是3600秒.到了指定的时间,就会刷新缓存内容.如果指定一个负数的话,意味着永远不会过期.  
            duration : 也是用来指定缓存内容的时间,它和time属性只能是2选1,它的特点是可以用Simple Data Format 或者是ISO-8601进行日期格式化.  
            cron   : 用万年历的形式指定缓存内容何时过期的.它应用的Unix的万年历形式,如("0 * * * *")  
            refresh : 是个Boolean值,如果是True的话,则不管前面提到的过期检查,都刷新.默认情况是false.  
            mode   : 设置这项为”silent”将防止把括起来的内容输出.这在你预加载缓存内容而不愿显示给用户看到时很有用.  
            groups : 可以提供一个以逗号分割的组名称.如group="A, B".这将允许你以组的名义来操作他们,分组非常有用,比如你要缓存的内容正好需要另外一个应用程序的一部分或数据,当依赖的发生了改变,正好联动的可以使很多的组过期,进而使与组发生关联的缓存内容得到更新.  
            language : 设置编码方式.  
            refreshpolicyclass:指定自定义的类来处理缓存的内容什么时候过期.这个类需要从 refreshpolicyparam com.opensymphony.oscache.web.WebEntryRefreshPolicy继承.  
            refreshpolicyparam : 它和上面的是联合使用的.是给refreshpolicyclass传任意的参数的.指定这项的话,就必须有refreshpolicyclass,否则就不起作用.  
            属性就这么多了,下面举几个应用的例子:  
            <os:cache key="<%=myKey%>" time="1800" refresh="<%=needRefresh%>">  
            <!--这里是要缓存的内容-->  
            </os:cache>  
            这里将myKey标识的缓存内容保持30分钟,到期自动刷新.如果needRefresh为true也会刷新(适合于更新内容的即时刷新).  
             
            <os:cache key="<%=myKey%>" cron="0 2 * * *" refresh="<%=needRefresh%>">  
            <!--这里是要缓存的内容-->  
            </os:cache>  
            将myKey标识的缓存内容在每天的凌晨2时自动刷新.如果needRefresh为true也会刷新(适合于更新内容的即时刷新).  
            举到了这个例子,我不得不把cron表达式多说几句.首先这五颗星的位置代表  
            分,小时,一个月中的天,月,一周中的天  
            分: 无疑问0~59.  
            小时 : 无疑问 0~23.  
            天(月) : 1~31  
            月 : 1~12,用英文全称也可以.如January, April  
            天(周): 0~6(0代表Sunday; 1代表Monday… 6代表Saturday)  
            举个例子,比如我们想让缓存的内容在4月的晚上11:45分过期.我们可以这样来写  
            "45 23 * April *".  
             
             
            <usecached />  
            需要放在cache标签中嵌套使用(一般配合try..catch使用)告诉他的上级标签是否应用缓存的译本. 则出现异常时将会替换包括上级标签在内的所有内容(提示:Missing cached content). use="true|false" : 是否应用的标记. 默认为True.一般省略.  
            应用例子:  
            <os:cache>  
            ..内容..  
                <% try {%>  
                ......其它内容  
                <%}catch (Exception e) {%>  
                Inside catch: <os:usecached use="<%=isUsed%>"/> YES  
                <% } %>  
            </os:cache>  
            则出现异常时的页面输出有两种:  
            1>. isUsed=false  
            ..内容..  
            ......其它内容  
            Inside catch: YES  
            2>. isUsed=true  
            Missing cached content  
             
            <flush />  
            这个标签是用于在运行时状态下刷新缓存的.这个标签非常有用,因为它可以放在Web程序的管理部分使管理员可以决定何时刷新缓存.  
            属性如下:  
            scope : 刷新的范围.3个值, "application", "session" and null .null表示刷新所有.  
            Key : 和scope联合使用,刷新指定范围的指定缓存.如果不指定scope则key无效.  
            group : 和scope联合使用, 刷新指定范围的指定组中的缓存. 不指定scope无效.  
            Pattern :任何包含了pattren指定的字符串的缓存都被更新.它也是和scope连用.但是现在官方不赞成再用这个属性了.用group完全可以取代这个.便于管理.  
            language : 设置编码方式  
            举几个应用的例子:  
            刷新整个application.  
            <os:flush scope="application" />  
             
            刷新session中的foobar这个缓存.  
            <os:flush scope="session" key="foobar" />  
             
            在application 中刷新所有currencyData 组中的缓存  
            <os:flush scope="application" group="currencyData" />  
             
             
            <addgroup />  
            这个标签也是必须嵌套在cache标签中的.把缓存的东东放入到指定的组中.这样就可以以组来刷新指定的内容了.  
            属性只有group来指定名字的.例子如下:  
            把test1加入到group1和group2中  
            <os:cache key="test1">  
                < os:addgroup group="group1" />  
                ... some jsp content ...  
                < os:addgroup group="group2" />  
                ... some more jsp content ...  
            </ os:cache>  
             
             
            <addgroups /> (2.3及以后的版本中新加的)  
            同上面的功能相同,只不过可以不用一个一个加group了.例子如下:  
            < os:cache key="test1">  
                ... some jsp content ...  
                < os:addgroups groups="group1,group2" />  
                ... some jsp content ...  
            </ os:cache>  
             
            2.API的应用  
            在实际应用中除了JSP标签库和CacheFilter(下面介绍)外,还可以使用OSCache提供的Java API .下面我来介绍一个实用的 Java类 ,使用GeneralCacheAdministrator来建立,刷新和管理缓存. GeneralCacheAdministrator 可以被实例化,里面有很多的实用方法.此外它还管理加载cache.properties并且根据这个属性文件创建一个缓存实例.因此你最好使用单例模式来创建GeneralCacheAdministrator实例.  
            主要用到的GeneralCacheAdministrator的方法有  
            public Object getFromCache(String key) throws NeedsRefreshException; -- 从缓存中获取一个key标识的对象.  
            public Object getFromCache(String key, int refreshPeriod) throws NeedsRefreshException ; -- 从缓存中获取一个key标识的对象. refreshPeriod刷新周期,标识此对象在缓存中保存的时间(单位:秒)  
             
            public void putInCache(String key, Object content) -- 存储一个由Key标识的缓存对象.  
             
            public void putInCache(String key, Object content, String[] groups)   -- 存储一个由Key标识的属于groups中所有成员的缓存对象.  
             
            public void flushEntry(String key) -- 更新一个Key标识的缓存对象.  
            public void flushGroup(String group) --更新一组属于groupr标识的所有缓存对象.  
            public void flushAll() -- 更新所有缓存.  
             
            public void cancelUpdate(String key) --- 取消更新 只用于在处理捕获的NeedsRefreshException异常并尝试生成新缓存内容失效的时候.  
            public void removeEntry(String key) ---从缓中移除一个key标识的对象  
            public void clear() --- 清除所有缓存  
            官方的使用例子:  
            ///采取补救措施的典型方案  
            String myKey = "myKey";  
            String myValue;  
            int myRefreshPeriod = 1000; //刷新周期1000秒  
            try {  
            //从Cache中获得 要做类型转换  
            myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);  
            } catch (NeedsRefreshException nre) {  
            try {  
              // Cache中没有则从库获得数据.  
              myValue = "This is the content retrieved.";  
              // 存放在Cache中 键值myKey  
              admin.putInCache(myKey, myValue);  
            } catch (Exception ex) {  
            // 尝试恢复Cache中的内容  
              myValue = (String) nre.getCacheContent();  
              // 如果Cache中的内容没有复原 则用这个终级方法  
              admin.cancelUpdate(myKey); //取消对myKey的更新 即类似数据回滚  
            }  
            }  
            ///不采取补救措施的典型方案  
            String myKey = "myKey";  
            String myValue;  
            int myRefreshPeriod = 1000;  
            try {  
            //从Cache中获得 要做类型转换  
            myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);  
            } catch (NeedsRefreshException nre) {  
            try {  
              // Cache中没有则从库获得数据.  
              myValue = "This is the content retrieved.";  
              // 存放在Cache中 键值myKey  
              admin.putInCache(myKey, myValue);  
              updated = true;  
            } finally {  
              if (!updated) {  
                // 如果Cache中的内容更新出现异常 则用这个终级方法  
              admin.cancelUpdate(myKey); //取消对myKey的更新 即类似数据回滚  
              }  
            }  
            }  
            注意:  
            如果一个NeedsRefreshException出现 必须调用admin.putInCache或甚至admin.cancelUpdate来避免死锁情况发生.  
             
            3.CacheFilter的应用  
            OScache可以是你很轻易的缓存网站中全部页面,甚至是那些2进制文件.从2.4版本开始你可以在运行期设置和覆盖CacheFilter的初始化参数.注意,只有返回状态为200的页面才会缓存. (HttpServletResponse.SC_OK).  
            配置CacheFilter,在Web.xml中加入如下:  
            <filter>  
            <filter-name>CacheFilter</filter-name>  
            <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>  
            <init-param>  
              <param-name>time</param-name>  
              <param-value>600</param-value>  
            </init-param>  
            <init-param>  
              <param-name>scope</param-name>  
              <param-value>session</param-value>  
            </init-param>  
            </filter>  
             
            <filter-mapping>  
            <filter-name>CacheFilter</filter-name>  
            <url-pattern>*.jsp</url-pattern>  
            </filter-mapping>  
            这个例子将在session范围缓存所有JSp10分钟.默认情况scope为application,时间为1小时.  
            如果ICacheKeyProvider不设置的话,这个CacheFilter将使用(URI+QueryString)作为缓存Key.  
            你可以使用下列的初始化参数来设置CacheFilter:  
             
            Parameter: time  
            设置缓存时间,默认是1个小时.可以设置为-1(不确定).这样他就不会过期了.除非你明确刷新它(前面说到的refresh =”true”).或者是更改这个刷新的策略.  
             
            Parameter: scope  
            同cache的scope. 也是有application(default)和session  
             
            Parameter: cron (NEW! Since 2.3)  
            同cache的scope.设置过期  
             
            Parameter: fragment (NEW! Since 2.2)  
            作用不太清除,用默认即可.  
             
            Parameter: nocache (NEW! Since 2.2)  
            定义那些页面不需要缓存.”off”---缓存所有;”sessionIdInURL”---如果session中包括这URL的则不缓存这个页面  
             
            Parameter: lastModified (NEW! Since 2.2)  
            定义是否把Header发送到Response中.  
            ”off”----不发送,即便它设置在过滤链中.  
            “on”----如果在过滤链中则发送.  
            “inital”(default)----最后更改的信息将基于当前时间被设置  
             
            Parameter: max-age (NEW! Since 2.3.1)  
            设置在浏览器中缓存的最大时间.在设置的期间,不再向服务器请求,而是从自己的缓存中查找页面.默认是60秒.  
             
            Parameter: expires (NEW! Since 2.2)  
            定义过期header发送到Response中的时间.  
            “off”----不发送.  
            “on”(default)---如果在过滤链中则发送.并且time这个过期信息将基于时间参数和页面内容的创建时间初始化.  
             
            Parameter: ICacheKeyProvider (NEW! Since 2.2)  
            指定实现ICacheKeyProvider接口的类.  
             
             
            Parameter: ICacheGroupsProvider (NEW! Since 2.2)  
            指定实现ICacheGroupsProvider接口的类  
             
            Parameter: EntryRefreshPolicy (New! Since 2.3)  
            指定实现EntryRefreshPolicy接口的类.  
             
             
            Parameter: disableCacheOnMethods (New! Since 2.4)  
            指定请求方式不进行缓存.默认Null,对所有的请求方式都缓存.例如:  
            <init-param>  
              <param-name>disableCacheOnMethods</param-name>  
              <param-value>POST,PUT,DELETE</param-value>  
            </init-param>  
             
            Parameter: oscache-properties-file (New! Since 2.4)  
            通过指定OSCache的属性文件,开发者就能运行多个CacheFilter  
             
             
             
            4.OSCache的属性文件.(oscache.properties)  
            cache.memory  
            值为true或false.默认为true.如果设置为false那么缓存到数据库或硬盘中.似乎有点傻,所以我们一般不改此项.  
             
            cache.capacity  
            缓存元素的个数.默认是没有限制的.  
             
            cache.algorithm  
            缓存的算法.注意要是指定算法的话,必须把上面的缓存个数指定.这里支持三种算法.  
            com.opensymphony.oscache.base.algorithm.LRUCache – 最后最近使用  
            com.opensymphony.oscache.base.algorithm.FIFOCache – 先进先出  
            com.opensymphony.oscache.base.algorithm.UnlimitedCache – 无限缓存  
             
            cache.blocking  
            是否同步化。true 或者 false。一般设为true,避免读取脏数据。  
             
            cache.unlimited.disk  
            指定硬盘缓存是否要作限制。默认值为false。false的状况下,disk cache capacity 将和cache.capacity的值相同。  
             
            cache.persistence.class  
            指定类是被持久化的类。class必须实现PersistenceListener接口。 作为硬盘持久,可以实现 com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener 接口。 它把class的toString()输出的hash值作为文件的名称。如果你要把文件名易读(自己设定),DiskPersistenceListener 的父类也 能使用,但其可能有非法字符或者过长的名字。 注意:HashDiskPersistenceListener 和 DiskPersistenceListener 需要设定硬盘路径:cache.path  
             
            cache.path  
            指定硬盘缓存的路径。目录如果不存在将被建立。同时注意oscache应该要有权限写文件系统。 cache.path=c:\\myapp\\cache or *ix: cache.path=/opt/myapp/cache  
             
             
            cache.persistence.overflow.only (NEW! Since 2.1)  
            指定是否只有在内存不足的情况下才使用硬盘缓存。 默认值false。但推荐是true如果内存cache被允许的话。这个属性彻底的改变了cache的行为,使得persisted cache 和memory完全不同。  
             
            cache.event.listeners  
            用逗号分离的class名列表。每个class必须实现以下接口之一,或者几个 CacheEntryEventListener:接收 cache add/update/flush and remove事件 CacheMapAccessEventListener :接收cache 访问事件。这个可以让你跟踪cache怎么工作。 默认是不配置任何class的。当然你可以使用一下的 class: com.opensymphony.oscache.plugins.clustersupport.BroadcastingCacheEventListener -分布式的(此处被屏蔽)。可以广播到局域网内的其他cache实例。 com.opensymphony.oscache.extra.CacheEntryEventListenerImpl -一个简单的(此处被屏蔽)。在cache的生命周期中记录count of 所有entry的事件。 com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl -记录 count of cache map events(cache hits,misses and state hits).  
             
            cache.key  
            设置ServletCacheAdministrator使用的Key.在代码中如果需要用到的话,可以通过com.opensymphony.oscache.web.ServletCacheAdministrator.DEFAULT_CACHE_KEY得到.  
             
            cache.use.host.domain.in.key  
            如果你的服务器是被配置到多台主机上的话,你或许想加上一个主机的名字在它生成的缓存Key上.true的话会加上.默认值是false.  
             
            附加的属性: cache.cluster.multicast.ip, cache.cluster.properties  
             
             
             
            5.小结:  
            OSCache的使用主要有4种:  
            POJO 缓存  
            HTTP Response 缓存  
            JSP Tag Library 缓存  
            O/R Data Access 缓存  
             
            1)、POJO 缓存  
            这种方式的缓存直接调用OSCache的API进行,主要用于处理页面内容会根据参数动态改变,可以将参数设置为key值来保存数据:  
            首先,声明成员变量:  
            // OSCache Adminitrator instance  
            private static GeneralCacheAdministrator cacheAdmin = null;  
            其次,进行初始化:  
            public RingArtistAction() {  
            cacheAdmin = new GeneralCacheAdministrator();  
            }  
            将POJO进行缓存:  
            // Cache data key and refresh period  
            String key = sex + ":" + place;  
            int refreshPeriod = Constants.getIntegerValue(Constants.OSCACHE_REFRESH_PERIOD).intValue();  
            try {  
              // Get from the cache  
            artists = (Map) cacheAdmin.getFromCache(key, refreshPeriod);  
            } catch (NeedsRefreshException nre) {  
              try {  
                // Get the value (probably from the database)  
            int count = getArtistCount(sex, place, errors);  
            artists = getArtistData(sex, place, count, errors);  
                // Store in the cache  
            cacheAdmin.putInCache(key, artists);  
              } catch (Exception ex) {  
                // We have the current content if we want fail-over.  
            artists = (Map) nre.getCacheContent();  
                // It is essential that cancelUpdate is called if the  
                // cached content is not rebuilt  
            cacheAdmin.cancelUpdate(key);  
            ex.printStackTrace();  
              }  
            }  
             
            2)、HTTP Response 缓存  
            这种方式的缓存用来处理整个页面的内容固定,不会根据参数动态改变:  
            首先在web.xml中配置CacheFilter:  
            <filter>  
            <filter-name>CacheFilter</filter-name>  
            <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>  
            <init-param>  
            <param-name>time</param-name>  
            <param-value>86400</param-value>  
            </init-param>  
            <init-param>  
            <param-name>scope</param-name>  
            <param-value>application</param-value>  
            </init-param>  
            </filter>  
            将所有需要缓存的页面加入filter-mapping:  
            <filter-mapping>  
            <filter-name>Set Character Encoding</filter-name>  
            <url-pattern>/*</url-pattern>  
            </filter-mapping>  
            注意,只有返回状态为200(HttpServletResponse.SC_OK)的内容才会被缓存  
             
            3)、JSP Tag 缓存  
            JSP Tag缓存主要用于缓存JSP页面的局部内容:  
            <cache:cache key="especialcategory" cron="* 5 * * *">  
            <jsp:include page="/ringcategory.do" flush="true" >  
            <jsp:param name="ringType" value="1"/>  
            </jsp:include>  
            </cache:cache>  
             
            4)、O/R Data Access 缓存  
            请阅读参考资料的内容获取详情。 
            如果想随时清除web.xml配置的缓存请使用ServletCacheAdministrator.getInstance(request.getSession().getServletContext()).flushAll(); 
             
             | 
         
    
 
	
 
	 
	
	    
    
评论:
 
	
			
		
			- 
				
					# Cookie混乱及解决办法。  
				Posted @ 2008-12-09 16:34
				  
				Cookie的path不同属于不同的cookie.所以如果path简单的用'/'来表示,将会在客户端写下/,和实际所在path两个cookie,将来如果要清除cookie的话默认的只能清除/下的cookie,这样会造成cookie的混乱。引起程序的状态不稳定。
 解决办法是用String path=request.getContextPath来写入Cookie的path.这样会在客户端唯一的写入一个cookie。然后清除的时候也要写入这个path,用cookie的时间=0来清除。  回复  更多评论
				   
				
				 
			 
		
			- 
				
					# re: OSCache的实际使用  
				Posted @ 2009-06-24 23:25
				  
				package com.test;
 import java.awt.BorderLayout;
 import java.awt.FlowLayout;
 
 import java.awt.Frame;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
 
 import javax.swing.JButton;
 import javax.swing.JLabel;
 
 
 
 /**
 * This code was edited or generated using CloudGarden's Jigloo
 * SWT/Swing GUI Builder, which is free for non-commercial
 * use. If Jigloo is being used commercially (ie, by a corporation,
 * company or business for any purpose whatever) then you
 * should purchase a license for each developer using Jigloo.
 * Please visit www.cloudgarden.com for details.
 * Use of Jigloo implies acceptance of these licensing terms.
 * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
 * THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
 * LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
 */
 public class Workers extends Frame implements ActionListener, WindowListener {
 	
 	
 	public static void main(String [] args){
 		new Workers();
 	}
 	
 	private JLabel lab1,lab2,lab3,lab4,lab5,lab6,lab7;
     private JButton b1,b2,b3,b4,b5;
 	
 
 	public Workers(){
 		super("灌水机参数设置界面");
 		this.setSize(800, 600);
 		this.setLocation(100, 100);
 		GridLayout thisLayout = new GridLayout(7, 2);
 		this.setLayout(thisLayout);
 		lab1 = new JLabel("灌水机参数设置:");
 		lab2 = new JLabel("\u704c\u6c34\u673a\u65f6\u95f4\u95f4\u9694");
 		lab3 = new JLabel("文章标题");
 		lab4 = new JLabel("发表文章路径");
 		lab5 = new JLabel("发表文章类型");
 		lab6 = new JLabel("");
 		b1 = new JButton("发表");
 		b1.setSize(10, 5);
 		b2 = new JButton("查看发表统计");
 		b2.setSize(10, 5);
 		this.add(lab1);
 		this.add(lab2);
 		this.add(lab3);
 		this.add(lab4);
 		this.add(lab5);
 		this.add(lab6);
 		this.add(b1);
 		b1.setPreferredSize(new java.awt.Dimension(232, 60));
 		this.add(b2);
 		b2.setPreferredSize(new java.awt.Dimension(10, 5));
 		this.addWindowListener(this);
 		this.setVisible(true);
 		
 	}
 	
 	
 	
 	
 	
 	
 	public void actionPerformed(ActionEvent arg0) {
 		// TODO Auto-generated method stub
 
 	}
 
 	public void windowActivated(WindowEvent arg0) {
 		// TODO Auto-generated method stub
 
 	}
 
 	public void windowClosed(WindowEvent arg0) {
 		System.exit(0);
 
 	}
 
 	public void windowClosing(WindowEvent arg0) {
 		System.exit(0);
 
 	}
 
 	public void windowDeactivated(WindowEvent arg0) {
 		// TODO Auto-generated method stub
 
 	}
 
 	public void windowDeiconified(WindowEvent arg0) {
 		// TODO Auto-generated method stub
 
 	}
 
 	public void windowIconified(WindowEvent arg0) {
 		// TODO Auto-generated method stub
 
 	}
 
 	public void windowOpened(WindowEvent arg0) {
 		// TODO Auto-generated method stub
 
 	}
 	
 	
 
 }
   回复  更多评论
				   
				
				 
			 
		
			- 
				
					# re: OSCache的实际使用[未登录]  
				Posted @ 2009-08-06 09:59
				  
				网站静态化方面的好文章
 http://www.cnblogs.com/yizhu2000/archive/2008/09/01/1281532.html  回复  更多评论
				   
				
				 
			 
		
			- 
				
					# re: OSCache的实际使用   
				Posted @ 2009-08-31 13:42
				  
				import java.util.regex.Matcher; import java.util.regex.Pattern;
  public class IPReg { 	 	public boolean isTure(){ 		String ipReg="([1-9]{1}[0-9]?[0-9]?[.]{1}){3}[1-9]{1}[0-9]?[0-9]?"; 		String inputStr="12.40.43.8"; 		Pattern patt=Pattern.compile(ipReg); 		Matcher m = patt.matcher(inputStr); 		while(m.find()){ 			System.out.print(m.group()); 		} 		return m.find(); 	} 	public static void main(String [] args){ 		IPReg ipreg = new IPReg(); 		System.out.println(" is ture?:"+ipreg.isTure()); 	} }   回复  更多评论
				   
				
				 
			 
		
			 
		
 
 
				
				  	
		 |