cachetag.java

来自「一个不错的cache」· Java 代码 · 共 797 行 · 第 1/2 页

JAVA
797
字号
/* * Copyright (c) 2002-2003 by OpenSymphony * All rights reserved. */package com.opensymphony.oscache.web.tag;import com.opensymphony.oscache.base.Cache;import com.opensymphony.oscache.base.NeedsRefreshException;import com.opensymphony.oscache.util.StringUtil;import com.opensymphony.oscache.web.ServletCacheAdministrator;import com.opensymphony.oscache.web.WebEntryRefreshPolicy;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import java.io.IOException;import java.util.ArrayList;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.jsp.JspTagException;import javax.servlet.jsp.PageContext;import javax.servlet.jsp.tagext.BodyTagSupport;import javax.servlet.jsp.tagext.TryCatchFinally;/** * CacheTag is a tag that allows for server-side caching of post-processed JSP content.<p> * * It also gives great programatic control over refreshing, flushing and updating the cache.<p> * * Usage Example: * <pre><code> *     &lt;%@ taglib uri="oscache" prefix="cache" %&gt; *     &lt;cache:cache key="mycache" *                 scope="application" *                 refresh="false" *                 time="30"> *              jsp content here... refreshed every 30 seconds *     &lt;/cache:cache&gt; * </code></pre> * * @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> * @version        $Revision: 1.6 $ */public class CacheTag extends BodyTagSupport implements TryCatchFinally {    /**    * Constants for time computation    */    private final static int SECOND = 1;    private final static int MINUTE = 60 * SECOND;    private final static int HOUR = 60 * MINUTE;    private final static int DAY = 24 * HOUR;    private final static int WEEK = 7 * DAY;    private final static int MONTH = 30 * DAY;    private final static int YEAR = 365 * DAY;    /**    * The key under which the tag counter will be stored in the request    */    private final static String CACHE_TAG_COUNTER_KEY = "__oscache_tag_counter";    /**    * Constants for refresh time    */    final static private int ONE_MINUTE = 60;    final static private int ONE_HOUR = 60 * ONE_MINUTE;    final static private int DEFAULT_TIMEOUT = ONE_HOUR;    private static transient Log log = LogFactory.getLog(CacheTag.class);    /**    * Cache modes    */    final static private int SILENT_MODE = 1;    /**    * A flag to indicate whether a NeedsRefreshException was thrown and    * the update needs to be cancelled    */    boolean cancelUpdateRequired = false;    private Cache cache = null;    /**    * If no groups are specified, the cached content does not get put into any groups    */    private List groups = null;    private ServletCacheAdministrator admin = null;    /**    * The actual key to use. This is generated based on the supplied key, scope etc.    */    private String actualKey = null;    /**    * The content that was retrieved from cache    */    private String content = null;    /**    * The cron expression that is used to expire cache entries at specific dates and/or times.    */    private String cron = null;    /**    * if cache key is null, the request URI is used    */    private String key = null;    /**    *  The ISO-639 language code to distinguish different pages in application scope    */    private String language = null;    /**    * Class used to handle the refresh policy logic    */    private String refreshPolicyClass = null;    /**    * Parameters that will be passed to the init method of the    * refresh policy instance.    */    private String refreshPolicyParam = null;    /**    * Whether the cache should be refreshed instantly    */    private boolean refresh = false;    /**    * used for subtags to tell this tag that we should use the cached version    */    private boolean useBody = true;    /**    * The cache mode. Valid values are SILENT_MODE    */    private int mode = 0;    /**    * The cache scope to use    */    private int scope = PageContext.APPLICATION_SCOPE;    /**    * time (in seconds) before cache should be refreshed    */    private int time = DEFAULT_TIMEOUT;    /**    * Set the time this cache entry will be cached for. A date and/or time in    * either ISO-8601 format or a simple format can be specified. The acceptable    * syntax for the simple format can be any one of the following:    *    * <ul>    * <li>0 (seconds)    * <li>0s (seconds)    * <li>0m (minutes)    * <li>0h (hours)    * <li>0d (days)    * <li>0w (weeks)    * </ul>    *    * @param duration The duration to cache this content (using either the simple    * or the ISO-8601 format). Passing in a duration of zero will turn off the    * caching, while a negative value will result in the cached content never    * expiring (ie, the cached content will always be served as long as it is    * present).    */    public void setDuration(String duration) {        try {            // Try Simple Date Format Duration first because it's faster            this.time = parseDuration(duration);        } catch (Exception ex) {            if (log.isDebugEnabled()) {                log.debug("Failed parsing simple duration format '" + duration + "' (" + ex.getMessage() + "). Trying ISO-8601 format...");            }            try {                // Try ISO-8601 Duration                this.time = parseISO_8601_Duration(duration);            } catch (Exception ex1) {                // An invalid duration entered, not much impact.                // The default timeout will be used                log.warn("The requested cache duration '" + duration + "' is invalid (" + ex1.getMessage() + "). Reverting to the default timeout");                this.time = DEFAULT_TIMEOUT;            }        }    }    /**    * Sets the cron expression that should be used to expire content at specific    * dates and/or times.    */    public void setCron(String cron) {        this.cron = cron;    }    /**     * Sets the groups for this cache entry. Any existing groups will     * be replaced.     *     * @param groups A comma-delimited list of groups that the cache entry belongs to.     */    public void setGroups(String groups) {        this.groups = StringUtil.split(groups, ',');    }    /**     * Adds to the groups for this cache entry.     *     * @param group A group to which the cache entry should belong.     */    void addGroup(String group) {        if (groups == null) {            groups = new ArrayList();        }        groups.add(group);    }    /**    * Set the key for this cache entry.    *    * @param key The key for this cache entry.    */    public void setKey(String key) {        this.key = key;    }    /**    * Set the ISO-639 language code to distinguish different pages in application scope    *    * @param language The language code for this cache entry.    */    public void setLanguage(String language) {        this.language = language;    }    /**    * This method allows the user to programatically decide whether the cached    * content should be refreshed immediately.    *    * @param refresh Whether or not to refresh this cache entry immediately.    */    public void setRefresh(boolean refresh) {        this.refresh = refresh;    }    /**    * Setting this to <code>true</code> prevents the cache from writing any output    * to the response, however the JSP content is still cached as normal.    * @param mode The cache mode to use.    */    public void setMode(String mode) {        if ("silent".equalsIgnoreCase(mode)) {            this.mode = SILENT_MODE;        } else {            this.mode = 0;        }    }    /**    * Class used to handle the refresh policy logic    */    public void setRefreshpolicyclass(String refreshPolicyClass) {        this.refreshPolicyClass = refreshPolicyClass;    }    /**    * Parameters that will be passed to the init method of the    * refresh policy instance.    */    public void setRefreshpolicyparam(String refreshPolicyParam) {        this.refreshPolicyParam = refreshPolicyParam;    }    // ----------- setMethods ------------------------------------------------------    /**    * Set the scope of this cache.    * <p>    * @param scope The scope of this cache. Either "application" (default) or "session".    */    public void setScope(String scope) {        if (scope.equalsIgnoreCase(ServletCacheAdministrator.SESSION_SCOPE_NAME)) {            this.scope = PageContext.SESSION_SCOPE;        } else {            this.scope = PageContext.APPLICATION_SCOPE;        }    }    /**    * Set the time this cache entry will be cached for (in seconds)    *    * @param time The time to cache this content (in seconds). Passing in    * a time of zero will turn off the caching. A negative value for the    * time will result in the cached content never expiring (ie, the cached    * content will always be served if it is present)    */    public void setTime(int time) {        this.time = time;    }    /**    * This controls whether or not the body of the tag is evaluated or used.<p>    *    * It is most often called by the &lt;UseCached /&gt; tag to tell this tag to    * use the cached content.    *    * @see UseCachedTag    * @param useBody Whether or not to use the cached content.    */    public void setUseBody(boolean useBody) {        if (log.isDebugEnabled()) {            log.debug("<cache>: Set useBody to " + useBody);        }        this.useBody = useBody;    }    /**    * After the cache body, either update the cache, serve new cached content or    *  indicate an error.    *    * @throws JspTagException The standard exception thrown.    * @return The standard BodyTag return.    */    public int doAfterBody() throws JspTagException {        String body = null;        try {            // if we have a body, and we have not been told to use the cached version            if ((bodyContent != null) && (useBody || (time == 0)) && ((body = bodyContent.getString()) != null)) {                if ((time != 0) || (refreshPolicyClass != null)) {                    // Instantiate custom refresh policy if needed                    WebEntryRefreshPolicy policy = null;                    if (refreshPolicyClass != null) {                        try {                            policy = (WebEntryRefreshPolicy) Class.forName(refreshPolicyClass).newInstance();                            policy.init(actualKey, refreshPolicyParam);                        } catch (Exception e) {                            if (log.isInfoEnabled()) {                                log.info("<cache>: Problem instantiating or initializing refresh policy : " + refreshPolicyClass);                            }                        }                    }                    if (log.isDebugEnabled()) {                        log.debug("<cache>: Updating cache entry with new content : " + actualKey);                    }                    cancelUpdateRequired = false;                    if ((groups == null) || groups.isEmpty()) {                        cache.putInCache(actualKey, body, policy);                    } else {                        String[] groupArray = new String[groups.size()];                        groups.toArray(groupArray);                        cache.putInCache(actualKey, body, groupArray, policy, null);                    }                }            }            // otherwise if we have been told to use the cached content and we have cached content            else {                if (!useBody && (content != null)) {                    if (log.isInfoEnabled()) {                        log.info("<cache>: Using cached version as instructed, useBody = false : " + actualKey);                    }                    body = content;                }                // either the cached entry is blank and a subtag has said don't useBody, or body is null                else {                    if (log.isInfoEnabled()) {                        log.info("<cache>: Missing cached content : " + actualKey);                    }                    body = "Missing cached content";                }            }            // Only display anything if we're not running in silent mode            if (mode != SILENT_MODE) {                bodyContent.clearBody();                bodyContent.write(body);                bodyContent.writeOut(bodyContent.getEnclosingWriter());            }        } catch (java.io.IOException e) {            throw new JspTagException("IO Error: " + e.getMessage());        }        return SKIP_BODY;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?