JAVA缓存最简单一种实现
创建一个静态的map ConcurrentHashMap 线程安全
本地文件缓存
Ehcache 缓存
jar包
ehcache-core-2.5.2.jar slf4j-api-1.6.1.jar slf4j-jdk14-1.6.1.jar
配置 ehcache.xml
可配置多个cache通过 Cache sample = cacheManager.getCache("name");获取缓存对象
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../bin/ehcache.xsd">
<!--
name:Cache的唯一标识
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大
eternal:Element是否永久有效,一但设置了,timeout将不起作用
overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大
11. timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大
diskPersistent : 是否持久化磁盘缓存。当这个属性的值为true时,系统在初始化的时候会在磁盘中查找文件名为cache名称,后缀名为index的的文件
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)
-->
<defaultCache overflowToDisk="true" eternal="false"/>
<diskStore path="D:/cache" />
<!--
<cache name="zzugxy" overflowToDisk="true" eternal="false"
timeToIdleSeconds="300" timeToLiveSeconds="600" maxElementsInMemory="1000" >
maxElementsOnDisk="10" diskPersistent="true" diskExpiryThreadIntervalSeconds="300"
diskSpoolBufferSizeMB="100" memoryStoreEvictionPolicy="LRU" />
-->
</ehcache>
JAVA 代码
1.获取CacheManager 对象 不传参数表示默认路径 可以传入文件路径和网络地址
2.CacheManager cacheManager = CacheManager.create();
获取ehcache.xml 文件里配置好的 cache
Cache sample = cacheManager.getCache("SimplePageCachingFilter");
3.创建 缓存元素 key 和 val 字面意思
Element element = new Element("key", "val");
4.sample.put(element); 将缓存对象 加入缓存
通过key获取cache中的 缓存元素
Element result = sample.get("key");
注意添加到cache中对象要序列化 实现Serializable接口
通过 次元素 可获取 val等 属性的值
删除缓存
sample.remove("key");
sample.removeAll();
获取所有的缓存对象
for (Object key : cache.getKeys()) {
System.out.println(key);
}
得到缓存中的对象数
cache.getSize();
得到缓存对象占用内存的大小
cache.getMemoryStoreSize();
得到缓存读取的命中次数
cache.getStatistics().getCacheHits();
得到缓存读取的错失次数
cache.getStatistics().getCacheMisses();
写入磁盘
cache.flush();
要想把cache真正持久化到磁盘,写程序时必须注意,在是用net.sf.ehcache.Cache的void put (Element element)方法后要使用void flush()方法
创建个缓存
Ehcache cache = new Cache("testCache", 5000, false, false, 5, 2);
sample.add(cache )
Ehcache整合MyBatis
导入 mybatis-ehcache-1.0.0.jar 还有其他myBatis相关包
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qiuqiu.dao.PersonDao">
<!-- 以下两个<cache>标签二选一,第一个可以输出日志,第二个不输出日志 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
<!-- <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> -->
<select id="selectUserById" parameterType="int" resultType="org.qiuqiu.vo.Person">
select * from person where id=#{id}
</select>
</mapper>
通过注释的方式 整合
@CacheNamespace(implementation=org.mybatis.caches.ehcache.EhcacheCache.class)
EhcacheCache 实现了 mybatis的 Cache接口
默认获取根目录下的ehcache.xml文件
如果 之前在ehcache.xml 没有配置过 相应的cache
这里会根据 id创建一个cache
id= Dao的地址
在ehcache.xml配置 cache麻烦的话
可以 自定义类 继承EhcacheCache 重写 获取cache 将@CacheNamespace
注解里面的参数传进去 自定义 cache
Ehcache页面缓存
jar包
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-web</artifactId>
<version>2.0.4</version>
</dependency>
页面缓存主要用Filter过滤器对请求的url进行过滤,如果该url在缓存中出现。那么页面数据就从缓存对象中获取,并以gzip压缩后返回。其速度是没有压缩缓存时速度的3-5倍,效率相当之高!其中页面缓存的过滤器有CachingFilter,一般要扩展filter或是自定义Filter都继承该CachingFilter
自定义类 继承 SimplePageCachingFilter
重写 doFilter 方法 在里面先判断 是否是要缓存的地址
如果是就调用super.doFilter(request, response, chain);
如果不是就调用chain.doFilter(request, response);
SimplePageCachingFilter里面默认获取 名字SimplePageCachingFilter 的 cache配置
重写 getCacheName方法 设置 cache名字
默认 key :
stringBuffer.append(httpRequest.getMethod()).append(httpRequest.getRequestURI()).append(httpRequest.getQueryString())
可以重写 SimplePageCachingFilter 的 calculateKey() 方法 自己定义key
Ehcache Spring 整合
<bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager">
<ref local="defaultCacheManager"/>
</property>
</bean>
<cache:annotation-driven cache-manager="cacheManager"/>
在类或方法上@Cacheable
@Cacheable(value=”cache”)
这个注释的意思是,当调用这个方法的时候,会从一个名叫 cache的缓存中查询,如果没有,则执行实际的方法(即查询数据库),并将执行的结果存入缓存中,否则返回缓存中的对象。
同时 还有@CacheEvict @CachePut 等注解
详解
远程缓存
Memcached
java memcached client
jar包
commons-pool-1.5.6.jar
java_memcached-release_2.6.6.jar
slf4j-api-1.6.1.jar
slf4j-simple-1.6.1.jar
主要是两个类
SockIOPool 和 MemCachedClient
SockIOPool 这个类用来创建管理客户端和服务器通讯连接池
MemCachedClient 缓存的管理
set方法 gei 方法 等
memcached 缓存对象 需要 实现序列化
set方法 gei 方法 等
注:设置有效时间为5秒是
new Date(5000) 不是 new Date(System.currentTimeMillis()+5000) 神逻辑
更多API
java memcached client 整合spring
<bean id="sockIOPool" class="com.danga.MemCached.SockIOPool"
factory-method="getInstance" init-method="initialize" destroy-method="shutDown">
<constructor-arg>
<value>neeaMemcachedPool</value>
</constructor-arg>
<property name="servers">
<list>
<value>127.1.0.1:11211</value>
</list>
</property>
<property name="initConn">
<value>10</value>
</property>
<property name="maxConn">
<value>250</value>
</property>
<property name="maintSleep">
<value>30</value>
</property>
<property name="nagle">
<value>false</value>
</property>
<property name="socketTO">
<value>3000</value>
</property>
</bean>
<bean id="memcachedClient" class="com.danga.MemCached.MemCachedClient">
<constructor-arg>
<value>neeaMemcachedPool</value>
</constructor-arg>
</bean>
org.springframework.cache.ehcache.EhCacheCacheManager 重org.springframework.cache.Cache和 org.springframework.cache.support.AbstractCacheManager
<bean id="cacheManager" class="com.dingxin.kunyu.cache.MemcachedCacheManager">
<property name="memcachedClient">
<ref bean="memcachedClient"/>
</property>
</bean>
<cache:annotation-driven cache-manager="cacheManager"/>mybatis和memcached的整合
mybatis和memcached的整合
JAR 包
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-memcached</artifactId>
<version>1.0.0</version>
</dependency>
<mapper namespace="org.acme.FooMapper"> <cache type="org.mybatis.caches.memcached.MemcachedCache" />
打印日志
<cache type="org.mybatis.caches.memcached.LoggingMemcachedCache" /> ...</mapper>
memcache的配置是根据classpath下的 /memcached.properties 配置的,如果没有使用默
还可以实现 mybatis的 Cache接口 进行整合
使用Simple-Spring-Memcached注解做缓存操作
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>xmemcached-provider</artifactId>
<version>3.6.0</version>
</dependency>
<!--spymemcached客户端 -->
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spymemcached-provider</artifactId>
<version>3.6.0</version>
</dependency>
Spring 配置
<import resource="simplesm-context.xml" />
<aop:aspectj-autoproxy />
这里面有针对不同客户端的spring配置
simplesm-context.xml 在simple-spring-memcached-3.4.0.jar 包里
在方法上 使用 @ReadThroughSingleCache
两个参数 namespace key前缀 expiration到期时间
在参数上@ParameterValueKeyProvider 生成key 多个参数时候 需要指定 order 值
注 参数不能带空格 或者空的 会报错
@InvalidateSingleCache
作用:失效Cache中的数据
@UpdateSingleCache
作用:更新Cache中的数据 等等
@CacheKeyMethod 标记做为参数 的对象方法上 调用该方法生产key 不包含此注解则调用 toString方法
xmemcached 客户端
Jar 包
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.0.0</version>
</dependency>
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
AddrUtil.getAddresses("127.1.0.1:11211"), new int[] { 1, 1, 1, 1 }
//设置连接池大小,即客户端个数
builder.setConnectionPoolSize(50);
//宕机报警
builder.setFailureMode(true);
//使用二进制文件
builder.setCommandFactory(new BinaryCommandFactory());
MemcachedClient memcachedClient = null;
try {
memcachedClient = builder.build();
try {
memcachedClient.set("zlex", 36000, "set/get");
memcachedClient.get("zlex",);
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (MemcachedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();}
Redis
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.0.0</version>
</dependency>
Jedis客户端
连接池配置
//连接池配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(10);
config.setMaxIdle(50);//设置最大空闲数
config.setBlockWhenExhausted(false);
config.setMaxWaitMillis(timeout);//设置超时时间
config.setMinEvictableIdleTimeMillis(30000);
更多参数 详解
http://shift-alt-ctrl.iteye.com/blog/1885910
//获得连接池
JedisPool pool == new JedisPool(config, host, port, timeout)
//jedisPool对象 可以通过spring 进行封装
//获得Jedis
Jedis client = jedisPool.getResource();
try{
client.set("k1", "v1");
client.expire("k1", time) //设置有效时间
client.get("k1"); //获取值
client.del("k1"); //删除值
}catch(Exception e){
e.printStackTrace();
}finally{
jedisPool.returnResource(client); //必须 释放对象池
}
Redis的key和value都支持二进制安全的字符串
保存对象 需要 序列化对象
序列化工具
public class SerializeUtil {
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
//序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
}
return null;
}
public static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
//反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
}
return null;
}
}
Spring Data Redis
在Jedis的基础上,提供了对Redis访问的进一步封装。使用SDR,不在需要手动维护连接的建立、释放,对对象序列化提供了默认实现
SDR依赖的的是Spring的高版本3.x
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
<!--定义连接工厂-->
<bean id = "jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg index="0" ref="jedisPoolConfig"/>
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="timeout" value="${redis.timeout}"/>
<property name="password" value="${redis.password}"/>
</bean>
<!--定义redisTemplate:提供了对Jedis进行的通用API操作。-->
<bean id = "redisTemplate"
class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
</property>
</bean>
SDR默认采用JDK的序列化机制 使用JdkSerializationRedisSerializer类,进行对象和byte[]之间的相互转换,就像上面的序列化代码
这里是设置 keySerializer 为StringRedisSerializer 所以使用字符串形式的key
redisTemplate.opsForValue().set(key, value);
redisTemplate.opsForValue().get(key);
redisTemplate.delete(key);
http://docs.spring.io/spring-data/redis/docs/1.0.x/api/org/springframework/data/redis/core/RedisTemplate.html
Redis 整合 MyBatis
自定义类 继承myBatis 的cache接口 http://www.tuicool.com/articles/j2AzA3