码迷,mamicode.com
首页 > 其他好文 > 详细

EJB AOP + Ehcache实现EJB方法缓存

时间:2014-07-22 23:05:15      阅读:338      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   java   使用   

最近在做一个J2EE的分布式项目,多个子系统之间需要通过Web Service进行通信,项目中使用EJB发布WebService


 

为了提高系统的响应效率决定给所有的Web Service查询方法返回值添加缓存。要给所有的查询方法统一添加缓存,首先就会想到使用AOP,然后会想到Spring AOP。但是发布成Web ServiceEJB是不受Spring管理的,于是想到了EJB中的AOP策略:Interceptor

 

实现思路如下:

EJB的实现类添加拦截器

拦截器判断查询方法的返回值是否已在缓存中,如果在则直接返回,否则调用EJB的方法,并将返回值放到缓存中,然后将结果返回

 

 

项目中使用的缓存产品是Ehcache,使用时需要引用以下jar

ehcache-core.jar

slf4j-api.jar

slf4j-log4j.jar

 

首先封装一个缓存处理类,功能如下

获取缓存对象

根据名称获取缓存对象

清空缓存对象

根据名称清空缓存对象

添加缓存对象


public class CacheHandler {
	//缓存管理器变量
	private CacheManager manager;
	//缓存变量
	private Cache cache;
	
	//缓存名称
	private final String cacheName="EJB_METHOD_CACHE";
	/********************************单例模式(饿汉式)  begin***********************************************/
	
	private  static CacheHandler cacheHandler=new CacheHandler();
	
	/**
	 * 私有构造函数
	 */
	private CacheHandler(){
		System.out.println("---------------创建单例 begin--------------");
		initCache();
		System.out.println("---------------创建单例 end--------------");
	}
	
	public static CacheHandler getInstance(){
		return cacheHandler;
	}
	
	/********************************单例模式(饿汉式)  end***********************************************/
	
	
	/**
	 * @MethodName	: initCache
	 * @Description	: 初始化缓存
	 */
	private void initCache(){
		//1.创建cachemanager
		URL url=getClass().getResource("/ehcache.xml");
		manager=CacheManager.create(url);
		cache=manager.getCache(cacheName);
		//如果cache是空,則手動創建
		// 当启动hibernate二级缓存时,cache为空
		if(cache==null){
			cache=new Cache("EJB_METHOD_CACHE", 10000, true, false, 600000, 300000);
			manager.addCache(cache);
		}
	}
	
	
	/**
	 * @MethodName	: getCache
	 * @Description	: 外部通过get方法拿到cache后,可清空cache
	 * @return
	 */
	public Cache getCache() {
		return cache;
	}
	
	/**
	 * @MethodName	: getCacheByName
	 * @Description	: 根据缓存名称获取缓存
	 * @param cacheName	缓存名称
	 * @return	缓存名称对应的缓存对象
	 */
	public Cache getCacheByName(String cacheName){
		return manager.getCache(cacheName);
	}
	
	/**
	 * @MethodName	: clearCache
	 * @Description	: 清理缓存
	 */
	public void clearCache(){
		if(cache!=null){
			cache.removeAll();
		}
	}
	
	/**
	 * @MethodName	: clearCacheByName
	 * @Description	: 根据缓存名称删除缓存
	 * @param cacheName	缓存名称
	 */
	public void clearCacheByName(String cacheName){
		getCacheByName(cacheName).removeAll();
	}
	
	
	/**
	 * @MethodName	: addCache
	 * @Description	: 用户自定义缓存
	 * @param cacheName	自定义缓存的名称
	 * @return	自定义的缓存
	 */
	public Cache addCache(String cacheName){
		Cache customCache = manager.getCache(cacheName);
		if(customCache==null){
			customCache =new Cache(cacheName, 10000, false, false, 600000, 300000);
			manager.addCache(customCache);
		}
		return customCache;
	}
	
}

为查询方法添加缓存

 

应用于查询方法的拦截器

public class CacheInterceptor {
	@AroundInvoke
	public Object processCache(InvocationContext context) throws Exception{
		String targetName = context.getTarget().getClass().getName();
		String methodName = context.getMethod().getName();
		Object[] arguments =context.getParameters();
		Object result;
		
		//获取缓存对象
		Cache cache = CacheHandler.getInstance().getCache();
		
		//如果方法名以find、query、或get开头则执行缓存策略
		if(methodName.startsWith("find") || methodName.startsWith("get") || methodName.startsWith("query")){
			String cacheKey = getCacheKey(targetName, methodName, arguments);
			Element element = cache.get(cacheKey);
			if (element == null) {
				result = context.proceed(); // 执行目标方法,并保存目标方法执行后的返回值
				element = new Element(cacheKey, (Serializable) result);
				cache.put(element);
				System.out.println("createCache-->" + cacheKey);
			} else {
				System.out.println("hit Cache-->" + cacheKey);
			}
			return element.getObjectValue();
		}
		
		//否则直接执行目标方法
		return context.proceed();
	}
	
	/**
	 * @MethodName	: getCacheKey
	 * @Description	: 获得cache key的方法,cache key是Cache中一个Element的唯一标识 cache key包括
	 * 包名+类名+方法名+各个参数的具体指,如com.co.cache.service.UserServiceImpl.getAllUser
	 * @param targetName	类名
	 * @param methodName	方法名
	 * @param arguments		方法实参数组
	 * @return						cachekey
	 */
	private String getCacheKey(String targetName, String methodName,
			Object[] arguments) {
		StringBuffer sb = new StringBuffer();
		sb.append(targetName).append(".").append(methodName);
		if ((arguments != null) && (arguments.length != 0)) {
			for (int i = 0; i < arguments.length; i++) {
				if(arguments[i] instanceof String[]){
					String[] strArray = (String[])arguments[i];
					sb.append(".");
					for(String str : strArray){
						sb.append(str);
					}
				}else{
					sb.append(".").append(arguments[i]);
				}
				
			}
		}
		
		return sb.toString();
	}

}

将此拦截器应用到需要添加缓存的EJB实现类上即可

其实就是一行注解:@Interceptors(CacheInterceptor.class),如下所示

@Stateless
@Remote( IJcCommonBean.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@WebService(endpointInterface = "mgr.jc.webservice.common.IJcCommonBean",serviceName = "JcCommonService",targetNamespace = "http://common.webservice.jc.mgr/")
@Interceptors(CacheInterceptor.class)
public class JcCommonBeanImpl extends BaseMgr implements IJcCommonBean {
	//此处是EJB业务逻辑方法

}

清除缓存

 

EJB执行了增删改方法后,缓存中的数据就变成了脏数据,需要清空缓存

同样是用一个拦截器来解决,不同的是,这个拦截器是添加在EJB增删改方法上的

 

拦截器代码如下


public class CacheClearInterceptor {
	
	@AroundInvoke
	public Object clearCache(InvocationContext context) throws Exception{
		
		//执行目标方法
		Object returnObj =context.proceed();
		
		/**************************清空本地缓存  begin**************************************/
		System.out.println("清空前的缓存数:"+CacheHandler.getInstance().getCache().getSize());
		//清空本地缓存
		CacheHandler.getInstance().clearCache();
		System.out.println("清空后的缓存数:"+CacheHandler.getInstance().getCache().getSize());
		/**************************清空本地缓存  end**************************************/
		
		return returnObj;
	}
	
}

将此拦截器应用到增删改方法上

@Interceptors(CacheClearSyncInterceptor.class)
public void addAgency(Agency agency) {
	
	commonEao.save(agency);
	
}

这样就实现了为WebService添加缓存

 

下一篇博客将为大家讲述分布式环境下的缓存同步问题



EJB AOP + Ehcache实现EJB方法缓存,码迷,mamicode.com

EJB AOP + Ehcache实现EJB方法缓存

标签:des   style   blog   http   java   使用   

原文地址:http://blog.csdn.net/wzwenhuan/article/details/24742039

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!