1.Spring使用原生redisTemplate(数据一致性要求不高)
2.Spring基于注解整合Redis实现内容缓存(要求一致性高)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>com.wwjgroupId>
<artifactId>smallartifactId>
<version>0.0.1-SNAPSHOTversion>
parent>
<artifactId>small-daoartifactId>
<properties>
<mybatis.version>3.4.5mybatis.version>
<mybatis-spring.version>1.3.1mybatis-spring.version>
<pagehelper.version>4.1.4pagehelper.version>
<mysql-connector.version>5.1.41mysql-connector.version>
<c3p0>0.9.5.3c3p0>
<spring-redis>1.6.0.RELEASEspring-redis>
<jredis-version>2.7.3jredis-version>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>${mybatis.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>${mybatis-spring.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql-connector.version}version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>${c3p0}version>
dependency>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-redisartifactId>
<version>${spring-redis}version>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>${jredis-version}version>
dependency>
dependencies>
project>
# Redis settings
redis.host=144.202.3.120
redis.port=6379
redis.pass=redis
redis.dbIndex=0
redis.expiration=3000
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
# check data 有效性
redis.testOnBorrow=true
package com.wwj.utils;
import java.lang.reflect.Method;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
/**
* 重写的generate()方法为数据存入缓存的无参的方法指定存入缓存中的数据的key
* @author Yun
*
*/
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
private volatile JedisConnectionFactory jedisConnectionFactory;
private volatile RedisTemplate<String, String> redisTemplate;
private volatile RedisCacheManager redisCacheManager;
public RedisCacheConfig() {
super();
}
/**
* 带参数的构造方法 初始化所有的成员变量
*
* @param jedisConnectionFactory
* @param redisTemplate
* @param redisCacheManager
*/
public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate<String, String> redisTemplate,
RedisCacheManager redisCacheManager) {
this.jedisConnectionFactory = jedisConnectionFactory;
this.redisTemplate = redisTemplate;
this.redisCacheManager = redisCacheManager;
}
public JedisConnectionFactory getJedisConnecionFactory() {
return jedisConnectionFactory;
}
public RedisTemplate<String, String> getRedisTemplate() {
return redisTemplate;
}
public RedisCacheManager getRedisCacheManager() {
return redisCacheManager;
}
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
//sb.append(target.getClass().getName());
sb.append(method.getName());
if(objects.length != 0){
sb.append("_");
for (Object obj : objects) {
sb.append(obj.toString());
}
}
return sb.toString();
}
};
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.wwj"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.propertiesvalue>
<value>classpath:redis.propertiesvalue>
list>
property>
bean>
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
<property name="driverClass" value="${jdbc.driver}">property>
<property name="jdbcUrl" value="${jdbc.url}">property>
<property name="user" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:spring/mybatis-config.xml">property>
<property name="mapperLocations" value="classpath:Mapper/*.xml">property>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.wwj.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">property>
bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<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>
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<property name="database" value="${redis.dbIndex}" />
<property name="poolConfig" ref="poolConfig" />
bean>
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="hashKeySerializer" ref="stringRedisSerializer"/>
<property name="keySerializer" ref="stringRedisSerializer"/>
bean>
<bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg name="redisOperations" ref="redisTemplate" />
<property name="defaultExpiration" value="${redis.expiration}" />
bean>
<bean id="redisCacheConfig" class="com.wwj.utils.RedisCacheConfig">
<constructor-arg ref="jedisConnectionFactory"/>
<constructor-arg ref="redisTemplate"/>
<constructor-arg ref="redisCacheManager"/>
bean>
beans>
@Cacheable:表明在进入方法之前,Spring会先去缓存服务器中查找对应key的缓存值,如果找到缓存值,那么Spring将不会再调用方法,而是将缓存值独处,返回给调用者;如果没有找到缓存值,那么Spring就会执行你的方法,将最后的结果通过key保存到缓存服务器中。
@CachePut:表明Spring会将该方法返回的值缓存到缓存服务器中,这里需要注意的是,Spring不会事先去缓存服务器中查找,而是直接执行方法,然后缓存。换句话说,该方法始终会被Spring所调用。
@CacheEvict:表示执行方法后从缓存服务器移除对应key的值;
@Cacheable(value=“xxx” key=“zzz”)注解:标注该方法查询的结果进入缓存,再次访问时直接读取缓存中的数据
1.对于有参数的方法,指定value(缓存区间)和key(缓存的key);
对于无参数的方法,只需指定value,存到数据库中数据的key通过重写的generate()方法生成。
2.调用该注解标识的方法时,会根据value和key去redis缓存中查找数据,如果查找不到,则去数据库中查找,然后将查找到的数据存放入redis缓存中;
3.向redis中填充的数据分为两部分:
1).用来记录xxx缓存区间中的缓存数据的key的xxx~keys(zset类型)
2).缓存的数据,key:数据的key;value:序列化后的从数据库中得到的数据
4.第一次执行@Cacheable注解标识的方法,会在redis中新增上面两条数据
5.非第一次执行@Cacheable注解标识的方法,若未从redis中查找到数据,则执行从数据库中查询
* @CacheEvict()注解:移除指定缓存区间的一个或者多个缓存对象
* @param value + key 或者 value + allEntries=true
* 1.value + key 移除value缓存区间内的键为key的数据
* 2.value + allEntries=true 移除value缓存区间内的所有数据
1.建一张用户表模拟数据以及封装的resultmap对应的vo对象(需要被序列化)
2.构建服务层以及dao层和controller层
package com.wwj.controller;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.wwj.service.RedisService;
@Controller
public class RedisController {
@Autowired
private RedisService redisService;
@Resource
private RedisTemplate redisTemplate;
@RequestMapping("/selectRedis1")
@ResponseBody
public String selectRedis1(){
String personCount = null;
personCount= (String) redisTemplate.opsForValue().get("person_count");
if(personCount == null){
//redis缓存中无数据,从数据库中查询,并放入redis缓存中,设置生存时间为1小时
personCount = Integer.toString(redisService.getPersonCount());
redisTemplate.opsForValue().set("person_count", personCount, 1, TimeUnit.HOURS);
} else {
System.out.println("从redis拿取数据");
personCount= (String) redisTemplate.opsForValue().get("person_count");
}
return personCount;
}
}
代码操作示例(数据一致性高)以及增加或者删除修改数据后清空缓存
package com.wwj.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.wwj.mapper.PersonMapper;
import com.wwj.model.Person;
import com.wwj.service.RedisService;
@Service("redisService")
public class RedisServiceImpl implements RedisService{
@Autowired
private PersonMapper personMapper;
@Override
public Integer getPersonCount() {
// TODO Auto-generated method stub
return personMapper.selectCountOfPerson();
}
@Cacheable(value="getPersons")
@Override
public List<Person> getPersons() {
// TODO Auto-generated method stub
return personMapper.selectPersons();
}
@Cacheable(value="getPersonById",key="'getPersonById_'+#id")
@Override
public Person getPersonById(Integer id) {
// TODO Auto-generated method stub
return personMapper.selectPersonById(id);
}
@CacheEvict(value="getPersons",allEntries=true)
@Override
public int savePerson(String name) {
// TODO Auto-generated method stub
return personMapper.insertPerson(name);
}
}