SpringBoot整合Redis(單機版)
一:環境搭建.
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;
}
瀏覽器訪問測試[email protected]
這個時候清空控制檯,多次請求觀察.發現控制檯沒有輸出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.