oscache如何缓存页面及如何强制清除指定页面的缓存

本文介绍如何在Web项目中部署Oscache缓存组件,包括配置缓存过滤器、自定义缓存键生成规则及实现缓存清理功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、部署oscache到web项目中,本案例下载oscache的版本是oscache-2.4.1-full.zip,

     步骤:

          1)将oscache-2.4.1.jar 、commons-logging.jar、jgroups-all.jar 包放到项目的 WEB-INF/lib 目录下

          2)将oscache.properties 文件放到项目的src目录下

          3)修改项目 WEB-INF/web.xml文件,添加以下内容

              

	<filter>
		<filter-name>CacheFilter</filter-name>
		<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>
		<init-param>
			<description>缓存有效时间,单位秒,这里设置了7天</description>
			<param-name>time</param-name>
			<param-value>604800</param-value>
		</init-param>
		<init-param>
			<description>缓存的范围,只能是session或application</description>
			<param-name>scope</param-name>
			<param-value>application</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CacheFilter</filter-name>
		<url-pattern>/oscache/*</url-pattern>
	</filter-mapping>


 

2、其实,按照步骤1 部署之后,就可以缓存 /oscache/* 路径下的页面。但是这样存在着一个问题,那就是怎么强制清除缓存?上述的web.xml代码可以看到,通过CacheFilter过滤器只是配置了缓存的有效时间,没法强制清楚缓存。在实际的应用中,却经常会碰到要删除缓存的情况,例如,菜单管理页面,基本上这个页面上的数据会不变,改动少,但也会存在改动的情况,像这种情况就需要改动了之后立即清除缓存,否则用户看到的还是旧的菜单!!我找了下oscache的api文档,发下可以通过以下代码去清除缓存:

		Cache cache = ServletCacheAdministrator.getInstance(request.getSession().getServletContext()).getCache(request,  
				scopetype);
		cache.flushEntry(key);

      这段代码,有个问题是,必须要知道缓存的key才能够删除对应的缓存!接着,查看了com.opensymphony.oscache.web.filter.CacheFilter 源代码,发现了以下这段代码:

    /**
     * {@link ICacheKeyProvider}
     * @see com.opensymphony.oscache.web.filter.ICacheKeyProvider#createCacheKey(javax.servlet.http.HttpServletRequest, ServletCacheAdministrator, Cache)
     */
    public String createCacheKey(HttpServletRequest httpRequest, ServletCacheAdministrator scAdmin, Cache cache) {
        return scAdmin.generateEntryKey(null, httpRequest, cacheScope);
    }

      这段代码,是缓存的key的生成算法。可以看到oscache有自己的key生成规则,但是如果换成自己的key生成规则,不就可以知道,项目中所有页面对应的缓存的key么?所以自己就写了一个CacheFilter,代码如下:

package edu.filter;

import javax.servlet.http.HttpServletRequest;

import com.opensymphony.oscache.base.Cache;
import com.opensymphony.oscache.web.ServletCacheAdministrator;
import com.opensymphony.oscache.web.filter.CacheFilter;

/**
 * Title: CustomOscacheFilter.java
 * Description:  自定义oscache缓存的filter
 *               修改了key的生成规则,让页面路径(相对于 Webapp 的路径)作为key
 * @author yh.zeng
 * @date 2017-6-16
 */
public class CustomOscacheFilter extends CacheFilter{
	
	private String getQueryString(HttpServletRequest httpRequest){
		String queryString = httpRequest.getQueryString();
		if(queryString == null || queryString.equals("")){
			return "";
		}else{
			return "?" + queryString;
		}
	}
	
	@Override
	public String createCacheKey(HttpServletRequest httpRequest,
			ServletCacheAdministrator scAdmin, Cache cache) {
		return httpRequest.getServletPath() + getQueryString(httpRequest) ;
	}

}

 

修改WEB-INF/web.xml,过滤器CacheFilter的类名改成自己写的filter类,代码如下:

	<filter>
		<filter-name>CacheFilter</filter-name>
		<!-- <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> -->
		<filter-class>edu.filter.CustomOscacheFilter</filter-class>
		<init-param>
			<description>缓存有效时间,单位秒,这里设置了7天</description>
			<param-name>time</param-name>
			<param-value>604800</param-value>
		</init-param>
		<init-param>
			<description>缓存的范围,只能是session或application</description>
			<param-name>scope</param-name>
			<param-value>application</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CacheFilter</filter-name>
		<url-pattern>/oscache/*</url-pattern>
	</filter-mapping>


 


     接着,也将强制删除缓存的代码也封装成一个工具类,如下:

package utils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.PageContext;

import com.opensymphony.oscache.base.Cache;
import com.opensymphony.oscache.web.ServletCacheAdministrator;

/**
 * Title: OscacheUtils.java
 * Description: Oscache缓存工具类
 * @author yh.zeng
 * @date 2017-6-16
 */
public class OscacheUtils {
	
	public enum  CACHE_SCOPE{
		APPLICATION_SCOPE,
		SESSION_SCOPE
	}

	/**
	 * 强制刷新(即清除)OSCACHE的缓存数据
	 * @param request   请求对象
	 * @param key       缓存的KEY
	 * @param scope     缓存的作用域
	 */
	public static void flushCacheByKey(HttpServletRequest request, String key, CACHE_SCOPE scope){
		int scopetype = 0;
		switch(scope){
		        case APPLICATION_SCOPE:
		        	    scopetype = PageContext.APPLICATION_SCOPE;
		        	    break;
		        case SESSION_SCOPE:
		        	    scopetype = PageContext.SESSION_SCOPE;
		        	    break;
		}
		Cache cache = ServletCacheAdministrator.getInstance(request.getSession().getServletContext()).getCache(request,  
				scopetype);
		cache.flushEntry(key);
	}
	
}



 

3、写一个测试的页面/oscache/test.jsp,测试缓存功能

<%@ page language="java" import="java.util.Date" pageEncoding="utf-8"%>
<html>
<head>
</head>
<body>
时间:<%=new Date()%>
</body>
</html>


 

大家会发现不管怎么刷新重新打开test.jsp页面,时间还是不会变!这是因为这个页面第一次被打开的时候,页面被oscache缓存起来了,下次重新打开这个页面的时候,会从缓存中读取页面数据,服务器不会重新解析这个页面。大家看下面的后台日志就会发现:

[INFO][2017-06-17 00:35:55][CacheFilter:116] - OSCache: filter in scope 4
[INFO][2017-06-17 00:35:55][CacheFilter:171] - OSCache: New cache entry, cache stale or cache scope flushed for /oscache/test.jsp
[INFO][2017-06-17 00:35:56][CacheFilter:186] - OSCache: New entry added to the cache with key /oscache/test.jsp
[INFO][2017-06-17 00:35:59][CacheFilter:116] - OSCache: filter in scope 4
[INFO][2017-06-17 00:35:59][CacheFilter:146] - OSCache: Using cached entry for /oscache/test.jsp
[INFO][2017-06-17 00:35:59][CacheFilter:116] - OSCache: filter in scope 4
[INFO][2017-06-17 00:35:59][CacheFilter:146] - OSCache: Using cached entry for /oscache/test.jsp
[INFO][2017-06-17 00:36:00][CacheFilter:116] - OSCache: filter in scope 4


上面的日志,同时也可以看出,/oscache/test.jsp 这个页面对应的缓存的key为/oscache/test.jsp。大家可能会提问 这个页面访问路径后加请求参数是否会刷新时间呢?答案,是会的。例如,你访问http://localhost:8080/OscacheTestProj/oscache/test.jsp?a=1 ,页面的时间就会改变,因为这个时候,这个页面对应的缓存KEY=/oscache/test.jsp?a=1,刚好oscache缓存中没有存KEY=/oscache/test.jsp?a=1的缓存数据,所以服务器会重新解析这个页面,并创建KEY=/oscache/test.jsp?a=1的缓存数据!大家看后台日志可以看到:

[INFO][2017-06-17 00:44:02][CacheFilter:116] - OSCache: filter in scope 4
[INFO][2017-06-17 00:44:02][CacheFilter:146] - OSCache: Using cached entry for /oscache/test.jsp
[INFO][2017-06-17 00:44:03][CacheFilter:116] - OSCache: filter in scope 4
[INFO][2017-06-17 00:44:03][CacheFilter:146] - OSCache: Using cached entry for /oscache/test.jsp
[INFO][2017-06-17 00:44:31][CacheFilter:116] - OSCache: filter in scope 4
[INFO][2017-06-17 00:44:31][CacheFilter:171] - OSCache: New cache entry, cache stale or cache scope flushed for /oscache/test.jsp?a=1
[INFO][2017-06-17 00:44:31][CacheFilter:186] - OSCache: New entry added to the cache with key /oscache/test.jsp?a=1


4、大家会发现测试的页面/oscache/test.jsp没有【清除缓存】的功能,这个功能确实很实用!大家肯定还记得我在前面提到的OscacheUtils.java工具类,可以用来清除缓存。这个是手动清除的功能,肯定是前端和后端交互实现的功能,因此前端我考虑用jquery的ajax,后端的话,写个Servlet调用OscacheUtils.java工具类去实现,代码如下:

package edu.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import utils.OscacheUtils;
import utils.StringUtils;

/**
 * Title: ClearCacheServlet.java
 * Description: 清除KEY对应的OSCACHE缓存
 * @author yh.zeng
 * @date 2017-6-16
 */
public class ClearCacheServlet extends HttpServlet {

	private static final long serialVersionUID = -3266620619413471751L;
	private Logger logger = Logger.getLogger(ClearCacheServlet.class);
	private OscacheUtils.CACHE_SCOPE CACHE_SCOPE = OscacheUtils.CACHE_SCOPE.APPLICATION_SCOPE; //缓存作用域
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		String scope = config.getInitParameter("scope");
		if(scope != null){
			if(!scope.equals("application") && !scope.equals("session")){
				logger.error("init-param参数scope的值必须是application或session!");
				throw new ServletException("init-param参数scope的值必须是application或session!");
			}else{
				if(scope.equals("application")){
					CACHE_SCOPE = OscacheUtils.CACHE_SCOPE.APPLICATION_SCOPE;
				}else{
					CACHE_SCOPE = OscacheUtils.CACHE_SCOPE.SESSION_SCOPE;
				}
			}
		}
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		String cachekey = req.getParameter("cachekey"); //缓存的key
		boolean success = true;
		
		try{
			OscacheUtils.flushCacheByKey(req, cachekey, CACHE_SCOPE);
		}catch (Exception e){
			e.printStackTrace();
			logger.error(StringUtils.getExceptionMessage(e));
			success = false;
		}
		if(success){
			resp.getWriter().write("success");
		}else{
			resp.getWriter().write("fail");
		}
		
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
	    doGet(req, resp);
	}
    
}

 

修改WEB-INF/web.xml,添加ClearCacheServlet的配置,如下:

	<servlet>
	   <servlet-name>clearCacheServlet</servlet-name>
	   <servlet-class>edu.servlet.ClearCacheServlet</servlet-class>
	   <init-param>
	      <param-name>scope</param-name>
	      <param-value>application</param-value>
	   </init-param>
	</servlet>
	<servlet-mapping>
	   <servlet-name>clearCacheServlet</servlet-name>
	   <url-pattern>/servlet/clearCacheServlet</url-pattern>
	</servlet-mapping>

 


/oscache/test.jsp也进行了修改,代码如下:

<%@ page language="java" import="java.util.Date" pageEncoding="utf-8"%>
<html>
<head>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript">
       function clearCache(){
           $.post("${pageContext.request.contextPath}/servlet/clearCacheServlet",{cachekey:"/oscache/test.jsp"},function(result){
               if(result == "success"){
                  alert("删除缓存成功!");
               }else{
                  alert("删除缓存失败!");
               }
           });
           return false;
       }
    </script>
</head>
<body>
时间:<%=new Date()%>
<br>
<a href="javascript:void(0)" onclick="clearCache()">清除缓存</a>
</body>
</html>



效果:

点击【清除缓存】之后,再重新刷新页面或打开页面就会发现页面显示的时间会改变了!

 

最终,项目的资源结构如下图:

 

oscache-2.4.1-full.zip 下载地址: http://download.youkuaiyun.com/detail/yh_zeng2/9870218

此次案例的demo下载地址:https://github.com/zengyh/OscacheTestProj.git

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值