SpringBoot+Mybatis+redis實現二級緩存
阿新 • • 發佈:2018-07-24
gap nal configure argument prope gets ssp tro 1.2
對於查詢比較多的項目可以考慮配置二級緩存,mybatis本身的二級緩存是緩存到本地,但是對於多個節點的項目來說,可能會出現數據不一致的問題,所以采用redis緩存,這樣二級緩存的數據就可以緩存到內存,可實現多個節點項目的數據同步。
1、配置redis的連接
#redis gmall.redis.host=172.16.1.250 gmall.redis.port=6379 gmall.redis.pass=Gworld2017 gmall.redis.photo.database=6 #最大分配的對象數 gmall.redis.maxActive=12000 #最大能夠保持idel狀態的對象數 gmall.redis.maxIdle=600 #當池內沒有返回對象時,最大等待時間 gmall.redis.maxWait=2000 gmall.redis.timeout=5000 #當調用borrow Object方法時,是否進行有效性檢查 gmall.redis.testOnBorrow=true #當調用return Object方法時,是否進行有效性檢查 gmall.redis.testOnReturn=true gmall.redis.minIdle=5
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" default-lazy-init="false"> <bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" primary="true"> <property name="hostName" value="${gmall.redis.host}" /> <property name="port" value="${gmall.redis.port}" /> <property name="password" value="${gmall.redis.pass}" /> <property name="timeout" value="${gmall.redis.timeout}" /> <property name="database" value="${gmall.redis.photo.database}" /> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" primary="true"> <property name="connectionFactory" ref="jedisConnFactory" /> <property name="exposeConnection" value="true" /> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> </bean> </beans>
2、配置mybatis-config.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
3、編寫RedisCache實現Cache類
package com.gcard.gwmedia.cache; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; import com.gcard.gwmedia.utils.SpringBeanFactoryUtils; public class RedisCache implements Cache { Logger logger = LoggerFactory.getLogger(getClass()); private final String FREFIX = "CACHE_"; private final String id; private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); @SuppressWarnings("rawtypes") private RedisTemplate redisTemplate; private long cleanInterval; private long lastClear; public RedisCache(String id){ if(id == null){ throw new IllegalArgumentException("Cache instance require an ID"); } this.id = id; this.cleanInterval = 1 * 60 * 60 * 1000;//一個小時 this.lastClear = System.currentTimeMillis(); } @SuppressWarnings({ "unchecked" }) @Override public void clear() { lastClear = System.currentTimeMillis(); String strKey = FREFIX + id.toString(); getRedisTemplate().delete(strKey); logger.debug("Clear all the cached query result from redis"); } @Override public String getId() { return id; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Object getObject(Object key) { if(key != null){ String strKey = FREFIX + id.toString(); if(clearWhenStale(strKey)){ return null; } RedisTemplate redisTemplate = getRedisTemplate(); Object obj = redisTemplate.opsForHash().get(strKey, key.toString()); logger.debug("Get cached query result from redis"); if(obj != null){ return obj; }else{ return null; } }else{ return null; } } @SuppressWarnings("rawtypes") private RedisTemplate getRedisTemplate() { if(redisTemplate == null){ redisTemplate = (RedisTemplate) SpringBeanFactoryUtils.getBean("redisTemplate"); } return redisTemplate; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void putObject(Object key, Object value) { if (key != null) { String strKey = FREFIX + id.toString(); clearWhenStale(strKey); RedisTemplate redisTemplate = getRedisTemplate(); redisTemplate.opsForHash().put(strKey,key.toString(),value); logger.debug("Put query result to redis"); } } @Override public ReadWriteLock getReadWriteLock() { return readWriteLock; } @Override public int getSize() { return 0; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Object removeObject(Object key) { if (key != null) { String strKey = FREFIX + id.toString(); RedisTemplate redisTemplate = getRedisTemplate(); redisTemplate.opsForHash().delete(strKey, key.toString()); logger.debug("Remove cached query result from redis"); } return null; } public boolean clearWhenStale(Object key){ if(System.currentTimeMillis()-lastClear > cleanInterval){ logger.info("clearWhenStale key={}", key); clear(); return true; } return false; } }
4、配置mapper.xml文件
在mapper.xml文件加入<cache/>
<cache type="com.gcard.gwmedia.cache.RedisCache"/>
5、Application啟動類添加註解@EnableCaching
package com.gcard.gwmedia; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.ImportResource; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) @ImportResource(locations = {"classpath:/config/applicationContext.xml"}) @EnableAsync @EnableCaching public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
SpringBoot+Mybatis+redis實現二級緩存