java pagecache_oscache源代码阅读(四) -- JSP/Servlet缓存CacheFilter

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicvoidinit(FilterConfig filterConfig){

d18c02628675d0a2c816449d98bda930.png        config=filterConfig;

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png        log.info("OSCache: Initializing CacheFilter with filter name"+config.getFilterName());

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//此变量用于防治请求被重复的缓存d18c02628675d0a2c816449d98bda930.pngrequestFiltered=REQUEST_FILTERED+config.getFilterName();

d18c02628675d0a2c816449d98bda930.png        log.info("Request filter attribute is"+requestFiltered);

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//读取配置文件d18c02628675d0a2c816449d98bda930.pngProperties props=null;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry{

d18c02628675d0a2c816449d98bda930.png//首先按照Filter参数指定的地方读取配置文件,否则读取默认位置的d18c02628675d0a2c816449d98bda930.pngString propertiesfile=config.getInitParameter("oscache-properties-file");

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(propertiesfile!=null&&propertiesfile.length()>0){

d18c02628675d0a2c816449d98bda930.png                props=Config.loadProperties(propertiesfile,

d18c02628675d0a2c816449d98bda930.png"CacheFilter with filter name '"+config.getFilterName()+"'");

ecedf933ec37d714bd4c2545da43add2.png            }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif        }catch(Exception e){

d18c02628675d0a2c816449d98bda930.png            log.info("OSCache: Init parameter 'oscache-properties-file' not set, using default.");

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//实例化ServletCacheAdministrator,ServletCacheAdministrator只有一个实例,这里需要关注一下d18c02628675d0a2c816449d98bda930.pngadmin=ServletCacheAdministrator.getInstance(config.getServletContext(), props);

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//缓存超时时间d18c02628675d0a2c816449d98bda930.pngString timeParam=config.getInitParameter("time");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(timeParam!=null){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry{

d18c02628675d0a2c816449d98bda930.png                setTime(Integer.parseInt(timeParam));

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }catch(NumberFormatException nfe){

d18c02628675d0a2c816449d98bda930.png                log.error("OSCache: Unexpected value for the init parameter 'time', defaulting to one hour. Message="d18c02628675d0a2c816449d98bda930.png+nfe.getMessage());

ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//缓存范围d18c02628675d0a2c816449d98bda930.pngString scopeParam=config.getInitParameter("scope");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(scopeParam!=null){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif("session".equalsIgnoreCase(scopeParam)){

d18c02628675d0a2c816449d98bda930.png                setCacheScope(PageContext.SESSION_SCOPE);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("application".equalsIgnoreCase(scopeParam)){

d18c02628675d0a2c816449d98bda930.png                setCacheScope(PageContext.APPLICATION_SCOPE);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }else{

d18c02628675d0a2c816449d98bda930.png                log.error("OSCache: Wrong value '"+scopeParam

d18c02628675d0a2c816449d98bda930.png+"' for init parameter 'scope', defaulting to 'application'.");

ecedf933ec37d714bd4c2545da43add2.png            }d18c02628675d0a2c816449d98bda930.png

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//利用"计划任务"表达式来处理超时时间d18c02628675d0a2c816449d98bda930.pngsetCron(config.getInitParameter("cron"));

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//是否处理included18c02628675d0a2c816449d98bda930.pngString fragmentParam=config.getInitParameter("fragment");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(fragmentParam!=null){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif("no".equalsIgnoreCase(fragmentParam)){

d18c02628675d0a2c816449d98bda930.png                setFragment(FRAGMENT_NO);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("yes".equalsIgnoreCase(fragmentParam)){

d18c02628675d0a2c816449d98bda930.png                setFragment(FRAGMENT_YES);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("auto".equalsIgnoreCase(fragmentParam)){

d18c02628675d0a2c816449d98bda930.png                setFragment(FRAGMENT_AUTODETECT);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }else{

d18c02628675d0a2c816449d98bda930.png                log.error("OSCache: Wrong value '"+fragmentParam

d18c02628675d0a2c816449d98bda930.png+"' for init parameter 'fragment', defaulting to 'auto detect'.");

ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//是否处理URL里包括session id的请求d18c02628675d0a2c816449d98bda930.pngString nocacheParam=config.getInitParameter("nocache");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(nocacheParam!=null){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif("off".equalsIgnoreCase(nocacheParam)){

d18c02628675d0a2c816449d98bda930.png                nocache=NOCACHE_OFF;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("sessionIdInURL".equalsIgnoreCase(nocacheParam)){

d18c02628675d0a2c816449d98bda930.png                nocache=NOCACHE_SESSION_ID_IN_URL;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }else{

d18c02628675d0a2c816449d98bda930.png                log.error("OSCache: Wrong value '"+nocacheParam

d18c02628675d0a2c816449d98bda930.png+"' for init parameter 'nocache', defaulting to 'off'.");

ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//是否处理写入到response中的header属性Last-Modifiedd18c02628675d0a2c816449d98bda930.pngString lastModifiedParam=config.getInitParameter("lastModified");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(lastModifiedParam!=null){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif("off".equalsIgnoreCase(lastModifiedParam)){

d18c02628675d0a2c816449d98bda930.png                lastModified=LAST_MODIFIED_OFF;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("on".equalsIgnoreCase(lastModifiedParam)){

d18c02628675d0a2c816449d98bda930.png                lastModified=LAST_MODIFIED_ON;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("initial".equalsIgnoreCase(lastModifiedParam)){

d18c02628675d0a2c816449d98bda930.png                lastModified=LAST_MODIFIED_INITIAL;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }else{

d18c02628675d0a2c816449d98bda930.png                log.error("OSCache: Wrong value '"+lastModifiedParam

d18c02628675d0a2c816449d98bda930.png+"' for init parameter 'lastModified', defaulting to 'initial'.");

ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//是否处理写入到response中的header属性Expiresd18c02628675d0a2c816449d98bda930.pngString expiresParam=config.getInitParameter("expires");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(expiresParam!=null){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif("off".equalsIgnoreCase(expiresParam)){

d18c02628675d0a2c816449d98bda930.png                setExpires(EXPIRES_OFF);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("on".equalsIgnoreCase(expiresParam)){

d18c02628675d0a2c816449d98bda930.png                setExpires(EXPIRES_ON);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif("time".equalsIgnoreCase(expiresParam)){

d18c02628675d0a2c816449d98bda930.png                setExpires(EXPIRES_TIME);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }else{

d18c02628675d0a2c816449d98bda930.png                log.error("OSCache: Wrong value '"+expiresParam

d18c02628675d0a2c816449d98bda930.png+"' for init parameter 'expires', defaulting to 'on'.");

ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//是否处理写入到response中的header属性Cache-Controld18c02628675d0a2c816449d98bda930.pngString cacheControlMaxAgeParam=config.getInitParameter("max-age");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(cacheControlMaxAgeParam!=null){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(cacheControlMaxAgeParam.equalsIgnoreCase("no init")){

d18c02628675d0a2c816449d98bda930.png                setCacheControlMaxAge(MAX_AGE_NO_INIT);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }elseif(cacheControlMaxAgeParam.equalsIgnoreCase("time")){

d18c02628675d0a2c816449d98bda930.png                setCacheControlMaxAge(MAX_AGE_TIME);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }else{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry{

d18c02628675d0a2c816449d98bda930.png                    setCacheControlMaxAge(Long.parseLong(cacheControlMaxAgeParam));

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif                }catch(NumberFormatException nfe){

d18c02628675d0a2c816449d98bda930.png                    log.error("OSCache: Unexpected value for the init parameter 'max-age', defaulting to '60'. Message="d18c02628675d0a2c816449d98bda930.png+nfe.getMessage());

ecedf933ec37d714bd4c2545da43add2.png                }ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//ICacheKeyProvider的实例,用于创建缓存的keyd18c02628675d0a2c816449d98bda930.pngICacheKeyProvider cacheKeyProviderParam=(ICacheKeyProvider) instantiateFromInitParam(

d18c02628675d0a2c816449d98bda930.png"ICacheKeyProvider", ICacheKeyProvider.class,this.getClass().getName());

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(cacheKeyProviderParam!=null){

d18c02628675d0a2c816449d98bda930.png            setCacheKeyProvider(cacheKeyProviderParam);

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//ICacheGroupsProvider的实例,用于创建缓存的group名字d18c02628675d0a2c816449d98bda930.pngICacheGroupsProvider cacheGroupsProviderParam=(ICacheGroupsProvider) instantiateFromInitParam(

d18c02628675d0a2c816449d98bda930.png"ICacheGroupsProvider", ICacheGroupsProvider.class,this.getClass().getName());

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(cacheGroupsProviderParam!=null){

d18c02628675d0a2c816449d98bda930.png            setCacheGroupsProvider(cacheGroupsProviderParam);

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//EntryRefreshPolicy的实例,用于指定缓存过期策略d18c02628675d0a2c816449d98bda930.pngEntryRefreshPolicy expiresRefreshPolicyParam=(EntryRefreshPolicy) instantiateFromInitParam(

d18c02628675d0a2c816449d98bda930.png"EntryRefreshPolicy", EntryRefreshPolicy.class, ExpiresRefreshPolicy.class.getName());

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(expiresRefreshPolicyParam!=null){

d18c02628675d0a2c816449d98bda930.png            setExpiresRefreshPolicy(expiresRefreshPolicyParam);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif        }else{

d18c02628675d0a2c816449d98bda930.png            setExpiresRefreshPolicy(newExpiresRefreshPolicy(time));

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//指定哪些请求方式不去缓存,如GET,POST等d18c02628675d0a2c816449d98bda930.pngString disableCacheOnMethodsParam=config.getInitParameter("disableCacheOnMethods");

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(StringUtil.hasLength(disableCacheOnMethodsParam)){

d18c02628675d0a2c816449d98bda930.png            disableCacheOnMethods=StringUtil.split(disableCacheOnMethodsParam,',');

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

8f1ba5b45633e9678d1db480c16cae3f.png    }

这个方法主要是对Filter的init-param的载入还有缓存管理器类实例的创建(里面会包括一个Application Scope的Cache的创建还有oscache配置文件的读取)。其中的这句调用时需要关注一下的,admin = ServletCacheAdministrator.getInstance(config.getServletContext(), props),也就是ServletCacheAdministrator类实例的创建。

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicsynchronizedstaticServletCacheAdministrator getInstance(ServletContext context, Properties p){

d18c02628675d0a2c816449d98bda930.png//Cache在ServletContext中的属性名d18c02628675d0a2c816449d98bda930.pngString adminKey=null;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(p!=null){

d18c02628675d0a2c816449d98bda930.png//这里是oscache配置文件中的cache.key属性d18c02628675d0a2c816449d98bda930.pngadminKey=p.getProperty(CACHE_KEY_KEY);

ecedf933ec37d714bd4c2545da43add2.png        }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(adminKey==null){

d18c02628675d0a2c816449d98bda930.png            adminKey=DEFAULT_CACHE_KEY;

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png//ServletCacheAdministrator在ServletContext中的键值要加上"_admin"这个后缀d18c02628675d0a2c816449d98bda930.pngadminKey+=CACHE_ADMINISTRATOR_KEY_SUFFIX;

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//先尝试在ServletContext中找Cache,当然,第一次初始化时是不会找到的d18c02628675d0a2c816449d98bda930.pngServletCacheAdministrator admin=(ServletCacheAdministrator) context.getAttribute(adminKey);

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(admin==null){

d18c02628675d0a2c816449d98bda930.png//实例化一个,并在ServletContext中设定好相关属性d18c02628675d0a2c816449d98bda930.pngadmin=newServletCacheAdministrator(context, p);

d18c02628675d0a2c816449d98bda930.png            Map admins=(Map) context.getAttribute(CACHE_ADMINISTRATORS_KEY);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(admins==null){

d18c02628675d0a2c816449d98bda930.png                admins=newHashMap();

ecedf933ec37d714bd4c2545da43add2.png            }d18c02628675d0a2c816449d98bda930.png            admins.put(adminKey, admin);

d18c02628675d0a2c816449d98bda930.png            context.setAttribute(CACHE_ADMINISTRATORS_KEY, admins);

d18c02628675d0a2c816449d98bda930.png            context.setAttribute(adminKey, admin);

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(log.isInfoEnabled()){

d18c02628675d0a2c816449d98bda930.png                log.info("Created new instance of ServletCacheAdministrator with key"+adminKey);

ecedf933ec37d714bd4c2545da43add2.png            }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//创建Application级别的Cached18c02628675d0a2c816449d98bda930.pngadmin.getAppScopeCache(context);

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(admin.context==null){

d18c02628675d0a2c816449d98bda930.png            admin.context=context;

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.pngreturnadmin;

8f1ba5b45633e9678d1db480c16cae3f.png    }4f1150b881333f12a311ae9ef34da474.png

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicCache getAppScopeCache(ServletContext context){

d18c02628675d0a2c816449d98bda930.png        Cache cache;

d18c02628675d0a2c816449d98bda930.png//首先尝试在ServletContext中查询App级的缓存d18c02628675d0a2c816449d98bda930.pngObject obj=context.getAttribute(getCacheKey());

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif((obj==null)||!(objinstanceofCache)){

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(log.isInfoEnabled()){

d18c02628675d0a2c816449d98bda930.png                log.info("Created new application-scoped cache at key:"+getCacheKey());

ecedf933ec37d714bd4c2545da43add2.png            }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//创建一个缓存实例并放入ServletContext中d18c02628675d0a2c816449d98bda930.pngcache=createCache(PageContext.APPLICATION_SCOPE,null);

d18c02628675d0a2c816449d98bda930.png            context.setAttribute(getCacheKey(), cache);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif        }else{

d18c02628675d0a2c816449d98bda930.png            cache=(Cache) obj;

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.pngreturncache;

8f1ba5b45633e9678d1db480c16cae3f.png    }4f1150b881333f12a311ae9ef34da474.png

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifprivateServletCache createCache(intscope, String sessionId){

d18c02628675d0a2c816449d98bda930.png//创建ServletCached18c02628675d0a2c816449d98bda930.pngServletCache newCache=newServletCache(this, algorithmClass, cacheCapacity, scope);

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//这里的2个参数是用于给持久化缓存构建缓存目录用的,这里要注意,Session级别的缓存可能会有问题

d18c02628675d0a2c816449d98bda930.png//因为config是全局唯一的,在并发访问的情况下如果多个session同时创建缓存会出现同步错误的

d18c02628675d0a2c816449d98bda930.png//所以session级别缓存是不是应该慎用磁盘缓存呢?d18c02628675d0a2c816449d98bda930.pngconfig.set(HASH_KEY_SCOPE,""+scope);

d18c02628675d0a2c816449d98bda930.png        config.set(HASH_KEY_SESSION_ID, sessionId);

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//初始化Cache监听器,包括磁盘缓存的处理类d18c02628675d0a2c816449d98bda930.pngnewCache=(ServletCache) configureStandardListeners(newCache);

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(config.getProperty(CACHE_ENTRY_EVENT_LISTENERS_KEY)!=null){

d18c02628675d0a2c816449d98bda930.png//Add any event listeners that have been specified in the

d18c02628675d0a2c816449d98bda930.png//configurationd18c02628675d0a2c816449d98bda930.pngCacheEventListener[] listeners=getCacheEventListeners();

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giffor(inti=0; i

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(listeners[i]instanceofScopeEventListener){

d18c02628675d0a2c816449d98bda930.png                    newCache.addCacheEventListener(listeners[i]);

ecedf933ec37d714bd4c2545da43add2.png                }ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.pngreturnnewCache;

8f1ba5b45633e9678d1db480c16cae3f.png    }

看过#init()方法后就轮到#doFilter()方法了,这是真正每次对请求进行缓存的地方:

4f1150b881333f12a311ae9ef34da474.pngpublicvoiddoFilter(ServletRequest request, ServletResponse response, FilterChain chain)

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifthrowsServletException, IOException{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(log.isInfoEnabled()){

d18c02628675d0a2c816449d98bda930.png            log.info("OSCache: filter in scope"+cacheScope);

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//判断是否请求已经缓存或者是否能缓存

d18c02628675d0a2c816449d98bda930.png//#isFilteredBefore()判断request中是否包括了requestFiltered这个变量

d18c02628675d0a2c816449d98bda930.png//#isCacheableInternal()根据Filter的disableCacheOnMethods和nocache参数进行判断97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(isFilteredBefore(request)||!isCacheableInternal(request)){

d18c02628675d0a2c816449d98bda930.png            chain.doFilter(request, response);

d18c02628675d0a2c816449d98bda930.pngreturn;

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//设置当前的请求已经缓存了d18c02628675d0a2c816449d98bda930.pngrequest.setAttribute(requestFiltered, Boolean.TRUE);

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png        HttpServletRequest httpRequest=(HttpServletRequest) request;

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//checks if the response will be a fragment of a page

d18c02628675d0a2c816449d98bda930.png//是否处理"include",如果是自动判断那么要判断请求中是否有javax.servlet.include.request_uri参数d18c02628675d0a2c816449d98bda930.pngbooleanfragmentRequest=isFragment(httpRequest);

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//根据不同的缓存范围来返回缓存实例d18c02628675d0a2c816449d98bda930.pngCache cache;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(cacheScope==PageContext.SESSION_SCOPE){

d18c02628675d0a2c816449d98bda930.png//#getSessionScopeCache()中返回的Cache是保存在Session中的d18c02628675d0a2c816449d98bda930.pngcache=admin.getSessionScopeCache(httpRequest.getSession(true));

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif        }else{

d18c02628675d0a2c816449d98bda930.png//#getAppScopeCache()中返回的Cache是保存在ServletContext中的d18c02628675d0a2c816449d98bda930.pngcache=admin.getAppScopeCache(config.getServletContext());

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//生成缓存的key,默认的cacheKeyProvider就是CacheFilter自己

d18c02628675d0a2c816449d98bda930.png//成生的key默认是请求路径+方法名(GET,POST)d18c02628675d0a2c816449d98bda930.pngString key=cacheKeyProvider.createCacheKey(httpRequest, admin, cache);

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry{

d18c02628675d0a2c816449d98bda930.png//查找缓存,如果还没有加入缓存,会抛出NeedsRefreshException,进入异常处理路径d18c02628675d0a2c816449d98bda930.pngResponseContent respContent=(ResponseContent) cache.getFromCache(key, time, cron);

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(log.isInfoEnabled()){

d18c02628675d0a2c816449d98bda930.png                log.info("OSCache: Using cached entry for"+key);

ecedf933ec37d714bd4c2545da43add2.png            }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.pngbooleanacceptsGZip=false;

d18c02628675d0a2c816449d98bda930.png//这里是对客户端缓存的处理,判断下请求中是否包含If-Modified-Since头信息97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif((!fragmentRequest)&&(lastModified!=LAST_MODIFIED_OFF)){

d18c02628675d0a2c816449d98bda930.pnglongclientLastModified=httpRequest.getDateHeader(HEADER_IF_MODIFIED_SINCE);

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//如果请求中的最后修改时间大于缓存的最后修改时间,那么就返回状态码30497e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif((clientLastModified!=-1)&&(clientLastModified>=respContent.getLastModified())){

d18c02628675d0a2c816449d98bda930.png                    ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_NOT_MODIFIED);

d18c02628675d0a2c816449d98bda930.pngreturn;

ecedf933ec37d714bd4c2545da43add2.png                }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//判断是否接受gzip压缩的响应,通过判断请求Header Accept-Encoding是否包含gzipd18c02628675d0a2c816449d98bda930.pngacceptsGZip=respContent.isContentGZiped()&&acceptsGZipEncoding(httpRequest);

ecedf933ec37d714bd4c2545da43add2.png            }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//将缓存的内容写入响应d18c02628675d0a2c816449d98bda930.pngrespContent.writeTo(response, fragmentRequest, acceptsGZip);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif        }catch(NeedsRefreshException nre){

d18c02628675d0a2c816449d98bda930.png//如果缓存中还没有想要的数据或者缓存需要刷新d18c02628675d0a2c816449d98bda930.pngbooleanupdateSucceeded=false;

d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.giftry{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(log.isInfoEnabled()){

d18c02628675d0a2c816449d98bda930.png                    log.info("OSCache: New cache entry, cache stale or cache scope flushed for"+key);

ecedf933ec37d714bd4c2545da43add2.png                }d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//这里用CacheHttpServletResponseWrapper来代替原来的response对象继续请求处理d18c02628675d0a2c816449d98bda930.pngCacheHttpServletResponseWrapper cacheResponse=newCacheHttpServletResponseWrapper(

d18c02628675d0a2c816449d98bda930.png                        (HttpServletResponse) response, fragmentRequest, time*1000L, lastModified, expires,

d18c02628675d0a2c816449d98bda930.png                        cacheControlMaxAge);

d18c02628675d0a2c816449d98bda930.png//继续调用后边的Filter和Servletd18c02628675d0a2c816449d98bda930.pngchain.doFilter(request, cacheResponse);

d18c02628675d0a2c816449d98bda930.png                cacheResponse.flushBuffer();

d18c02628675d0a2c816449d98bda930.png

d18c02628675d0a2c816449d98bda930.png//这里判断下响应码是否是200,只有"OK"才会缓存97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(isCacheableInternal(cacheResponse)){

d18c02628675d0a2c816449d98bda930.png//创建缓存的group,默认的cacheGroupsProvider也是自己d18c02628675d0a2c816449d98bda930.pngString[] groups=cacheGroupsProvider.createCacheGroups(httpRequest, admin, cache);

d18c02628675d0a2c816449d98bda930.png//Store as the cache content the result of the response

d18c02628675d0a2c816449d98bda930.png//将响应内容写入缓存d18c02628675d0a2c816449d98bda930.pngcache.putInCache(key, cacheResponse.getContent(), groups, expiresRefreshPolicy,null);

d18c02628675d0a2c816449d98bda930.png                    updateSucceeded=true;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(log.isInfoEnabled()){

d18c02628675d0a2c816449d98bda930.png                        log.info("OSCache: New entry added to the cache with key"+key);

ecedf933ec37d714bd4c2545da43add2.png                    }ecedf933ec37d714bd4c2545da43add2.png                }97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif            }finally{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(!updateSucceeded){

d18c02628675d0a2c816449d98bda930.png//如果写入缓存失败,要取消更新,防止缓存出现错误的状态d18c02628675d0a2c816449d98bda930.pngcache.cancelUpdate(key);

ecedf933ec37d714bd4c2545da43add2.png                }ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }8f1ba5b45633e9678d1db480c16cae3f.png    }

这个方法的整个流程通过代码的注释其实是很好理解的,要注意的地方有两点:

首先,关注下异常路径里更新缓存的地方,这里用CacheHttpServletResponseWrapper来代替原来的Response对象来继续流程,通过对Response进行包装(Decorator)的方式来记录其要返回客户端的Header和页面内容(记录到ResponseContent类的属性中),其中页面内容的捕获是通过用SplitServletOutputStream类来代替原有的OutputStream来实现的,SplitServletOutputStream中包括了ResponseContent对象的一个ByteArrayOutputStream,每次写入页面响应的数据也都要记录在ByteArrayOutputStream中一份,而在调用Cache的putInCache()方法时有一个cacheResponse.getContent()方法,会返回ResponseContent类的属性,也就是真正要缓存的对象,并且将其ByteArrayOutputStream流中的数据"提交"到一个byte数组中保存下来,从而实现了响应数据的缓存。

其次,是将缓存的ResponseContent中的数据输出的过程,也就是这一句:respContent.writeTo(response, fragmentRequest, acceptsGZip);基本可以理解为上边缓存过程的逆过程,这里就不多说了,有兴趣的可以了解下CacheHttpServletResponseWrapper,ResponseContent,SplitServletOutputStream的相关源代码。

posted on 2010-12-20 08:42 臭美 阅读(3269) 评论(2)  编辑  收藏 所属分类: Cache

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值