本文主要讲解如何在现有的SSM(Spring + SpringMVC + Mybatis)项目下,整合Redis作为二级缓存,本文使用的是mysql数据库。
准备工作:
·完整的SSM项目;
SSM项目搭建及源码
·已安装好的Redis支持
整合过程:
1、在原来的项目中添加相关的jar包支持
注意:这里用的是spring-data-redis-1.4.1.RELEASE.jar,这个版本下,Redis版本必须在2.6.2以下,commons-pool2必须在2.0以上,否则会有兼容性问题
2、编写工具类(实现cache接口)
RedisCache.java
package com.redis;
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.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import com.sun.jndi.url.corbaname.corbanameURLContextFactory;
import com.sun.org.apache.xml.internal.serialize.Serializer;
import redis.clients.jedis.exceptions.JedisConnectionException;
/**
*
* 使用第三方内存数据库Redis作为二级缓存
*/
public class RedisCache implements Cache {
private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);
private static JedisConnectionFactory jedisConnectionFactory;
private final String id;
/**
* The {@code ReadWriteLock}.
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
logger.debug("MybatisRedisCache:id=" + id);
this.id = id;
}
@Override
public void clear() {
JedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
// connection.flushDb();
// connection.flushAll();
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
}
@Override
public String getId() {
return this.id;
}
@Override
public Object getObject(Object key) {
Object result = null;
JedisConnection connection = null;
key = com.util.StringUtil.redisKey(key);
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result = serializer.deserialize(connection.get(serializer.serialize(key)));
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
@Override
public ReadWriteLock getReadWriteLock() {
// TODO Auto-generated method stub
return this.readWriteLock;
}
@Override
public int getSize() {
int result = 0;
JedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
result = Integer.valueOf(connection.dbSize().toString());
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
@Override
public void putObject(Object key, Object value) {
JedisConnection connection = null;
key = com.util.StringUtil.redisKey(key);
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
}
@Override
public Object removeObject(Object key) {
JedisConnection connection = null;
Object result = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result = connection.expire(serializer.serialize(key), 0);
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
public static void updataObject(String key,Object value){
JedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
connection.expire(serializer.serialize(key), 0);
if(key.indexOf("UserMapper")>0){
connection.expire(serializer.serialize("UserMapper"), 0);
}
else if(key.indexOf("ArticleMapper")>0){
connection.expire(serializer.serialize("ArticleMapper"), 0);
}
else if(key.indexOf("CommentMapper")>0){
connection.expire(serializer.serialize("CommentMapper"), 0);
}
else if(key.indexOf("MessageMapper")>0){
connection.expire(serializer.serialize("MessageMapper"), 0);
}
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
}
public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.jedisConnectionFactory = jedisConnectionFactory;
}
}
RedisCacheTransfer.java
package com.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
public class RedisCacheTransfer{
@Autowired
public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.setJedisConnectionFactory(jedisConnectionFactory);
}
}
3、开启mybatis中对缓存的支持
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
<property name="mapperLocations" value="classpath:com/mapping/*.xml" />
<!-- 以下为添加支持部分star -->
<!-- 开启缓存支持 -->
<property name="configurationProperties">
<props>
<!-- 开启关键-->
<prop key="cacheEnabled">true</prop>
<!-- 查询时,关闭关联对象即时加载以提高性能 -->
<prop key="lazyLoadingEnabled">false</prop>
<!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指定),不会加载关联表的所有字段,以提高性能 -->
<prop key="aggressiveLazyLoading">true</prop>
<!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->
<prop key="multipleResultSetsEnabled">true</prop>
<!-- 允许使用列标签代替列名 -->
<prop key="useColumnLabel">true</prop>
<!-- 允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖 -->
<prop key="useGeneratedKeys">true</prop>
<!-- 给予被嵌套的resultMap以字段-属性的映射支持 -->
<prop key="autoMappingBehavior">FULL</prop>
<!-- 对于批量更新操作缓存SQL以提高性能 -->
<prop key="defaultExecutorType">BATCH</prop>
<!-- 数据库超过25000秒仍未响应则超时 -->
<prop key="defaultStatementTimeout">25000</prop>
</props>
</property>
<!-- end -->
</bean>
4、redis属性文件redis.properties
# Redis settings
redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true
5、Redis数据管理
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config.properties</value>
<!-- 扫描redis属性文件 -->
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
<!-- redis数据源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- Spring-redis连接池管理工厂 -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
p:pool-config-ref="poolConfig" />
<!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 -->
<bean id="redisCacheTransfer" class="com.redis.RedisCacheTransfer">
<property name="jedisConnectionFactory" ref="jedisConnectionFactory" />
</bean>
6、相关的mapper.xml文件添加缓存工具类
<cache type="com.redis.RedisCache" />
7、实体类实现Serialzable接口
至此,ssm项目整合Redis完成。