公告
日歷
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
27 | 28 | 29 | 30 | 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 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
導(dǎo)航
隨筆分類(86)
隨筆檔案(85)
搜索
最新評(píng)論

閱讀排行榜
評(píng)論排行榜
|
OSCache使用
我們網(wǎng)站在優(yōu)化之前速度是很慢的,后來(lái)采用了OScache,網(wǎng)站性能才得以大幅度提升。下面把心得體會(huì)寫下來(lái)備忘。
因?yàn)楝F(xiàn)在的項(xiàng)目以.jsp結(jié)尾的已經(jīng)不多了。所以直接在jsp頁(yè)面里加cache的形式已經(jīng)不常。最常用的還是在web.xml里使用oscache的過(guò)濾器(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幾種選項(xiàng)。request范圍太短,用了性能不會(huì)提高多少,幾乎沒用。
可以把cache想像成一個(gè)池子。
session是針對(duì)一個(gè)用戶有一個(gè)cache,在請(qǐng)求的url相同的情況下,cache住的頁(yè)面內(nèi)容和其他用戶是不一樣的。一個(gè)用戶使用一個(gè)池子。比request級(jí)緩存更省資源。
application是針對(duì)所有用戶的一個(gè)cache,打開一個(gè)url后,所有的用戶看見的內(nèi)容都一樣。大家都共用這個(gè)池子。比session級(jí)更節(jié)省資源。速度也相當(dāng)于靜態(tài)化的html頁(yè)。
2.深層問(wèn)題:cache是根據(jù)什么來(lái)緩存內(nèi)容的呢?
<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>
過(guò)濾器當(dāng)然會(huì)過(guò)濾所有的url,但在這個(gè)例子中,oscache只cache住包含ystore!allStores.do和ystore!storedetail.do字串的url內(nèi)容。具體過(guò)程是這樣:
(1.它過(guò)濾到符合條件的url后,把/ystore!storedetail.do***之后的字串進(jìn)行BASE32位編碼,得到一個(gè)key。
(2.拿著這個(gè)key去內(nèi)容中進(jìn)行hashMap查找,如果找到了,就把value返回給客戶端,否則,把這個(gè)key與服務(wù)器返回的內(nèi)容作為一個(gè)HashMap(kay-->value)存進(jìn)內(nèi)存。
(3.當(dāng)再次過(guò)濾到符合條件的url后,把/ystore!storedetail.do***之后的字串進(jìn)行BASE32位編碼,得到一個(gè)key,然后重復(fù)第2步。
看個(gè)實(shí)際例子:
/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傳遞查詢條件的情況。它只認(rèn)url,相信這一點(diǎn)并記住這一點(diǎn)。
3.緩存的手工清除。
當(dāng)用戶登陸自己的頁(yè)面或者發(fā)表了一個(gè)評(píng)論,我們就應(yīng)該手工清除(刷新)cache中的緩存,而不應(yīng)該靠設(shè)定的時(shí)間來(lái)清除了。 這時(shí)要使用ServletCacheAdministrator類。ServletCacheAdministrator.getInstance(request.getSession().getServletContext()).flushAll();目前它只有一個(gè).flushAll()可用。普通cache管理類GeneralCacheAdministrator類對(duì)過(guò)濾的cache是不管用的。
4.下面是了key級(jí)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 * 根據(jù)查詢生成唯一的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 }
下面是轉(zhuǎn)抄的網(wǎng)上的一些資源作為補(bǔ)充。
一.OSCache簡(jiǎn)介
OSCache是OpenSymphony這個(gè)開源項(xiàng)目眾多Projects中的一個(gè)。他是一個(gè)高效的J2EE緩存框架,能夠很好的解決動(dòng)態(tài)網(wǎng)站速度的問(wèn)題。下面來(lái)
看下OSCache解決了動(dòng)態(tài)網(wǎng)站的哪些令人郁悶的問(wèn)題。
1.緩存動(dòng)態(tài)內(nèi)容:其實(shí)我們的動(dòng)態(tài)網(wǎng)頁(yè)上一般只有一部分是動(dòng)態(tài)的(表頭,表尾一般是不變的),如果我們緩存整個(gè)網(wǎng)頁(yè)顯然不成,因?yàn)橛胁糠质?
隨著請(qǐng)求有可能變的。OSCache提供的方式是允許我們只緩存一部分網(wǎng)頁(yè)。
2.緩存2進(jìn)制內(nèi)容:產(chǎn)生的圖片和PDF文件在服務(wù)器加載的時(shí)候非常的耗時(shí)。OSCache解決這個(gè)問(wèn)題是通過(guò)一個(gè)Servlet2.3的緩存過(guò)濾功能,然后能
夠緩存任意的URI(比如一個(gè)完整的頁(yè)面或者是一個(gè)產(chǎn)生的圖片/PDF文件)
3.容錯(cuò):有這種情況或許我們會(huì)遇到,就是當(dāng)一個(gè)動(dòng)態(tài)的網(wǎng)頁(yè)出現(xiàn)錯(cuò)誤。即便我們的頁(yè)面有95%都加載完畢,但就是由于這個(gè)錯(cuò)誤,整個(gè)頁(yè)面就會(huì)
返回錯(cuò)誤的提示或頁(yè)面。OSCache允許我們提供出現(xiàn)錯(cuò)誤時(shí)的緩存內(nèi)容,如果出現(xiàn)就適時(shí)的提示出來(lái)了。
除了上面的這些Servlet的特征外,OSCache完全可以充當(dāng)任何一個(gè)java程序的緩存方案。OSCache 的一般特征如下:
1.緩存任意對(duì)象:可以不受限制的緩存JSP的一部分或是Http請(qǐng)求,任何的Java對(duì)象都可以被緩存。
2.全面的API:通過(guò)API可以完完全全的控制OSCache的任何特性。
3.持久緩存:我們可以把認(rèn)為重要的數(shù)據(jù)緩存到硬盤上。
4.支持集群:集群緩存數(shù)據(jù)能被單個(gè)的進(jìn)行參數(shù)配置,不需要修改代碼。
5.緩存記錄的過(guò)期:你可以有最大限度的控制緩存對(duì)象的過(guò)期,包括可插入式的刷新策略(如果默認(rèn)性能不需要時(shí))。
二.OSCache運(yùn)行環(huán)境
如果用到OSCache Tag Library的話,需要Servlet2.3和JSP1.2的支持。如果是直接用OSCache API的話那么就不需要Servlet容器的支持。
目前可以正常運(yùn)行的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或以上)
用到緩存過(guò)濾需要Servlet2.3支持.目前知道的可以個(gè)工作在OrionServer,WebLogic,Tomcat上.
OSCache需要Java的版本至少是java 1.4.
三.OSCache的安裝
1.解壓oscache-2.4.1-full后發(fā)現(xiàn)他下面有如下文件:
2.把oscache-2.4.1.jar放到/WEB-INF/lib下.
3.要確保commons-logging.jar也在環(huán)境變量中.一般情況下他也放在/WEB-INF/lib下.
4. 把/etc/oscache.properties放入/WEB-INF/classes下.如果用的Eclipse的話,建議新建一個(gè) Source Folder比如叫Src_Config,然后就這個(gè)OSCache的屬性文件放在其中.通過(guò)修改這個(gè)OSCache的配置文件可以改變文件緩存的磁盤路徑,配置持久偵聽等等.
5.把etc/META-INF/oscache.tld也放在/WEB-INF/classes下.
你的目錄結(jié)構(gòu)如下:
四.OSCache應(yīng)用學(xué)習(xí)
1.JSP的應(yīng)用
要是想應(yīng)用OSCache的標(biāo)簽,我們必須先要引入進(jìn)來(lái).方式有兩種.
其一.在web.xml中加入:
<taglib>
<taglib-uri>oscache</taglib-uri>
<taglib-location>/WEB-INF/classes/oscache.tld</taglib-location>
</taglib>
然后我們?cè)贘Sp中就可以<%@ taglib uri="oscache" prefix="os"%>這樣來(lái)引用了.
其二,直接引用.直接在JSp中加入OSCache的標(biāo)簽庫(kù)引用
<%@ taglib uri="/WEB- INF/classes/oscache.tld" prefix="os"%>.如果要進(jìn)入官方的標(biāo)簽庫(kù)的話也行.& lt;%@ taglib uri="http://www.opensymphony.com/oscache" prefix="cache" %& gt;這樣就不用再把oscache.tld放在/WEB-INF/classes下了.
目前OSCache有5個(gè)標(biāo)簽.他們是cache, usecached, flush, addgroup, addgroups.下面我們來(lái)分別介紹一下他們的屬性和用法.
<cache></cache>
他是OSCache中最主要的標(biāo)簽了.括起來(lái)的內(nèi)容將根據(jù)屬性的設(shè)置來(lái)緩存起來(lái).第一次執(zhí)行的時(shí)候,OSCache會(huì)把cache標(biāo)簽中的JSp執(zhí)行并且緩存起來(lái),以后再執(zhí)行的話,他會(huì)首先判斷緩存的內(nèi)容是否過(guò)期,如果過(guò)期那么會(huì)從新執(zhí)行并緩存.否則就直接從緩存中讀取.判定過(guò)期的條件如下:
i.緩存的內(nèi)容超過(guò)了屬性time所指定的時(shí)間.
ii.不符合cron設(shè)置的時(shí)間間隔.
iii.如果scope指定的范圍刷新的話,則認(rèn)為過(guò)期了.如Session過(guò)期.
屬性如下:
key : 緩存的Key,可以是任何的字符,用來(lái)尋找緩存的內(nèi)容用的.可以理解成HashMap中的Key.不能把2個(gè)要緩存的東東定義成一個(gè)名字,那樣后一個(gè)會(huì)覆蓋前一個(gè)的內(nèi)容.默認(rèn)情況,如果不指定Key的話,OSCache也會(huì)自動(dòng)生成一個(gè)Key,規(guī)則是請(qǐng)求的URI+當(dāng)前頁(yè)面的Query String.
scope : 緩存的范圍.有2個(gè), application和session.默認(rèn)值是application.
time : 緩存內(nèi)容的時(shí)間.以秒為單位,默認(rèn)是3600秒.到了指定的時(shí)間,就會(huì)刷新緩存內(nèi)容.如果指定一個(gè)負(fù)數(shù)的話,意味著永遠(yuǎn)不會(huì)過(guò)期.
duration : 也是用來(lái)指定緩存內(nèi)容的時(shí)間,它和time屬性只能是2選1,它的特點(diǎn)是可以用Simple Data Format 或者是ISO-8601進(jìn)行日期格式化.
cron : 用萬(wàn)年歷的形式指定緩存內(nèi)容何時(shí)過(guò)期的.它應(yīng)用的Unix的萬(wàn)年歷形式,如("0 * * * *")
refresh : 是個(gè)Boolean值,如果是True的話,則不管前面提到的過(guò)期檢查,都刷新.默認(rèn)情況是false.
mode : 設(shè)置這項(xiàng)為”silent”將防止把括起來(lái)的內(nèi)容輸出.這在你預(yù)加載緩存內(nèi)容而不愿顯示給用戶看到時(shí)很有用.
groups : 可以提供一個(gè)以逗號(hào)分割的組名稱.如group="A, B".這將允許你以組的名義來(lái)操作他們,分組非常有用,比如你要緩存的內(nèi)容正好需要另外一個(gè)應(yīng)用程序的一部分或數(shù)據(jù),當(dāng)依賴的發(fā)生了改變,正好聯(lián)動(dòng)的可以使很多的組過(guò)期,進(jìn)而使與組發(fā)生關(guān)聯(lián)的緩存內(nèi)容得到更新.
language : 設(shè)置編碼方式.
refreshpolicyclass:指定自定義的類來(lái)處理緩存的內(nèi)容什么時(shí)候過(guò)期.這個(gè)類需要從 refreshpolicyparam com.opensymphony.oscache.web.WebEntryRefreshPolicy繼承.
refreshpolicyparam : 它和上面的是聯(lián)合使用的.是給refreshpolicyclass傳任意的參數(shù)的.指定這項(xiàng)的話,就必須有refreshpolicyclass,否則就不起作用.
屬性就這么多了,下面舉幾個(gè)應(yīng)用的例子:
<os:cache key="<%=myKey%>" time="1800" refresh="<%=needRefresh%>">
<!--這里是要緩存的內(nèi)容-->
</os:cache>
這里將myKey標(biāo)識(shí)的緩存內(nèi)容保持30分鐘,到期自動(dòng)刷新.如果needRefresh為true也會(huì)刷新(適合于更新內(nèi)容的即時(shí)刷新).
<os:cache key="<%=myKey%>" cron="0 2 * * *" refresh="<%=needRefresh%>">
<!--這里是要緩存的內(nèi)容-->
</os:cache>
將myKey標(biāo)識(shí)的緩存內(nèi)容在每天的凌晨2時(shí)自動(dòng)刷新.如果needRefresh為true也會(huì)刷新(適合于更新內(nèi)容的即時(shí)刷新).
舉到了這個(gè)例子,我不得不把cron表達(dá)式多說(shuō)幾句.首先這五顆星的位置代表
分,小時(shí),一個(gè)月中的天,月,一周中的天
分: 無(wú)疑問(wèn)0~59.
小時(shí) : 無(wú)疑問(wèn) 0~23.
天(月) : 1~31
月 : 1~12,用英文全稱也可以.如January, April
天(周): 0~6(0代表Sunday; 1代表Monday… 6代表Saturday)
舉個(gè)例子,比如我們想讓緩存的內(nèi)容在4月的晚上11:45分過(guò)期.我們可以這樣來(lái)寫
"45 23 * April *".
<usecached />
需要放在cache標(biāo)簽中嵌套使用(一般配合try..catch使用)告訴他的上級(jí)標(biāo)簽是否應(yīng)用緩存的譯本. 則出現(xiàn)異常時(shí)將會(huì)替換包括上級(jí)標(biāo)簽在內(nèi)的所有內(nèi)容(提示:Missing cached content). use="true|false" : 是否應(yīng)用的標(biāo)記. 默認(rèn)為True.一般省略.
應(yīng)用例子:
<os:cache>
..內(nèi)容..
<% try {%>
......其它內(nèi)容
<%}catch (Exception e) {%>
Inside catch: <os:usecached use="<%=isUsed%>"/> YES
<% } %>
</os:cache>
則出現(xiàn)異常時(shí)的頁(yè)面輸出有兩種:
1>. isUsed=false
..內(nèi)容..
......其它內(nèi)容
Inside catch: YES
2>. isUsed=true
Missing cached content
<flush />
這個(gè)標(biāo)簽是用于在運(yùn)行時(shí)狀態(tài)下刷新緩存的.這個(gè)標(biāo)簽非常有用,因?yàn)樗梢苑旁赪eb程序的管理部分使管理員可以決定何時(shí)刷新緩存.
屬性如下:
scope : 刷新的范圍.3個(gè)值, "application", "session" and null .null表示刷新所有.
Key : 和scope聯(lián)合使用,刷新指定范圍的指定緩存.如果不指定scope則key無(wú)效.
group : 和scope聯(lián)合使用, 刷新指定范圍的指定組中的緩存. 不指定scope無(wú)效.
Pattern :任何包含了pattren指定的字符串的緩存都被更新.它也是和scope連用.但是現(xiàn)在官方不贊成再用這個(gè)屬性了.用group完全可以取代這個(gè).便于管理.
language : 設(shè)置編碼方式
舉幾個(gè)應(yīng)用的例子:
刷新整個(gè)application.
<os:flush scope="application" />
刷新session中的foobar這個(gè)緩存.
<os:flush scope="session" key="foobar" />
在application 中刷新所有currencyData 組中的緩存
<os:flush scope="application" group="currencyData" />
<addgroup />
這個(gè)標(biāo)簽也是必須嵌套在cache標(biāo)簽中的.把緩存的東東放入到指定的組中.這樣就可以以組來(lái)刷新指定的內(nèi)容了.
屬性只有g(shù)roup來(lái)指定名字的.例子如下:
把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及以后的版本中新加的)
同上面的功能相同,只不過(guò)可以不用一個(gè)一個(gè)加group了.例子如下:
< os:cache key="test1">
... some jsp content ...
< os:addgroups groups="group1,group2" />
... some jsp content ...
</ os:cache>
2.API的應(yīng)用
在實(shí)際應(yīng)用中除了JSP標(biāo)簽庫(kù)和CacheFilter(下面介紹)外,還可以使用OSCache提供的Java API .下面我來(lái)介紹一個(gè)實(shí)用的 Java類 ,使用GeneralCacheAdministrator來(lái)建立,刷新和管理緩存. GeneralCacheAdministrator 可以被實(shí)例化,里面有很多的實(shí)用方法.此外它還管理加載cache.properties并且根據(jù)這個(gè)屬性文件創(chuàng)建一個(gè)緩存實(shí)例.因此你最好使用單例模式來(lái)創(chuàng)建GeneralCacheAdministrator實(shí)例.
主要用到的GeneralCacheAdministrator的方法有
public Object getFromCache(String key) throws NeedsRefreshException; -- 從緩存中獲取一個(gè)key標(biāo)識(shí)的對(duì)象.
public Object getFromCache(String key, int refreshPeriod) throws NeedsRefreshException ; -- 從緩存中獲取一個(gè)key標(biāo)識(shí)的對(duì)象. refreshPeriod刷新周期,標(biāo)識(shí)此對(duì)象在緩存中保存的時(shí)間(單位:秒)
public void putInCache(String key, Object content) -- 存儲(chǔ)一個(gè)由Key標(biāo)識(shí)的緩存對(duì)象.
public void putInCache(String key, Object content, String[] groups) -- 存儲(chǔ)一個(gè)由Key標(biāo)識(shí)的屬于groups中所有成員的緩存對(duì)象.
public void flushEntry(String key) -- 更新一個(gè)Key標(biāo)識(shí)的緩存對(duì)象.
public void flushGroup(String group) --更新一組屬于groupr標(biāo)識(shí)的所有緩存對(duì)象.
public void flushAll() -- 更新所有緩存.
public void cancelUpdate(String key) --- 取消更新 只用于在處理捕獲的NeedsRefreshException異常并嘗試生成新緩存內(nèi)容失效的時(shí)候.
public void removeEntry(String key) ---從緩中移除一個(gè)key標(biāo)識(shí)的對(duì)象
public void clear() --- 清除所有緩存
官方的使用例子:
///采取補(bǔ)救措施的典型方案
String myKey = "myKey";
String myValue;
int myRefreshPeriod = 1000; //刷新周期1000秒
try {
//從Cache中獲得 要做類型轉(zhuǎn)換
myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);
} catch (NeedsRefreshException nre) {
try {
// Cache中沒有則從庫(kù)獲得數(shù)據(jù).
myValue = "This is the content retrieved.";
// 存放在Cache中 鍵值myKey
admin.putInCache(myKey, myValue);
} catch (Exception ex) {
// 嘗試恢復(fù)Cache中的內(nèi)容
myValue = (String) nre.getCacheContent();
// 如果Cache中的內(nèi)容沒有復(fù)原 則用這個(gè)終級(jí)方法
admin.cancelUpdate(myKey); //取消對(duì)myKey的更新 即類似數(shù)據(jù)回滾
}
}
///不采取補(bǔ)救措施的典型方案
String myKey = "myKey";
String myValue;
int myRefreshPeriod = 1000;
try {
//從Cache中獲得 要做類型轉(zhuǎn)換
myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);
} catch (NeedsRefreshException nre) {
try {
// Cache中沒有則從庫(kù)獲得數(shù)據(jù).
myValue = "This is the content retrieved.";
// 存放在Cache中 鍵值myKey
admin.putInCache(myKey, myValue);
updated = true;
} finally {
if (!updated) {
// 如果Cache中的內(nèi)容更新出現(xiàn)異常 則用這個(gè)終級(jí)方法
admin.cancelUpdate(myKey); //取消對(duì)myKey的更新 即類似數(shù)據(jù)回滾
}
}
}
注意:
如果一個(gè)NeedsRefreshException出現(xiàn) 必須調(diào)用admin.putInCache或甚至admin.cancelUpdate來(lái)避免死鎖情況發(fā)生.
3.CacheFilter的應(yīng)用
OScache可以是你很輕易的緩存網(wǎng)站中全部頁(yè)面,甚至是那些2進(jìn)制文件.從2.4版本開始你可以在運(yùn)行期設(shè)置和覆蓋CacheFilter的初始化參數(shù).注意,只有返回狀態(tài)為200的頁(yè)面才會(huì)緩存. (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>
這個(gè)例子將在session范圍緩存所有JSp10分鐘.默認(rèn)情況scope為application,時(shí)間為1小時(shí).
如果ICacheKeyProvider不設(shè)置的話,這個(gè)CacheFilter將使用(URI+QueryString)作為緩存Key.
你可以使用下列的初始化參數(shù)來(lái)設(shè)置CacheFilter:
Parameter: time
設(shè)置緩存時(shí)間,默認(rèn)是1個(gè)小時(shí).可以設(shè)置為-1(不確定).這樣他就不會(huì)過(guò)期了.除非你明確刷新它(前面說(shuō)到的refresh =”true”).或者是更改這個(gè)刷新的策略.
Parameter: scope
同cache的scope. 也是有application(default)和session
Parameter: cron (NEW! Since 2.3)
同cache的scope.設(shè)置過(guò)期
Parameter: fragment (NEW! Since 2.2)
作用不太清除,用默認(rèn)即可.
Parameter: nocache (NEW! Since 2.2)
定義那些頁(yè)面不需要緩存.”off”---緩存所有;”sessionIdInURL”---如果session中包括這URL的則不緩存這個(gè)頁(yè)面
Parameter: lastModified (NEW! Since 2.2)
定義是否把Header發(fā)送到Response中.
”off”----不發(fā)送,即便它設(shè)置在過(guò)濾鏈中.
“on”----如果在過(guò)濾鏈中則發(fā)送.
“inital”(default)----最后更改的信息將基于當(dāng)前時(shí)間被設(shè)置
Parameter: max-age (NEW! Since 2.3.1)
設(shè)置在瀏覽器中緩存的最大時(shí)間.在設(shè)置的期間,不再向服務(wù)器請(qǐng)求,而是從自己的緩存中查找頁(yè)面.默認(rèn)是60秒.
Parameter: expires (NEW! Since 2.2)
定義過(guò)期header發(fā)送到Response中的時(shí)間.
“off”----不發(fā)送.
“on”(default)---如果在過(guò)濾鏈中則發(fā)送.并且time這個(gè)過(guò)期信息將基于時(shí)間參數(shù)和頁(yè)面內(nèi)容的創(chuàng)建時(shí)間初始化.
Parameter: ICacheKeyProvider (NEW! Since 2.2)
指定實(shí)現(xiàn)ICacheKeyProvider接口的類.
Parameter: ICacheGroupsProvider (NEW! Since 2.2)
指定實(shí)現(xiàn)ICacheGroupsProvider接口的類
Parameter: EntryRefreshPolicy (New! Since 2.3)
指定實(shí)現(xiàn)EntryRefreshPolicy接口的類.
Parameter: disableCacheOnMethods (New! Since 2.4)
指定請(qǐng)求方式不進(jìn)行緩存.默認(rèn)Null,對(duì)所有的請(qǐng)求方式都緩存.例如:
<init-param>
<param-name>disableCacheOnMethods</param-name>
<param-value>POST,PUT,DELETE</param-value>
</init-param>
Parameter: oscache-properties-file (New! Since 2.4)
通過(guò)指定OSCache的屬性文件,開發(fā)者就能運(yùn)行多個(gè)CacheFilter
4.OSCache的屬性文件.(oscache.properties)
cache.memory
值為true或false.默認(rèn)為true.如果設(shè)置為false那么緩存到數(shù)據(jù)庫(kù)或硬盤中.似乎有點(diǎn)傻,所以我們一般不改此項(xiàng).
cache.capacity
緩存元素的個(gè)數(shù).默認(rèn)是沒有限制的.
cache.algorithm
緩存的算法.注意要是指定算法的話,必須把上面的緩存?zhèn)€數(shù)指定.這里支持三種算法.
com.opensymphony.oscache.base.algorithm.LRUCache – 最后最近使用
com.opensymphony.oscache.base.algorithm.FIFOCache – 先進(jìn)先出
com.opensymphony.oscache.base.algorithm.UnlimitedCache – 無(wú)限緩存
cache.blocking
是否同步化。true 或者 false。一般設(shè)為true,避免讀取臟數(shù)據(jù)。
cache.unlimited.disk
指定硬盤緩存是否要作限制。默認(rèn)值為false。false的狀況下,disk cache capacity 將和cache.capacity的值相同。
cache.persistence.class
指定類是被持久化的類。class必須實(shí)現(xiàn)PersistenceListener接口。 作為硬盤持久,可以實(shí)現(xiàn) com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener 接口。 它把class的toString()輸出的hash值作為文件的名稱。如果你要把文件名易讀(自己設(shè)定),DiskPersistenceListener 的父類也 能使用,但其可能有非法字符或者過(guò)長(zhǎng)的名字。 注意:HashDiskPersistenceListener 和 DiskPersistenceListener 需要設(shè)定硬盤路徑:cache.path
cache.path
指定硬盤緩存的路徑。目錄如果不存在將被建立。同時(shí)注意oscache應(yīng)該要有權(quán)限寫文件系統(tǒng)。 cache.path=c:\\myapp\\cache or *ix: cache.path=/opt/myapp/cache
cache.persistence.overflow.only (NEW! Since 2.1)
指定是否只有在內(nèi)存不足的情況下才使用硬盤緩存。 默認(rèn)值false。但推薦是true如果內(nèi)存cache被允許的話。這個(gè)屬性徹底的改變了cache的行為,使得persisted cache 和memory完全不同。
cache.event.listeners
用逗號(hào)分離的class名列表。每個(gè)class必須實(shí)現(xiàn)以下接口之一,或者幾個(gè) CacheEntryEventListener:接收 cache add/update/flush and remove事件 CacheMapAccessEventListener :接收cache 訪問(wèn)事件。這個(gè)可以讓你跟蹤cache怎么工作。 默認(rèn)是不配置任何class的。當(dāng)然你可以使用一下的 class: com.opensymphony.oscache.plugins.clustersupport.BroadcastingCacheEventListener -分布式的(此處被屏蔽)。可以廣播到局域網(wǎng)內(nèi)的其他cache實(shí)例。 com.opensymphony.oscache.extra.CacheEntryEventListenerImpl -一個(gè)簡(jiǎn)單的(此處被屏蔽)。在cache的生命周期中記錄count of 所有entry的事件。 com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl -記錄 count of cache map events(cache hits,misses and state hits).
cache.key
設(shè)置ServletCacheAdministrator使用的Key.在代碼中如果需要用到的話,可以通過(guò)com.opensymphony.oscache.web.ServletCacheAdministrator.DEFAULT_CACHE_KEY得到.
cache.use.host.domain.in.key
如果你的服務(wù)器是被配置到多臺(tái)主機(jī)上的話,你或許想加上一個(gè)主機(jī)的名字在它生成的緩存Key上.true的話會(huì)加上.默認(rèn)值是false.
附加的屬性: cache.cluster.multicast.ip, cache.cluster.properties
5.小結(jié):
OSCache的使用主要有4種:
POJO 緩存
HTTP Response 緩存
JSP Tag Library 緩存
O/R Data Access 緩存
1)、POJO 緩存
這種方式的緩存直接調(diào)用OSCache的API進(jìn)行,主要用于處理頁(yè)面內(nèi)容會(huì)根據(jù)參數(shù)動(dòng)態(tài)改變,可以將參數(shù)設(shè)置為key值來(lái)保存數(shù)據(jù):
首先,聲明成員變量:
// OSCache Adminitrator instance
private static GeneralCacheAdministrator cacheAdmin = null;
其次,進(jìn)行初始化:
public RingArtistAction() {
cacheAdmin = new GeneralCacheAdministrator();
}
將POJO進(jìn)行緩存:
// 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 緩存
這種方式的緩存用來(lái)處理整個(gè)頁(yè)面的內(nèi)容固定,不會(huì)根據(jù)參數(shù)動(dòng)態(tài)改變:
首先在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>
將所有需要緩存的頁(yè)面加入filter-mapping:
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意,只有返回狀態(tài)為200(HttpServletResponse.SC_OK)的內(nèi)容才會(huì)被緩存
3)、JSP Tag 緩存
JSP Tag緩存主要用于緩存JSP頁(yè)面的局部?jī)?nèi)容:
<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 緩存
請(qǐng)閱讀參考資料的內(nèi)容獲取詳情。
如果想隨時(shí)清除web.xml配置的緩存請(qǐng)使用ServletCacheAdministrator.getInstance(request.getSession().getServletContext()).flushAll();
|
評(píng)論:
-
# Cookie混亂及解決辦法。
Posted @ 2008-12-09 16:34
Cookie的path不同屬于不同的cookie.所以如果path簡(jiǎn)單的用'/'來(lái)表示,將會(huì)在客戶端寫下/,和實(shí)際所在path兩個(gè)cookie,將來(lái)如果要清除cookie的話默認(rèn)的只能清除/下的cookie,這樣會(huì)造成cookie的混亂。引起程序的狀態(tài)不穩(wěn)定。
解決辦法是用String path=request.getContextPath來(lái)寫入Cookie的path.這樣會(huì)在客戶端唯一的寫入一個(gè)cookie。然后清除的時(shí)候也要寫入這個(gè)path,用cookie的時(shí)間=0來(lái)清除。 回復(fù) 更多評(píng)論
-
# re: OSCache的實(shí)際使用
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("灌水機(jī)參數(shù)設(shè)置界面");
this.setSize(800, 600);
this.setLocation(100, 100);
GridLayout thisLayout = new GridLayout(7, 2);
this.setLayout(thisLayout);
lab1 = new JLabel("灌水機(jī)參數(shù)設(shè)置:");
lab2 = new JLabel("\u704c\u6c34\u673a\u65f6\u95f4\u95f4\u9694");
lab3 = new JLabel("文章標(biāo)題");
lab4 = new JLabel("發(fā)表文章路徑");
lab5 = new JLabel("發(fā)表文章類型");
lab6 = new JLabel("");
b1 = new JButton("發(fā)表");
b1.setSize(10, 5);
b2 = new JButton("查看發(fā)表統(tǒng)計(jì)");
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
}
}
回復(fù) 更多評(píng)論
-
# re: OSCache的實(shí)際使用[未登錄]
Posted @ 2009-08-06 09:59
網(wǎng)站靜態(tài)化方面的好文章
http://www.cnblogs.com/yizhu2000/archive/2008/09/01/1281532.html 回復(fù) 更多評(píng)論
-
# re: OSCache的實(shí)際使用
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()); } } 回復(fù) 更多評(píng)論
|