servletcacheadministrator.java
来自「一个不错的cache」· Java 代码 · 共 744 行 · 第 1/2 页
JAVA
744 行
/* * Copyright (c) 2002-2003 by OpenSymphony * All rights reserved. */package com.opensymphony.oscache.web;import com.opensymphony.oscache.base.*;import com.opensymphony.oscache.base.events.CacheEventListener;import com.opensymphony.oscache.base.events.ScopeEvent;import com.opensymphony.oscache.base.events.ScopeEventListener;import com.opensymphony.oscache.base.events.ScopeEventType;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import java.io.Serializable;import java.util.*;import javax.servlet.ServletContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.servlet.jsp.PageContext;/** * A ServletCacheAdministrator creates, flushes and administers the cache. * <p> * This is a "servlet Singleton". This means it's not a Singleton in the traditional sense, * that is stored in a static instance. It's a Singleton _per web app context_. * <p> * Once created it manages the cache path on disk through the oscache.properties * file, and also keeps track of the flush times. * * @author <a href="mailto:mike@atlassian.com">Mike Cannon-Brookes</a> * @author <a href="mailto:tgochenour@peregrine.com">Todd Gochenour</a> * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a> * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a> * @author <a href="mailto:chris@swebtec.com">Chris Miller</a> * @version $Revision: 1.11 $ */public class ServletCacheAdministrator extends AbstractCacheAdministrator implements Serializable { private static final transient Log log = LogFactory.getLog(ServletCacheAdministrator.class); /** * Constants for properties read/written from/to file */ private final static String CACHE_USE_HOST_DOMAIN_KEY = "cache.use.host.domain.in.key"; private final static String CACHE_KEY_KEY = "cache.key"; /** * The default cache key that is used to store the cache in context. */ private final static String DEFAULT_CACHE_KEY = "__oscache_cache"; /** * Constants for scope's name */ public final static String SESSION_SCOPE_NAME = "session"; public final static String APPLICATION_SCOPE_NAME = "application"; /** * The key under which the CacheAdministrator will be stored in the ServletContext */ private final static String CACHE_ADMINISTRATOR_KEY = "__oscache_admin"; /** * Key used to store the current scope in the configuration. This is a hack * to let the scope information get passed through to the DiskPersistenceListener, * and will be removed in a future release. */ public final static String HASH_KEY_SCOPE = "scope"; /** * Key used to store the current session ID in the configuration. This is a hack * to let the scope information get passed through to the DiskPersistenceListener, * and will be removed in a future release. */ public final static String HASH_KEY_SESSION_ID = "sessionId"; /** * Key used to store the servlet container temporary directory in the configuration. * This is a hack to let the scope information get passed through to the * DiskPersistenceListener, and will be removed in a future release. */ public final static String HASH_KEY_CONTEXT_TMPDIR = "context.tempdir"; /** * The string to use as a file separator. */ private final static String FILE_SEPARATOR = "/"; /** * The character to use as a file separator. */ private final static char FILE_SEPARATOR_CHAR = FILE_SEPARATOR.charAt(0); /** * Constant for Key generation. */ private final static short AVERAGE_KEY_LENGTH = 30; /** * Usable caracters for key generation */ private static final String m_strBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * Map containing the flush times of different scopes */ private Map flushTimes; //private transient ServletContext context; /** * Key to use for storing and retrieving Object in contexts (Servlet, session). */ private String cacheKey; /** * Set property cache.use.host.domain.in.key=true to add domain information to key * generation for hosting multiple sites. */ private boolean useHostDomainInKey = false; /** * Create the cache administrator. * * This will reset all the flush times and load the properties file. */ private ServletCacheAdministrator(ServletContext context, Properties p) { super(p); config.set(HASH_KEY_CONTEXT_TMPDIR, context.getAttribute("javax.servlet.context.tempdir")); //this.context = context; flushTimes = new HashMap(); initHostDomainInKey(); } /** * Obtain an instance of the CacheAdministrator * * @param context The ServletContext that this CacheAdministrator is a Singleton under * @return Returns the CacheAdministrator instance for this context */ public static ServletCacheAdministrator getInstance(ServletContext context) { return getInstance(context, null); } /** * Obtain an instance of the CacheAdministrator * * @param context The ServletContext that this CacheAdministrator is a Singleton under * @param p the properties to use for the cache if the cache administrator has not been * created yet. Once the administrator has been created, the properties parameter is * ignored for all future invocations. If a null value is passed in, then the properties * are loaded from the oscache.properties file in the classpath. * @return Returns the CacheAdministrator instance for this context */ public static ServletCacheAdministrator getInstance(ServletContext context, Properties p) { ServletCacheAdministrator admin; admin = (ServletCacheAdministrator) context.getAttribute(CACHE_ADMINISTRATOR_KEY); // First time we need to create the administrator and store it in the // servlet context if (admin == null) { admin = new ServletCacheAdministrator(context, p); context.setAttribute(CACHE_ADMINISTRATOR_KEY, admin); if (log.isInfoEnabled()) { log.info("Created new instance of ServletCacheAdministrator"); } admin.getAppScopeCache(context); } return admin; } /** * Shuts down the cache administrator. This should usually only be called * when the controlling application shuts down. */ public static void destroyInstance(ServletContext context) { ServletCacheAdministrator admin; admin = (ServletCacheAdministrator) context.getAttribute(CACHE_ADMINISTRATOR_KEY); if (admin != null) { // Finalize the application scope cache Cache cache = (Cache) context.getAttribute(admin.getCacheKey()); if (cache != null) { admin.finalizeListeners(cache); context.removeAttribute(admin.getCacheKey()); context.removeAttribute(CACHE_ADMINISTRATOR_KEY); cache = null; if (log.isInfoEnabled()) { log.info("Shut down the ServletCacheAdministrator"); } } admin = null; } } /** * Grabs the cache for the specified scope * * @param request The current request * @param scope The scope of this cache (<code>PageContext.APPLICATION_SCOPE</code> * or <code>PageContext.SESSION_SCOPE</code>) * @return The cache */ public Cache getCache(HttpServletRequest request, int scope) { if (scope == PageContext.APPLICATION_SCOPE) { return getAppScopeCache(request.getSession(true).getServletContext()); } if (scope == PageContext.SESSION_SCOPE) { return getSessionScopeCache(request.getSession(true)); } throw new RuntimeException("The supplied scope value of " + scope + " is invalid. Acceptable values are PageContext.APPLICATION_SCOPE and PageContext.SESSION_SCOPE"); } /** * A convenience method to retrieve the application scope cache * @param context the current <code>ServletContext</code> * @return the application scope cache. If none is present, one will * be created. */ public Cache getAppScopeCache(ServletContext context) { Cache cache; Object obj = context.getAttribute(getCacheKey()); if ((obj == null) || !(obj instanceof Cache)) { if (log.isInfoEnabled()) { log.info("Created new application-scoped cache at key: " + getCacheKey()); } cache = createCache(PageContext.APPLICATION_SCOPE, null); context.setAttribute(getCacheKey(), cache); } else { cache = (Cache) obj; } return cache; } /** * A convenience method to retrieve the session scope cache * * @param session the current <code>HttpSession</code> * @return the session scope cache for this session. If none is present, * one will be created. */ public Cache getSessionScopeCache(HttpSession session) { Cache cache; Object obj = session.getAttribute(getCacheKey()); if ((obj == null) || !(obj instanceof Cache)) { if (log.isInfoEnabled()) { log.info("Created new session-scoped cache in session " + session.getId() + " at key: " + getCacheKey()); } cache = createCache(PageContext.SESSION_SCOPE, session.getId()); session.setAttribute(getCacheKey(), cache); } else { cache = (Cache) obj; } return cache; } /** * Get the cache key from the properties. Set it to a default value if it * is not present in the properties * * @return The cache.key property or the DEFAULT_CACHE_KEY */ public String getCacheKey() { if (cacheKey == null) { cacheKey = getProperty(CACHE_KEY_KEY); if (cacheKey == null) { cacheKey = DEFAULT_CACHE_KEY; } } return cacheKey; } /** * Set the flush time for a specific scope to a specific time * * @param date The time to flush the scope * @param scope The scope to be flushed */ public void setFlushTime(Date date, int scope) { if (log.isInfoEnabled()) { log.info("Flushing scope " + scope + " at " + date); } synchronized (flushTimes) { if (date != null) { // Trigger a SCOPE_FLUSHED event dispatchScopeEvent(ScopeEventType.SCOPE_FLUSHED, scope, date, null); flushTimes.put(new Integer(scope), date); } else { logError("setFlushTime called with a null date."); throw new IllegalArgumentException("setFlushTime called with a null date."); } } } /** * Set the flush time for a specific scope to the current time. * * @param scope The scope to be flushed */ public void setFlushTime(int scope) { setFlushTime(new Date(), scope); } /** * Get the flush time for a particular scope. * * @param scope The scope to get the flush time for. * @return A date representing the time this scope was last flushed. * Returns null if it has never been flushed. */ public Date getFlushTime(int scope) { synchronized (flushTimes) { return (Date) flushTimes.get(new Integer(scope)); } } /** * Retrieve an item from the cache * * @param scope The cache scope * @param request The servlet request * @param key The key of the object to retrieve * @param refreshPeriod The time interval specifying if an entry needs refresh * @return The requested object * @throws NeedsRefreshException */ public Object getFromCache(int scope, HttpServletRequest request, String key, int refreshPeriod) throws NeedsRefreshException { Cache cache = getCache(request, scope); key = this.generateEntryKey(key, request, scope); return cache.getFromCache(key, refreshPeriod); } /** * Checks if the given scope was flushed more recently than the CacheEntry provided. * Used to determine whether to refresh the particular CacheEntry. * * @param cacheEntry The cache entry which we're seeing whether to refresh * @param scope The scope we're checking * * @return Whether or not the scope has been flushed more recently than this cache entry was updated. */ public boolean isScopeFlushed(CacheEntry cacheEntry, int scope) { Date flushDateTime = getFlushTime(scope); if (flushDateTime != null) { long lastUpdate = cacheEntry.getLastUpdate(); return (flushDateTime.getTime() >= lastUpdate); } else { return false; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?