SpringMVC + MyBatis + Mysql + Redis(做为二级缓存) 配置
项目环境: 在SpringMVC + MyBatis + Mysql。Redis部署在Linux虚拟机。
一、总体思路
参考Ehcache实现MyBatis二级缓存代码(Maven引用对应jar查阅)
使用Spring管理Redis链接池
模仿EhcacheCache,实现RedisCache
二、pom.xml中加入Maven依赖
[Java] 纯文本查看 复制代码
?redis
<!-- spring-redis实现 -->
<dependency>spring
<groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.2.RELEASE</version>
</dependency>
<!-- redis客户端jar -->
<dependency>sql
<groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.0</version>
</dependency>
<!-- Ehcache实现,用于参考 -->
<dependency>数据库
<groupId>org.mybatis</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.0</version>
</dependency>
三、引入applicationContext.xml中引入redis配置
[Java] 纯文本查看 复制代码
?apache
<!-- 引入数据库配置文件 -->
<bean
id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">缓存
<property name="locations"> <list> <value>classpath:jdbc.properties</value> <value>classpath:redis.properties</value> </list> </property>
</bean>
<!-- redis数据源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">session
<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"mybatis
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.strive.cms.cache.RedisCacheTransfer">app
<property name="jedisConnectionFactory" ref="jedisConnectionFactory"/>
</bean>
四、建立缓存实现类RedisCache
[Java] 纯文本查看 复制代码
?ide
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; 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() { 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; 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 setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.jedisConnectionFactory = jedisConnectionFactory; }
}
五、建立中间类RedisCacheTransfer,完成RedisCache.jedisConnectionFactory的静态注入
[Java] 纯文本查看 复制代码
?
public class RedisCacheTransfer
{
@Autowired public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.setJedisConnectionFactory(jedisConnectionFactory); }
}
六、配置文件redis.properties
redis.host=192.168.25.132
redis.port=6379
redis.pass=
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true
七、mapper中加入MyBatis二级缓存
[Java] 纯文本查看 复制代码
<mapper namespace="com.strive.cms.dao.site.CatalogMapper" >
<cache type="com.strive.cms.cache.RedisCache"/>
</mapper>
八、Mybatis全局配置
[Java] 纯文本查看 复制代码
?
<?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>
<!-- 配置mybatis的缓存,延迟加载等等一系列属性 --> <settings> <!-- 全局映射器启用缓存 --> <setting name="cacheEnabled" value="true"/> <!-- 查询时,关闭关联对象即时加载以提升性能 --> <setting name="lazyLoadingEnabled" value="false"/> <!-- 对于未知的SQL查询,容许返回不一样的结果集以达到通用的效果 --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 容许使用列标签代替列名 --> <setting name="useColumnLabel" value="true"/> <!-- 不容许使用自定义的主键值(好比由程序生成的UUID 32位编码做为键值),数据表的PK生成策略将被覆盖 --> <setting name="useGeneratedKeys" value="false"/> <!-- 给予被嵌套的resultMap以字段-属性的映射支持 FULL,PARTIAL --> <setting name="autoMappingBehavior" value="PARTIAL"/> <!-- 对于批量更新操做缓存SQL以提升性能 BATCH,SIMPLE --> <!-- <setting name="defaultExecutorType" value="BATCH" /> --> <!-- 数据库超过25000秒仍未响应则超时 --> <!-- <setting name="defaultStatementTimeout" value="25000" /> --> <!-- Allows using RowBounds on nested statements --> <setting name="safeRowBoundsEnabled" value="false"/> <!-- Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn. --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be used just for statement execution, no data will be shared between two different calls to the same SqlSession. --> <setting name="localCacheScope" value="SESSION"/> <!-- Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. --> <setting name="jdbcTypeForNull" value="OTHER"/> <!-- Specifies which Object's methods trigger a lazy load --> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> <!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指 定),不会加载关联表的全部字段,以提升性能 --> <setting name="aggressiveLazyLoading" value="true"/> </settings>
</configuration>
九、打印Sql日志,方便测试
log4j.rootLogger=INFO,Console,File
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n
log4j.appender.File = org.apache.log4j.RollingFileAppender
log4j.appender.File.File = logs/ssm.log
log4j.appender.File.MaxFileSize = 10MB
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] %d{yyyy-MM-dd HH:mm:ss}%m%n
log4j.logger.com.strive.cms=DEBUG