当前位置: 首页 > 编程笔记 >

利用spring的拦截器自定义缓存的实现实例代码

郁灿
2023-03-14
本文向大家介绍利用spring的拦截器自定义缓存的实现实例代码,包括了利用spring的拦截器自定义缓存的实现实例代码的使用技巧和注意事项,需要的朋友参考一下

本文研究的主要是利用spring的拦截器自定义缓存的实现,具体实现代码如下所示。

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。本文利用Memcached 的实例和spring的拦截器实现缓存自定义的实现。利用拦截器读取自定义的缓存标签,key值的生成策略。

自定义的Cacheable

package com.jeex.sci;
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME) 
@Inherited 
@Documented 
public @interface Cacheable {
	String namespace();
	String key() default "";
	int[] keyArgs() default {
	}
	;
	String[] keyProperties() default {
	}
	;
	String keyGenerator() default "";
	int expires() default 1800;
}

自定义的CacheEvict

package com.jeex.sci;
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME) 
@Inherited 
@Documented 
public @interface CacheEvict {
	String namespace();
	String key() default "";
	int[] keyArgs() default {
	}
	;
	String[] keyProperties() default {
	}
	;
	String keyGenerator() default "";
}

spring如果需要前后通知的话,一般会实现MethodInterceptor public Object invoke(MethodInvocation invocation) throws Throwable

public Object invoke(MethodInvocation invoction) throws Throwable {
	Method method = invoction.getMethod();
	Cacheable c = method.getAnnotation(Cacheable.class);
	if (c != null) {
		return handleCacheable(invoction, method, c);
	}
	CacheEvict ce = method.getAnnotation(CacheEvict.class);
	if (ce != null) {
		return handleCacheEvict(invoction, ce);
	}
	return invoction.proceed();
}

处理cacheable标签

private Object handleCacheable(MethodInvocation invoction, Method method, 
    Cacheable c) throws Throwable {
	String key = getKey(invoction, KeyInfo.fromCacheable(c));
	if (key.equals("")) {
		if (log.isDebugEnabled()){
			log.warn("Empty cache key, the method is " + method);
		}
		return invoction.proceed();
	}
	long nsTag = (long) memcachedGet(c.namespace());
	if (nsTag == null) {
		nsTag = long.valueOf(System.currentTimeMillis());
		memcachedSet(c.namespace(), 24*3600, long.valueOf(nsTag));
	}
	key = makeMemcachedKey(c.namespace(), nsTag, key);
	Object o = null;
	o = memcachedGet(key);
	if (o != null) {
		if (log.isDebugEnabled()) {
			log.debug("CACHE HIT: Cache Key = " + key);
		}
	} else {
		if (log.isDebugEnabled()) {
			log.debug("CACHE MISS: Cache Key = " + key);
		}
		o = invoction.proceed();
		memcachedSet(key, c.expires(), o);
	}
	return o;
}

处理cacheEvit标签

private Object handleCacheEvict(MethodInvocation invoction,  
    CacheEvict ce) throws Throwable { 
  String key = getKey(invoction, KeyInfo.fromCacheEvict(ce));    
   
  if (key.equals("")) {  
    if (log.isDebugEnabled()) { 
      log.debug("Evicting " + ce.namespace()); 
    } 
    memcachedDelete(ce.namespace()); 
  } else { 
    Long nsTag = (Long) memcachedGet(ce.namespace()); 
    if (nsTag != null) { 
      key = makeMemcachedKey(ce.namespace(), nsTag, key); 
      if (log.isDebugEnabled()) { 
        log.debug("Evicting " + key); 
      } 
      memcachedDelete(key);         
    } 
  } 
  return invoction.proceed(); 
} 

根据参数生成key

//使用拦截到方法的参数生成参数 
private String getKeyWithArgs(Object[] args, int[] argIndex) { 
  StringBuilder key = new StringBuilder(); 
  boolean first = true; 
  for (int index: argIndex) { 
    if (index < 0 || index >= args.length) { 
      throw new IllegalArgumentException("Index out of bound"); 
    } 
    if (!first) { 
      key.append(':'); 
    } else { 
      first = false; 
    } 
    key = key.append(args[index]); 
  } 
  return key.toString(); 
} 

根据属性生成key

private String getKeyWithProperties(Object o, String props[])  
    throws Exception { 
  StringBuilder key = new StringBuilder(); 
  boolean first = true; 
  for (String prop: props) { 
    //把bean的属性转为获取方法的名字 
    String methodName = "get"  
        + prop.substring(0, 1).toUpperCase()  
        + prop.substring(1); 
    Method m = o.getClass().getMethod(methodName); 
    Object r = m.invoke(o, (Object[]) null); 
    if (!first) { 
      key.append(':'); 
    } else { 
      first = false; 
    } 
    key = key.append(r); 
  } 
  return key.toString(); 
} 

利用自定义的生成器生成key

//使用生成器生成key 
private String getKeyWithGenerator(MethodInvocation invoction, String keyGenerator)  
    throws Exception { 
  Class<?> ckg = Class.forName(keyGenerator); 
  CacheKeyGenerator ikg = (CacheKeyGenerator)ckg.newInstance(); 
  return ikg.generate(invoction.getArguments()); 
} 

保存key信息的帮助类

private static class KeyInfo {
	String key;
	int[] keyArgs;
	String keyProperties[];
	String keyGenerator;
	static KeyInfo fromCacheable(Cacheable c) {
		KeyInfo ki = new KeyInfo();
		ki.key = c.key();
		ki.keyArgs = c.keyArgs();
		ki.keyGenerator = c.keyGenerator();
		ki.keyProperties = c.keyProperties();
		return ki;
	}
	static KeyInfo fromCacheEvict(CacheEvict ce) {
		KeyInfo ki = new KeyInfo();
		ki.key = ce.key();
		ki.keyArgs = ce.keyArgs();
		ki.keyGenerator = ce.keyGenerator();
		ki.keyProperties = ce.keyProperties();
		return ki;
	}
	String key() {
		return key;
	}
	int[] keyArgs() {
		return keyArgs;
	}
	String[] keyProperties() {
		return keyProperties;
	}
	String keyGenerator() {
		return keyGenerator;
	}
}

参数的设置

//使用参数设置key 
@Cacheable(namespace="BlackList", keyArgs={0, 1}) 
public int anotherMethond(int a, int b) { 
  return 100; 
} 

测试类:

package com.jeex.sci.test;
import net.spy.memcached.MemcachedClient;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class TestMain {
	public static void main(String args[]) throws InterruptedException{
		ApplicationContext ctx = new FileSystemXmlApplicationContext("/src/test/resources/beans.xml");
		MemcachedClient mc = (MemcachedClient) ctx.getBean("memcachedClient");
		BlackListDaoImpl dao = (BlackListDaoImpl)ctx.getBean("blackListDaoImpl");
		while (true) {
			System.out.println("################################GETTING START######################");
			mc.flush();
			BlackListQuery query = new BlackListQuery(1, "222.231.23.13");
			dao.searchBlackListCount(query);
			dao.searchBlackListCount2(query);
			BlackListQuery query2 = new BlackListQuery(1, "123.231.23.14");
			dao.anotherMethond(333, 444);
			dao.searchBlackListCount2(query2);
			dao.searchBlackListCount3(query2);
			dao.evict(query);
			dao.searchBlackListCount2(query);
			dao.evictAll();
			dao.searchBlackListCount3(query2);
			Thread.sleep(300);
		}
	}
}

总结

以上就是本文关于利用spring的拦截器自定义缓存的实现实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

 类似资料:
  • 本文向大家介绍SpringBoot添加自定义拦截器的实现代码,包括了SpringBoot添加自定义拦截器的实现代码的使用技巧和注意事项,需要的朋友参考一下 在Controller层时,往往会需要校验或验证某些操作,而在每个Controller写重复代码,工作量比较大,这里在Springboot项目中 ,通过继承WebMvcConfigurerAdapter,添加拦截器。 1、WebMvcConfi

  • 本文向大家介绍Spring MVC 拦截器实现代码,包括了Spring MVC 拦截器实现代码的使用技巧和注意事项,需要的朋友参考一下 拦截器的实现 1、编写拦截器类实现HandlerInterceptor接口; 2、将拦截器注册进springmvc框架中; 3、配置拦截器的拦截规则; 其他实现方法 WebRequestInterceptor接口: 与上一个的区别是参数区别和prehandle的方

  • 本文向大家介绍spring boot拦截器实现IP黑名单实例代码,包括了spring boot拦截器实现IP黑名单实例代码的使用技巧和注意事项,需要的朋友参考一下 前言 最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习。所以今天就将上次的”?秒防刷新”进行了一番修改。上次是采用注解加拦截器(@Aspect)来实现功能的。但是,如果需求是一个全

  • 我想在我的web应用程序中实现登录/注销,我使用SpringMVC,对于登录/注销,我使用Ehcache和HandlerInterceptorAdapter。基本思想是: > 从下一个请求中,在HandlerInterceptorAdapter的preHandle()方法中从请求对象获取密钥,并签入缓存(如果存在),或者 重定向到登录页面。 用于存储在缓存中的代码为: 现在,对于每一个其他请求,我

  • 本文向大家介绍vue+axios实现登录拦截的实例代码,包括了vue+axios实现登录拦截的实例代码的使用技巧和注意事项,需要的朋友参考一下 一个项目学会vue全家桶+axios实现登录、拦截、登出功能,以及利用axios的http拦截器拦截请求和响应。 前言 该项目是利用了Github 提供的personal token作为登录token,通过token访问你的Repository List。

  • 本文向大家介绍SpringBoot拦截器实现登录拦截的方法示例,包括了SpringBoot拦截器实现登录拦截的方法示例的使用技巧和注意事项,需要的朋友参考一下 源码 GitHub:https://github.com/291685399/springboot-learning/tree/master/springboot-interceptor01 SpringBoot拦截器可以做什么 可以对UR