一:环境搭建.
1.1 SpringBoot的环境是 1.5.10.RELEASE.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1.2 已配置好开启Server服务的Redis一台.
1.3 查看所有的key,发现是空的.(keys * 通配)
1.4 IDEA下推荐一款插件,Redis的客户端工具.Iedis.
下载链接:Iedis 提取码(9sjd).安装方式就是加载硬盘里面的插件,然后重新启动IDEA即可.
效果如下.
这里在命令行添加一个String类型的key看一下效果吧.
二:Redis的配置.
2.1 由于前文我们源码分析了Data-Redis,对配置比较了解, 配置RestTemplate.这里使用RedisTemplate.StringRedisTemplate继承了RedisTemplate。
2.2 application.properties添加连接信息.
#配置Redis
spring.redis.database=0
spring.redis.host=Redis IP
spring.redis.port=6379
spring.redis.password=123456
#最大连接数
spring.redis.pool.max-active=8
#最大阻塞时间,负值表示没有限制
spring.redis.pool.max-wait=-1
#最小空闲连接数
spring.redis.pool.min-idle=0
#最大空闲连接数
spring.redis.pool.max-idle=8
#连接超时时间(毫秒)
spring.redis.timeout=10000
2.3 Java注解配置RedisTemplate.
RedisCacheConfig(注意导包的正确性)配置泛型类型<Object, Object>
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
/**
* author:
* date:
* time:
* description: 配置Redis缓存
*/
@Configuration
public class RedisCacheConfig {
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.pool.max-active}")
private int maxActive;
@Value("${spring.redis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.pool.max-wait}")
private int maxWait;
/** 配置JedisConnectionFactory*/
@Bean
public JedisConnectionFactory jedisConnectionFactory(){
JedisConnectionFactory factory=new JedisConnectionFactory();
factory.setDatabase(database);
factory.setHostName(host);
factory.setPassword(password);
factory.setPort(port);
JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxActive);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxWaitMillis(maxWait);
factory.setPoolConfig(jedisPoolConfig);
return factory;
}
/** SpringBoot自定义配置RedisTemplate*/
@Bean
@SuppressWarnings({"rawtypes", "unchecked"})
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template=new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper=new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(mapper);
// 设置value的序列化规则和 key的序列化规则
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
2.4 方式一:使用Jedis提供的Java客户端API方法操作Redis.
RedisController如下.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* author:
* date:
* time:
* description:Redis的五种数据类型操作
*/
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@RequestMapping("/value")
public Object redis(){
redisTemplate.opsForValue().set("name", "tomcat");
ValueOperations<Object, Object> value=redisTemplate.opsForValue();
Object name=value.get("name").toString();
// 输出value
System.out.println("获取的值:"+name);
return name;
}
@RequestMapping("/list")
public List<Object> list(){
ListOperations<Object, Object> list=redisTemplate.opsForList();
list.leftPush("s-list", "Chinese");
list.leftPush("s-list", "Math");
list.leftPush("s-list", "English");
// 输出list
System.out.println(list.range("s-list",0,2));
List<Object> resultList=list.range("s-list",0,2);
return resultList;
}
@RequestMapping("/set")
public Set<Object> set(){
SetOperations<Object, Object> set = redisTemplate.opsForSet();
set.add("p-set", "ps");
set.add("p-set", "27");
set.add("p-set", "180cm");
// 输出set
System.out.println(set.members("p-set"));
Set<Object> resultSet=set.members("p-set");
return resultSet;
}
@RequestMapping("/zset")
public Set<Object> zset(){
ZSetOperations<Object, Object> zset=redisTemplate.opsForZSet();
zset.add("z-set", "ps", 0);
zset.add("z-set", "27", 1);
zset.add("z-set", "180cm",2);
// 输出zset
System.out.println(zset.range("z-set",0, 2));
Set<Object> resultZSet=zset.range("z-set",0, 2);
return resultZSet;
}
@RequestMapping("/hash")
public Map<Object,Object> hash(){
HashOperations<Object, Object, Object> hash=redisTemplate.opsForHash();
Map<Object, Object> map=new HashMap();
map.put("name", "lucy");
map.put("age", 22);
map.put("address", "重庆市");
hash.putAll("map",map);
// 输出map
System.out.println(hash.entries("map"));
Map<Object, Object> resultMap=hash.entries("map");
return resultMap;
}
}
浏览器测试如下:
① String类型的.
② List类型的.
③ Set类型的.
④:ZSet类型的.
⑤:Hash类型.
IDEA的Redis插件查看一下吧.
删除所有的key.del key(后面跟多个key,返回成功删除的个数).
方式二:声明式注解操作
启动类添加@EnableCaching,开启声明式注解.
首先来看一下Spring对缓存的支持.
Spring定义了CacheManager和Cahce接口来统一不同的缓存技术,例如,单体版的缓存服务,分布式的缓存服务等,良好的可扩展性
CacheManager是Spring框架提供的各种缓存技术抽象接口.
Cahce接口包含缓存的各种操作(增加,删除,获取缓存).
CacheManager接口位置如下.
CacheManager.使用Spring缓存必不可少的.
getCache():获取指定的名称的缓存对象.
getCacheNames():返回Cache的集合.
SpringBoot为我们自动配置了多个CacheManager.不同我们自己配置CacheManagerle 那我们可以就 嘿嘿了.
SpringBoot默认是以spring.cache为前缀的属性配置缓存的.SpringBoot会自动根据spring.cahce的类型判断使用的缓存类型.
声明式缓存注解.
①:Cacheable
在方法执行前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存中的数据,如果没有数据,调用方法并将方法返回值放进缓存中.
②:CachePut
无论怎样,直接将方法的返回值放进缓存中.
③:CacheEvict
将一条或多条数据从缓存中删除.
④:Caching
可以通过@Caching注解将多个注解策略放在一个方法上.
配置RedisCacheManager.
@Bean
public CacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate){
RedisCacheManager cacheManager=new RedisCacheManager(redisTemplate);
return cacheManager;
}
Service层使用缓存.
缓存对象集合中,缓存是以key-value形式保存的。当不指定缓存的key时,SpringBoot会使用SimpleKeyGenerator
生成key。
由于key如果自己不指定默认就是方法的方法的所有参数组合.由于配置了Remplate的Key的规则是StringRedisSerializer.不能是Integer的入口参数,否则报类型不匹配的错误的.这里的key是使用的SpringEL获取的id值.如果不是能够获取的值就报如下错误的.
例如这样的写法 key="user-#id";
// key为id,value是方法的返回值
@Cacheable(value="UserCache",key="#id")
public User getUserById(String id) {
System.out.println("开始查询");
System.out.println("为id="+id+"的数据做了缓存!");
Integer userId=Integer.valueOf(id);
User user= userMapper.getUserById(Integer.valueOf(id));
System.out.println("结束查询");
return user;
}
Controller层
@RestController
@RequestMapping("/annot/redis")
public class AnnotRedisController {
@Autowired
private UserService userService;
@RequestMapping("/search/{id}")
public User getUser(@PathVariable("id") String id){
User user=null;
if(id!=null){
user=userService.getUserById(id);
}
return user;
}
浏览器访问测试.@Cacheable
这个时候清空控制台,多次请求观察.发现控制台没有输出Service的开始查询执行的方法,是走了Redis缓存的.
这个时候查询一下缓存吧.
使用@CacheEvict从缓存XXX中删除key为id的数据.
Service层
@Override
@CacheEvict(value="UserCache")
public int delete(String id) {
System.out.println("删除了id="+id+"的数据缓存!");
return userMapper.delete(Integer.valueOf(id));
}
Controller层
@RequestMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") String id){
if(id!=null){
userService.delete(id);
return "Delete Success";
}
return "Delete Fail";
}
浏览器测试一下吧.
查看删除效果.
@CachePut:是缓存新增或者是更新后的数据到缓存.测试一下吧.所以和@Cacheable的属性要一样的.缓存属性名和key要一致.
更新的是value值.
由于使用id的这种方式极容易出现重复的.冲突的.(使用是的参数名拼成的缓存key),如果两个方法的参数是一样的,但是里面的执行逻辑不同,这样我们执行第二个方法不就命中第一个方法的缓存了吗.
解决的方法就是我们自己制定key ,或者是实现一个KeyGenerator,在注解中指定KeyGenerator.在注解中指定KeyGenerator即可.但是如果这样的情况很多,每一个都要指定key、KeyGenerator很麻烦。
Spring框架提供:继承CachingConfigurerSupport并重写keyGenerator()。
RedisCacheConfig继承CacingConfigurerSupport.
@Bean
public KeyGenerator userKeyGenerator() {
return new KeyGenerator(){
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder builder=new StringBuilder();
builder.append(target).append("-").append(method).append("-");
for(Object obj:params){
builder.append("-").append(obj);
}
return builder.toString();
}
};
}
这样的缓存key就是包名+方法名+参数名了.只有三者都相同参会冲突的.
首先是访问id=4的用户,将数据由数据库查询出来存放至缓存里面.
至此完成了基于API方法调用和注解的两种方式整合了Redis.