Redis可以存儲鍵與5種不同數據結構類型之間的映射,這5種數據結構類型分別爲String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。
下面來對這5種數據結構類型作簡單的介紹:
結構類型 | 結構存儲的值 | 結構的讀寫能力 |
---|---|---|
String | 可以是字符串、整數或者浮點數 | 對整個字符串或者字符串的其中一部分執行操作;對象和浮點數執行自增(increment)或者自減(decrement) |
List | 一個鏈表,鏈表上的每個節點都包含了一個字符串 | 從鏈表的兩端推入或者彈出元素;根據偏移量對鏈表進行修剪(trim);讀取單個或者多個元素;根據值來查找或者移除元素 |
Set | 包含字符串的無序收集器(unorderedcollection),並且被包含的每個字符串都是獨一無二的、各不相同 | 添加、獲取、移除單個元素;檢查一個元素是否存在於某個集合中;計算交集、並集、差集;從集合裏賣弄隨機獲取元素 |
Hash | 包含鍵值對的無序散列表 | 添加、獲取、移除單個鍵值對;獲取所有鍵值對 |
Zset | 字符串成員(member)與浮點數分值(score)之間的有序映射,元素的排列順序由分值的大小決定 | 添加、獲取、刪除單個元素;根據分值範圍(range)或者成員來獲取元素 |
使用Jedis操作redis
首先要在pom文件中引入依賴:
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.2</version>
</dependency>
然後就可以使用jedis操作redis數據庫了
代碼如下:
package com.help.demo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
public class JedisClient {
private Jedis jedis;
@Before
public void testConnRedis() {
//連接redis ,redis的默認端口是6379 localhost也可以替換成目標IP
jedis = new Jedis ("localhost",6379);
//權限認證 如果有密碼 需要加上權限認證 如果沒有可以忽略
// jedis.auth("admin");
}
/**
* redis存儲字符串
*/
@Test
public void testString() {
//-----添加數據----------
jedis.set("name","xiaobai");//向key-->name中放入了value-->xiaobai
System.out.println(jedis.get("name"));//執行結果:xiaobai
//將值value關聯到key,並將key的生存時間設爲seconds(秒)。
jedis.setex("foo", 5, "haha");
System.out.println(jedis.get("foo"));
//拼接
jedis.append("name", " is my friend");
System.out.println(jedis.get("name"));
//返回key的個數
System.out.println(jedis.dbSize());
jedis.del("name"); //刪除某個鍵 //可以添加多個 jedis.del("key1","key2","key3","key4","key5");
System.out.println(jedis.get("name"));
//檢查給定key是否存在 因爲上面刪除了 所以不存在
Boolean boo = jedis.exists("name");
System.out.println(boo);
//設置多個鍵值對
jedis.mset("name","xiaoer","age","23","qq","476777XXX");
//jedis.incr("age"); //進行加1操作
System.out.println(jedis.get("name") + "-" + jedis.get("age") + "-" + jedis.get("qq"));
//將key改名爲newkey,當key和newkey相同或者key不存在時,返回一個錯誤
jedis.rename("name", "name2");
System.out.println(jedis.get("name2"));
//返回key所儲存的值的類型。
//none(key不存在),string(字符串),list(列表),set(集合),zset(有序集),hash(哈希表)
System.out.println(jedis.type("name2"));
//設置key生存時間,當key過期時,它會被自動刪除。
jedis.expire("name2", 10);//5秒過期
//移除給定key的生存時間(設置這個key永不過期)
jedis.persist("name2");
//清空所有的key
//jedis.flushAll();
//哈希表key中的域field的值設爲value。
/*jedis.hset("key1", "field1", "field1-value");
jedis.hset("key1", "field2", "field2-value");
jedis.hset("key1", "field3", "field3-value");*/
//和上面同樣的功能
Map<String, String> map = new HashMap<String, String>();
map.put("field1", "field5-value");
map.put("field2", "field6-value");
jedis.hmset("key1", map);
//返回哈希表key中給定域field的值
System.out.println(jedis.hget("key1", "field1"));
//返回哈希表key中給定域field的值(多個)
List<?> list = jedis.hmget("key1","field1","field2");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
//刪除哈希表key中的一個或多個指定域
//jedis.hdel("key1", "field1");
//jedis.hdel("key1", "field1","field2");
//查看哈希表key中,給定域field是否存在。
System.out.println(jedis.hexists("key1", "field1"));
//返回哈希表key中所有域和值
Map<String,String> map2 = jedis.hgetAll("key1");
for(Map.Entry entry: map2.entrySet()) {
System.out.print(entry.getKey() + ":" + entry.getValue() + "\t");
}
//返回哈希表key中的所有map集合的key值
System.out.println(jedis.hkeys("key1"));
//返回哈希表key中的所有map集合的value值
System.out.println(jedis.hvals("key1"));
//查詢key值對應的集合長度
System.out.println(jedis.llen("key2"));
//刪除redis中的list集合
for (int i = 0; i < jedis.llen("key2"); i++) {
System.out.println(jedis.lpop("key2")+"刪除");
}
//將值value插入到列表key的表頭。 在key對應 list的頭部添加字符串元素 如果沒有key值 那就新建一個key值然後建立list列表保存到redis 中
jedis.lpush("key2", "value1-0");
jedis.lpush("key2", "value1-1");
jedis.lpush("key2", "value1-2");
//在key對應 list 的尾部添加字符串元素
//jedis.rpush("key2", "value1-2");
//返回列表key中指定區間內的元素,區間以偏移量start和stop指定.
//下標(index)參數start和stop從0開始;
//負數下標代表從後開始(-1表示列表的最後一個元素,-2表示列表的倒數第二個元素,以此類推)
List<String> list2 = jedis.lrange("key2", 0, -1);//stop下標也在取值範圍內(閉區間)
for(int i=0;i<list2.size();i++){
System.out.println(list2.get(i));
}
//set集合--------------------------
//將member元素加入到集合key當中。
jedis.sadd("key3", "value5");
jedis.sadd("key3", "value8");
//移除集合中的member元素。
// jedis.srem("key3", "value5");
//返回集合key中的所有成員。
Set set = jedis.smembers("key3");
System.out.println(set.toString());
//判斷元素是否是集合key的成員
System.out.println(jedis.sismember("key3", "value2"));
//返回一個集合的全部成員,該集合是所有給定集合的交集
Set set2 = jedis.sinter("key3","key2");
System.out.println(set2.toString());
}
}
===========================================================
springboot操作redis之引入連接池:
首先,建立連接池然後通過獲取連接池連接redis(默認已經引入jedis依賴)
連接池工具類如下:
package com.chaoju.config;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public final class RedisUtil {
//Redis服務器IP
private static String ADDR = "localhost";
//Redis的端口號
private static int PORT = 6379;
//訪問密碼
private static String AUTH = "admin";
//可用連接實例的最大數目,默認值爲8;
//如果賦值爲-1,則表示不限制;如果pool已經分配了maxActive個jedis實例,則此時pool的狀態爲exhausted(耗盡)。
private static int MAX_ACTIVE = 1024;
//控制一個pool最多有多少個狀態爲idle(空閒的)的jedis實例,默認值也是8。
private static int MAX_IDLE = 200;
//等待可用連接的最大時間,單位毫秒,默認值爲-1,表示永不超時。如果超過等待時間,則直接拋出JedisConnectionException;
private static int MAX_WAIT = 10000;
private static int TIMEOUT = 10000;
//在borrow一個jedis實例時,是否提前進行validate操作;如果爲true,則得到的jedis實例均是可用的;
private static boolean TEST_ON_BORROW = true;
private static JedisPool jedisPool = null;
/**
* 初始化Redis連接池
*/
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWait(MAX_WAIT);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT);
//如果redis有密碼 就使用下面這個語句 沒有就使用上面這個
// jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取Jedis實例
* @return
*/
public synchronized static Jedis getJedis() {
try {
if (jedisPool != null) {
Jedis resource = jedisPool.getResource();
return resource;
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 釋放jedis資源
* @param jedis
*/
public static void returnResource(final Jedis jedis) {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
public static void main(String[] args) {
getJedis();
}
}
然後將上面的jedis連接的語句
jedis = new Jedis ("localhost",6379);
jedis.auth("admin");
換成
jedis = RedisUtil.getJedis();
如此也可以操作redis!!!
===============================================================================================
springboot使用配置文件操作redis之引入連接池:
首先在配置文件中添加redis的配置(默認已添加jedis依賴):
#redis jedis配置
# Redis數據庫索引(默認爲0)
spring.redis.database=0
# Redis服務器地址
spring.redis.host= 127.0.0.1
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認爲空)
#spring.redis.password=
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.pool.max-active=200
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連接池中的最大空閒連接
spring.redis.pool.max-idle=8
# 連接池中的最小空閒連接
spring.redis.pool.min-idle=0
# 連接超時時間(毫秒)
spring.redis.timeout=0
#spring-session 使用
spring.session.store-type=none
然後添加配置類:
package com.example.demo.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
public class JedisConfig extends CachingConfigurerSupport{
private Logger logger = LoggerFactory.getLogger(JedisConfig.class);
/**
* SpringSession 需要注意的就是redis需要2.8以上版本,然後開啓事件通知,在redis配置文件裏面加上
* notify-keyspace-events Ex
* Keyspace notifications功能默認是關閉的(默認地,Keyspace 時間通知功能是禁用的,因爲它或多或少會使用一些CPU的資源)。
* 或是使用如下命令:
* redis-cli config set notify-keyspace-events Egx
* 如果你的Redis不是你自己維護的,比如你是使用阿里雲的Redis數據庫,你不能夠更改它的配置,那麼可以使用如下方法:在applicationContext.xml中配置
* <util:constant static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
* @return
*/
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@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 long maxWaitMillis;
@Bean
public JedisPool redisPoolFactory(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setMaxTotal(maxActive);
jedisPoolConfig.setMinIdle(minIdle);
JedisPool jedisPool = new JedisPool(jedisPoolConfig,host,port,timeout,null);
logger.info("JedisPool注入成功!");
logger.info("redis地址:" + host + ":" + port);
return jedisPool;
}
}
這時啓動程序後在控制檯會出現配置類中打印的日誌
接着添加普通類 使用jedis的連接池:
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@RestController
public class Tests {
@Autowired
private JedisPool jedisPool;
@RequestMapping("/")
public String set() {
//獲取redis實例
Jedis resource = jedisPool.getResource();
String str = resource.get("age");
System.out.println(str);
return str;
}
}
啓動項目並訪問http://localhost:8080/
當頁面返回數據表示成功
==================================================================
使用Redistemplate操作redis數據庫
Spring封裝了RedisTemplate對象來進行對Redis的各種操作,它支持所有的Redis原生的api。RedisTemplate位於spring-data-redis包下。
RedisTemplate中定義了對5種數據結構操作:
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
StringRedisTemplate與RedisTemplate
1.兩者的關係是StringRedisTemplate繼承RedisTemplate。
2.兩者的數據是不共通的;也就是說StringRedisTemplate只能管理StringRedisTemplate裏面的數據,RedisTemplate只能管理RedisTemplate中的數據。
3.SDR默認採用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。
----StringRedisTemplate默認採用的是String的序列化策略,保存的key和value都是採用此策略序列化保存的。
----RedisTemplate默認採用的是JDK的序列化策略,保存的key和value都是採用此策略序列化保存的。
操作步驟:
首先添加redis依賴:
<!-- springboot整合redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
然後添加配置類(默認配置文件properties已經添加好):
package com.example.demo.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
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.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis配置類
*
**/
@Configuration
@EnableCaching//開啓註解
public class RedisConfig {
/**
* 選擇redis作爲默認緩存工具
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
CacheManager cacheManager = new RedisCacheManager(redisTemplate);
return cacheManager;
/*RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
// 多個緩存的名稱,目前只定義了一個
rcm.setCacheNames(Arrays.asList("thisredis"));
//設置緩存默認過期時間(秒)
rcm.setDefaultExpiration(600);
return rcm;*/
}
/**
* retemplate相關配置
* @param factory
* @return
*/
// 以下兩種redisTemplate自由根據場景選擇
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
// 配置連接工廠
template.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(默認使用JDK的序列化方式)
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修飾符範圍,ANY是都有包括private和public
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,比如String,Integer等會跑出異常
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
// 值採用json序列化
template.setValueSerializer(serializer);
//使用StringRedisSerializer來序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(factory);
return stringRedisTemplate;
}
}
接着就可以使用了,使用方式如下
添加redis操作String數據結構 的類:
package com.example.demo.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Tests {
@Autowired
private RedisTemplate<String, String> redisTemplate;
// private RedisTemplate<String, Object> redisTemplate;根據實際情況取泛型
String str = null;
@RequestMapping("/String")
public void sets(){
//set void set(K key, V value); 以key-value的形式保存字符串類的數據
redisTemplate.opsForValue().set("names", "劉德華");
//get V get(Object key); 獲取指定key值的數據
str = redisTemplate.opsForValue().get("names");
System.out.println(str);
//setIfAbsent Boolean setIfAbsent(K key, V value); 如果key值之前已經存在爲 false 如果之前不存在則爲 true
System.out.println(redisTemplate.opsForValue().setIfAbsent("names","劉德華22"));
//set void set(K key, V value, long timeout, TimeUnit unit);爲緩存設置時間
redisTemplate.opsForValue().set("name3","張學友",10, TimeUnit.SECONDS);
//由於設置的是10秒失效,十秒之內查詢有結果,十秒之後返回爲null
System.out.println(redisTemplate.opsForValue().get("name3"));
// set void set(K key, V value, long offset);
// 覆寫(overwrite)給定 key 所儲存的字符串值,從偏移量 offset 開始
redisTemplate.opsForValue().set("name4","hello world");
redisTemplate.opsForValue().set("name4","redis", 6);
//輸出結果 hello redis
System.out.println(redisTemplate.opsForValue().get("name4"));
//getAndSet V getAndSet(K key, V value); 設置鍵的字符串值並返回其舊值
redisTemplate.opsForValue().set("getSetTest","test");
//結果:test
System.out.println(redisTemplate.opsForValue().getAndSet("getSetTest","test2"));
//append Integer append(K key, String value);
//如果key已經存在並且是一個字符串,則該命令將該值追加到字符串的末尾。如果鍵不存在,則它被創建並設置爲空字符串,因此APPEND在這種特殊情況下將類似於SET。
redisTemplate.opsForValue().append("test","Hello");
System.out.println(redisTemplate.opsForValue().get("test"));
redisTemplate.opsForValue().append("test","world");
System.out.println(redisTemplate.opsForValue().get("test"));
//size Long size(K key); 返回key所對應的value值得長度
System.out.println("***************"+redisTemplate.opsForValue().size("test"));
//multiSet void multiSet(Map<? extends K, ? extends V> m);
//multiGet List<V> multiGet(Collection<K> keys);
//爲多個鍵分別設置它們的值
Map<String,String> maps = new HashMap<String, String>();
maps.put("multi1","multi4");
maps.put("multi2","multi5");
maps.put("multi3","multi6");
redisTemplate.opsForValue().multiSet(maps);
//添加多個鍵並獲取每個鍵對應的值
List<String> keys = new ArrayList<String>();
keys.add("multi1");
keys.add("multi2");
keys.add("multi3");
System.out.println(redisTemplate.opsForValue().multiGet(keys));//結果:[multi4, multi5, multi6]
//multiSetIfAbsent Boolean multiSetIfAbsent(Map<? extends K, ? extends V> m);
//爲多個鍵分別設置它們的值,如果存在則返回false,不存在返回true
Map<String,String> maps1 = new HashMap<String, String>();
maps1.put("multi11","multi11");
maps1.put("multi22","multi22");
maps1.put("multi33","multi33");
Map<String,String> maps2 = new HashMap<String, String>();
maps2.put("multi1","multi1");
maps2.put("multi2","multi2");
maps2.put("multi3","multi3");
System.out.println(redisTemplate.opsForValue().multiSetIfAbsent(maps1));//true
System.out.println(redisTemplate.opsForValue().multiSetIfAbsent(maps2)); //false
//increment Long increment(K key, long delta); 支持整數
redisTemplate.opsForValue().set("increlong","2");
//操作increment自增時出現錯誤 JedisDataException: ERR value is not an integer or out of range
//所以我在redis中初始化了上面的 redisTemplate.opsForValue().set("increlong","2");數據就不報錯了 有人說是redis引入依賴版本的問題 沒找到具體原因 如果有高手幫忙指點一下
redisTemplate.opsForValue().increment("increlong",2);
System.out.println("***************"+redisTemplate.opsForValue().get("increlong"));
//increment Double increment(K key, double delta); 支持浮點數
redisTemplate.opsForValue().increment("increlong",1.2);
System.out.println("***************"+redisTemplate.opsForValue().get("increlong"));
// get String get(K key, long start, long end); 截取key所對應的value字符串
redisTemplate.opsForValue().set("appendTest", "helloworld");
System.out.println("*********"+redisTemplate.opsForValue().get("appendTest",0,5));
System.out.println("*********"+redisTemplate.opsForValue().get("appendTest",0,-1));
System.out.println("*********"+redisTemplate.opsForValue().get("appendTest",-3,-1));
}
}
添加redis操作List數據結構 的類:
package com.example.demo.config;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/list")
public class TestList {
@Resource //這個地方之前用autowired注入報錯 換成了這個
private RedisTemplate<String, Object> redisTemplate;
/*
* public interface ListOperations<K,V>
* Redis列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素導列表的頭部(左邊)或者尾部(右邊)
* ListOperations專門操作list列表:
* */
@RequestMapping("/test")
public void TestList(){
//Long leftPush(K key, V value);
//將所有指定的值插入存儲在鍵的列表的頭部。如果鍵不存在,則在執行推送操作之前將其創建爲空列表。(從左邊插入)
redisTemplate.opsForList().leftPush("list","java");
redisTemplate.opsForList().leftPush("list","python");
redisTemplate.opsForList().leftPush("list","c++");
//Long leftPush(K key, V pivot, V value);
//把value值放到key對應列表中pivot值的左面,如果pivot值存在的話
redisTemplate.opsForList().leftPush("list","java","oc");
System.out.println(redisTemplate.opsForList().range("list",0,-1));
//Long leftPushAll(K key, V... values);
//批量把一個數組插入到列表中
String[] stringarrays = new String[]{"1","2","3"};
redisTemplate.opsForList().leftPushAll("listarray",stringarrays);
System.out.println(redisTemplate.opsForList().range("listarray",0,-1));
//Long leftPushAll(K key, Collection<V> values);
//批量把一個集合插入到列表中
List<Object> strings = new ArrayList<Object>();
strings.add("1");
strings.add("2");
strings.add("3");
redisTemplate.opsForList().leftPushAll("listcollection4", strings);
System.out.println(redisTemplate.opsForList().range("listcollection4",0,-1));
//Long rightPushAll(K key, V... values);
String[] stringarrayss = new String[]{"1","2","3"};
redisTemplate.opsForList().rightPushAll("listarrayright",stringarrayss);
System.out.println("=oo="+redisTemplate.opsForList().range("listarrayright",0,-1));
//Long rightPush(K key, V value);
//將所有指定的值插入存儲在鍵的列表的頭部。如果鍵不存在,則在執行推送操作之前將其創建爲空列表。(從右邊插入)
redisTemplate.opsForList().rightPush("listRight","PHP");
redisTemplate.opsForList().rightPush("listRight","PB");
System.out.println(redisTemplate.opsForList().range("listRight",0,-1));
//Long rightPushAll(K key, Collection<V> values);
List<Object> strings2 = new ArrayList<Object>();
strings2.add("7");
strings2.add("8");
strings2.add("9");
redisTemplate.opsForList().rightPushAll("listcollectionright", strings2);
System.out.println(redisTemplate.opsForList().range("listcollectionright",0,-1));
//Long rightPush(K key, V pivot, V value);
//把value值放到key對應列表中pivot值的右面,如果pivot值存在的話 如果不存在就不會保存
System.out.println(redisTemplate.opsForList().range("listRight",0,-1));
redisTemplate.opsForList().rightPush("listRight","PB","oc22");
System.out.println(redisTemplate.opsForList().range("listRight",0,-1));
//void set(K key, long index, V value);
//在列表中index的位置設置value值
redisTemplate.opsForList().set("listRight",1,"setValue");
System.out.println(redisTemplate.opsForList().range("listRight",0,-1));
//List<V> range(K key, long start, long end);
//返回存儲在鍵中的列表的指定元素。偏移開始和停止是基於零的索引,其中0是列表的第一個元素(列表的頭部),1是下一個元素
System.out.println(redisTemplate.opsForList().range("list",0,-1));
//Long size(K key); 返回存儲在鍵中的列表的長度。如果鍵不存在,則將其解釋爲空列表,並返回0。當key存儲的值不是列表時返回錯誤。
System.out.println(redisTemplate.opsForList().size("list"));
/*Long remove(K key, long count, Object value);
從存儲在鍵中的列表中刪除等於值的元素的第一個計數事件。
計數參數以下列方式影響操作:
count> 0:刪除等於從頭到尾移動的值的元素。
count <0:刪除等於從尾到頭移動的值的元素。
count = 0:刪除等於value的所有元素。
*/
System.out.println(redisTemplate.opsForList().range("listRight",0,-1));
redisTemplate.opsForList().remove("listRight",1,"setValue");//將刪除列表中存儲的列表中第一次次出現的“setValue”。
System.out.println(redisTemplate.opsForList().range("listRight",0,-1));
//V index(K key, long index);
//根據下表獲取列表中的值,下標是從0開始的
System.out.println(redisTemplate.opsForList().range("listRight",0,-1));
System.out.println(redisTemplate.opsForList().index("listRight",2));
//V leftPop(K key);
//彈出最左邊的元素,彈出之後該值在列表中將不復存在
System.out.println(redisTemplate.opsForList().range("list",0,-1));
System.out.println(redisTemplate.opsForList().leftPop("list"));
System.out.println(redisTemplate.opsForList().range("list",0,-1));
/*V leftPop(K key, long timeout, TimeUnit unit);
移出並獲取列表的第一個元素, 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素爲止。
用法與 leftPop(K key);一樣*/
//V rightPop(K key);
//彈出最右邊的元素,彈出之後該值在列表中將不復存在
System.out.println(redisTemplate.opsForList().range("list",0,-1));
System.out.println(redisTemplate.opsForList().rightPop("list"));
System.out.println(redisTemplate.opsForList().range("list",0,-1));
/*V rightPop(K key, long timeout, TimeUnit unit);
移出並獲取列表的最後一個元素, 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素爲止。
用法與 rightPop(K key);一樣*/
//V rightPopAndLeftPush(K sourceKey, K destinationKey);
//用於移除列表的最後一個元素,並將該元素添加到另一個列表並返回。
System.out.println(redisTemplate.opsForList().range("list",0,-1));
redisTemplate.opsForList().rightPopAndLeftPush("list","rightPopAndLeftPush");
System.out.println(redisTemplate.opsForList().range("list",0,-1));
System.out.println(redisTemplate.opsForList().range("rightPopAndLeftPush",0,-1));
/*V rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit);
用於移除列表的最後一個元素,並將該元素添加到另一個列表並返回,如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素爲止。
用法與rightPopAndLeftPush(K sourceKey, K destinationKey)一樣*/
}
}
添加Hash數據結構 的操作:
package com.example.demo.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hash")
public class TestHash {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@RequestMapping("/test")
public void TestHashs(){
//添加redis
Map<String,Object> testMap = new HashMap<String,Object>();
testMap.put("name","wang");
testMap.put("age",27);
testMap.put("tel","13000000000");
redisTemplate.opsForHash().putAll("redisHash1",testMap);
//void put(H key, HK hashKey, HV value);
//設置散列hashKey的值
redisTemplate.opsForHash().put("redisHash1","address","北京市豐臺區");
System.out.println(redisTemplate.opsForHash().entries("redisHash1"));
//List<HV> multiGet(H key, Collection<HK> hashKeys);
//從哈希中獲取給定hashKey的值
List<Object> kes = new ArrayList<Object>();
kes.add("name");
kes.add("age");
System.out.println(redisTemplate.opsForHash().multiGet("redisHash1",kes));
//Set<HK> keys(H key);
//獲取key所對應的散列表的key
System.out.println(redisTemplate.opsForHash().keys("redisHash1"));
//Long size(H key);
//獲取key所對應的散列表的大小個數
System.out.println(redisTemplate.opsForHash().size("redisHash1"));
//HV get(H key, Object hashKey);
//從鍵中的哈希獲取給定hashKey的值
System.out.println(redisTemplate.opsForHash().get("redisHash1","age"));
//Map<HK, HV> entries(H key);
//獲取整個哈希存儲的key值根據密鑰
System.out.println(redisTemplate.opsForHash().entries("redisHash1"));
//List<HV> values(H key);
//獲取整個哈希存儲的value值根據密鑰
System.out.println(redisTemplate.opsForHash().values("redisHash1"));
//Boolean hasKey(H key, Object hashKey);
//確定哈希hashKey是否存在
System.out.println(redisTemplate.opsForHash().hasKey("redisHash1","age"));
System.out.println(redisTemplate.opsForHash().hasKey("redisHash1","ttt"));
//Long delete(H key, Object... hashKeys);
//刪除給定的哈希hashKeys
redisTemplate.opsForHash().delete("redisHash1","name");
System.out.println(redisTemplate.opsForHash().entries("redisHash1"));
//Boolean putIfAbsent(H key, HK hashKey, HV value);
//僅當hashKey不存在時才設置散列hashKey的值。
System.out.println(redisTemplate.opsForHash().putIfAbsent("redisHash1","age",30));
System.out.println(redisTemplate.opsForHash().putIfAbsent("redisHash1","kkk","kkk"));
}
}
添加redis操作set數據結構 的類
package com.example.demo.config;
import javax.annotation.Resource;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/set")
public class TestSet {
/**
* Redis的Set是string類型的無序集合。集合成員是唯一的,這就意味着集合中不能出現重複的數據。
* Redis 中 集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是O(1)。
* public interface SetOperations<K,V>
* SetOperations提供了對無序集合的一系列操作:
*/
@Resource
private RedisTemplate<String, Object> redisTemplate;
@RequestMapping("/test")
public void TestSets(){
//Long add(K key, V... values);
//無序集合中添加元素,返回添加個數
//或者可以直接在add裏面添加多個值 如:template.opsForSet().add("setTest","123","456")
String[] strarrays = new String[]{"strarr1","sgtarr2","sgtarr3"};
System.out.println(redisTemplate.opsForSet().add("setTest", strarrays));
//Set<V> distinctRandomMembers(K key, long count);
//獲取多個key無序集合中的元素(去重),count表示個數
System.out.println("randomMembers:" + redisTemplate.opsForSet().distinctRandomMembers("setTest",5));
//List<V> randomMembers(K key, long count);
//獲取多個key無序集合中的元素(不去重),count表示個數
System.out.println("randomMembers:" + redisTemplate.opsForSet().randomMembers("setTest",5));
//Cursor<V> scan(K key, ScanOptions options);
//遍歷set
Cursor<Object> curosr = redisTemplate.opsForSet().scan("setTest", ScanOptions.NONE);
while(curosr.hasNext()){
System.out.println(curosr.next());
}
//V randomMember(K key);
//隨機獲取key無序集合中的一個元素
System.out.println("setTestrandomMember:" + redisTemplate.opsForSet().randomMember("setTest"));
System.out.println("setTestrandomMember:" + redisTemplate.opsForSet().randomMember("setTest"));
System.out.println("setTestrandomMember:" + redisTemplate.opsForSet().randomMember("setTest"));
System.out.println("setTestrandomMember:" + redisTemplate.opsForSet().randomMember("setTest"));
//Boolean move(K key, V value, K destKey);
//將 member 元素從 source 集合移動到 destination 集合
redisTemplate.opsForSet().move("setTest","strarr1","setTest2");
System.out.println(redisTemplate.opsForSet().members("setTest"));
System.out.println(redisTemplate.opsForSet().members("setTest2"));
//Boolean isMember(K key, Object o);
//判斷 member 元素是否是集合 key 的成員
System.out.println(redisTemplate.opsForSet().isMember("setTest","ccc"));
//Long size(K key);
//無序集合的大小長度
System.out.println(redisTemplate.opsForSet().size("setTest"));
//Set<V> members(K key);
//返回集合中的所有成員
System.out.println(redisTemplate.opsForSet().members("setTest"));
//V pop(K key);
//移除並返回集合中的一個隨機元素
System.out.println(redisTemplate.opsForSet().pop("setTest"));
System.out.println(redisTemplate.opsForSet().members("setTest"));
//Long remove(K key, Object... values);
//移除集合中一個或多個成員
String[] strarrays1 = new String[]{"strarr1","sgtarr2"};
System.out.println(redisTemplate.opsForSet().remove("setTest",strarrays1));
}
}
添加redis操作ZSet數據結構 的類:
package com.example.demo.config;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Redis有序集合和無序集合一樣也是string類型元素的集合,且不允許重複的成員。
*不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來爲集合中的成員進行從小到大的排序。
*有序集合的成員是唯一的,但分數(score)卻可以重複。
*/
@RestController
@RequestMapping("/zset")
public class TestZSet {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@RequestMapping("/test")
public void Zset(){
//Boolean add(K key, V value, double score);
//新增一個有序集合,存在的話爲false,不存在的話爲true
System.out.println(redisTemplate.opsForZSet().add("zset1","zset-1",1.0));
System.out.println(redisTemplate.opsForZSet().add("zset1","zset-2",3.0));
//Long add(K key, Set<TypedTuple<V>> tuples);
//新增一個有序集合 並返回添加個數
ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<Object>("zset-5",9.6);
ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<Object>("zset-6",9.9);
Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<ZSetOperations.TypedTuple<Object>>();
tuples.add(objectTypedTuple1);
tuples.add(objectTypedTuple2);
System.out.println(redisTemplate.opsForZSet().add("zset1",tuples));
System.out.println(redisTemplate.opsForZSet().range("zset1",0,-1));
//Cursor<TypedTuple<V>> scan(K key, ScanOptions options);
//遍歷zset
Cursor<ZSetOperations.TypedTuple<Object>> cursor = redisTemplate.opsForZSet().scan("zset1", ScanOptions.NONE);
while (cursor.hasNext()){
ZSetOperations.TypedTuple<Object> item = cursor.next();
System.out.println(item.getValue() + ":" + item.getScore());
}
//Long zCard(K key);
//獲取有序集合的成員個數
System.out.println(redisTemplate.opsForZSet().zCard("zset1"));
//Long size(K key);
//獲取有序集合的成員數,內部調用的就是zCard方法
System.out.println(redisTemplate.opsForZSet().size("zset1"));
//Long count(K key, double min, double max);
//通過分數返回有序集合指定區間內的成員個數
System.out.println(redisTemplate.opsForZSet().count("zset1",0,9.7));
//Double score(K key, Object o);
//獲取指定成員的score值
System.out.println("-oo-"+redisTemplate.opsForZSet().score("zset1","zset-2"));
//Double incrementScore(K key, V value, double delta);
//增加元素的score值,並返回增加後的值
System.out.println(redisTemplate.opsForZSet().incrementScore("zset1","zset-1",1.1)); //原爲1.1
//Long rank(K key, Object o);
//返回有序集中指定成員的排名,其中有序集成員按分數值遞增(從小到大)順序排列(從0開始) 如果沒有返回null
System.out.println(redisTemplate.opsForZSet().rank("zset1","zset-6"));
//Long reverseRank(K key, Object o);
//返回有序集中指定成員的排名,其中有序集成員按分數值遞減(從大到小)順序排列
System.out.println(redisTemplate.opsForZSet().reverseRank("zset1","zset-6"));
//Set<V> range(K key, long start, long end);
//通過索引區間返回有序集合成指定區間內的成員,其中有序集成員按分數值遞增(從小到大)順序排列
System.out.println(redisTemplate.opsForZSet().range("zset1",0,-1));
//Set<TypedTuple<V>> rangeWithScores(K key, long start, long end);
//通過索引區間返回有序集合成指定區間內的成員對象,其中有序集成員按分數值遞增(從小到大)順序排列
Set<ZSetOperations.TypedTuple<Object>> tuples1 = redisTemplate.opsForZSet().rangeWithScores("zset1",0,-1);
Iterator<ZSetOperations.TypedTuple<Object>> iterator = tuples1.iterator();
while (iterator.hasNext())
{
ZSetOperations.TypedTuple<Object> typedTuple = iterator.next();
System.out.println("value:" + typedTuple.getValue() + "score:" + typedTuple.getScore());
}
//Set<V> rangeByScore(K key, double min, double max);
//通過分數返回有序集合指定區間內的成員,其中有序集成員按分數值遞增(從小到大)順序排列
System.out.println(redisTemplate.opsForZSet().rangeByScore("zset1",0,5));
//Set<TypedTuple<V>> rangeByScoreWithScores(K key, double min, double max);
//通過分數返回有序集合指定區間內的成員對象,其中有序集成員按分數值遞增(從小到大)順序排列
Set<ZSetOperations.TypedTuple<Object>> tuples2 = redisTemplate.opsForZSet().rangeByScoreWithScores("zset1",0,5);
Iterator<ZSetOperations.TypedTuple<Object>> iterator2 = tuples2.iterator();
while (iterator2.hasNext())
{
ZSetOperations.TypedTuple<Object> typedTuple = iterator2.next();
System.out.println("value:" + typedTuple.getValue() + "score:" + typedTuple.getScore());
}
//Set<V> rangeByScore(K key, double min, double max, long offset, long count);
//通過分數返回有序集合指定區間內的成員,並在索引範圍內,其中有序集成員按分數值遞增(從小到大)順序排列
System.out.println(redisTemplate.opsForZSet().rangeByScore("zset1",0,5,1,2));
System.out.println(redisTemplate.opsForZSet().rangeByScore("zset1",0,5));
//Set<TypedTuple<V>> rangeByScoreWithScores(K key, double min, double max, long offset, long count);
//通過分數返回有序集合指定區間內的成員對象,並在索引範圍內,其中有序集成員按分數值遞增(從小到大)順序排列
Set<ZSetOperations.TypedTuple<Object>> tuples3 = redisTemplate.opsForZSet().rangeByScoreWithScores("zset1",0,5,1,2);
Iterator<ZSetOperations.TypedTuple<Object>> iterator3 = tuples3.iterator();
while (iterator3.hasNext())
{
ZSetOperations.TypedTuple<Object> typedTuple = iterator3.next();
System.out.println("value:" + typedTuple.getValue() + "score:" + typedTuple.getScore());
}
//Set<V> reverseRange(K key, long start, long end);
//通過索引區間返回有序集合成指定區間內的成員,其中有序集成員按分數值遞減(從大到小)順序排列
System.out.println(redisTemplate.opsForZSet().reverseRange("zset1",0,-1));
//Set<TypedTuple<V>> reverseRangeWithScores(K key, long start, long end);
//通過索引區間返回有序集合成指定區間內的成員對象,其中有序集成員按分數值遞減(從大到小)順序排列
Set<ZSetOperations.TypedTuple<Object>> tuples4 = redisTemplate.opsForZSet().reverseRangeWithScores("zset1",0,-1);
Iterator<ZSetOperations.TypedTuple<Object>> iterator4 = tuples4.iterator();
while (iterator4.hasNext())
{
ZSetOperations.TypedTuple<Object> typedTuple = iterator4.next();
System.out.println("value:" + typedTuple.getValue() + "score:" + typedTuple.getScore());
}
/*Set<V> reverseRangeByScore(K key, double min, double max);
與rangeByScore調用方法一樣,其中有序集成員按分數值遞減(從大到小)順序排列
Set<TypedTuple<V>> reverseRangeByScoreWithScores(K key, double min, double max);
與rangeByScoreWithScores調用方法一樣,其中有序集成員按分數值遞減(從大到小)順序排列
Set<V> reverseRangeByScore(K key, double min, double max, long offset, long count);
與rangeByScore調用方法一樣,其中有序集成員按分數值遞減(從大到小)順序排列
Set<TypedTuple<V>> reverseRangeByScoreWithScores(K key, double min, double max, long offset, long count);
與rangeByScoreWithScores調用方法一樣,其中有序集成員按分數值遞減(從大到小)順序排列*/
//Long remove(K key, Object... values);
//從有序集合中移除一個或者多個元素
System.out.println(redisTemplate.opsForZSet().remove("zset1","zset-6"));
System.out.println(redisTemplate.opsForZSet().range("zset1",0,-1));
//Long removeRange(K key, long start, long end);
//移除指定索引位置的成員,其中有序集成員按分數值遞增(從小到大)順序排列 如果key值不存在 返回0 代表一條也沒刪除
System.out.println(redisTemplate.opsForZSet().removeRange("zset1",1,2));
System.out.println(redisTemplate.opsForZSet().range("zset1",0,-1));
}
}
然後啓動項目 並訪問相應的路徑即可!!!
==================================================================
使用註解操作redis
註解緩存的使用
@Cacheable:在方法執行前Spring先查看緩存中是否有數據,如果有數據,則直接返回緩存數據;沒有則調用方法並將方法返回值放進緩存。
@CachePut:將方法的返回值放到緩存中。
@CacheEvict:刪除緩存中的數據。
package com.example.demo.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RedisController {
/* @Cacheable可以標記在一個方法上,也可以標記在一個類上。
* 當標記在一個方法上時表示該方法是支持緩存的,當標記在一個類上時則表示該類所有的方法都是
* 支持緩存的。對於一個支持緩存的方法,Spring會在其被調用後將其返回值緩存起來,以保證下次
* 利用同樣的參數來執行該方法時可以直接從緩存中獲取結果,而不需要再次執行該方法。Spring在
* 緩存方法的返回值時是以鍵值對進行緩存的,值就是方法的返回結果,至於鍵的話,Spring又支持
* 兩種策略,默認策略和自定義策略,這個稍後會進行說明。需要注意的是當一個支持緩存的方法在
* 對象內部被調用時是不會觸發緩存功能的。@Cacheable可以指定三個屬性,value、key和condition。
* */
/**
* @Cacheable 應用到讀取數據的方法上,先從緩存中讀取,如果沒有再從DB獲取數據,然後把數據添加到緩存中
* unless 表示條件表達式成立的話不放入緩存
*/
@RequestMapping("/item/{id}")
@Cacheable(value = "item")
public Item getItemById(@PathVariable int id) {
Item item = new Item();
item.setItemId(id);
item.setItemName("緩存1"+id);
return item;
}
/**
* @Cacheable 應用到讀取數據的方法上,先從緩存中讀取,如果沒有再從DB獲取數據,然後把數據添加到緩存中
* unless 表示條件表達式成立的話不放入緩存
*/
@RequestMapping("/item/all")
@Cacheable(value = "item")
public List<Item> getAllItem() {
Item item1 = new Item();
item1.setItemId(666);
item1.setItemName("緩存2"+666);
Item item2 = new Item();
item2.setItemId(999);
item2.setItemName("緩存3"+999);
List<Item> items=new ArrayList<Item>();
items.add(item1);
items.add(item2);
return items;
}
/**
* @CachePut 應用到寫數據的方法上,如新增/修改方法,調用方法時會自動把相應的數據放入緩存
* @param person
* @return
*/
@CachePut(value = "item" )
@RequestMapping("/item/{id}/update")
public Item updateItem(@PathVariable int id) {
Item item = new Item();
item.setItemId(id);
item.setItemName("緩存1"+id);
return item;
}
}
小技巧:
@Cacheable可以與@CachePut配合使用,通過@Cacheable添加數據並緩存到redis中 但如果數據庫修改而再一次查詢時 緩存的數據沒有修改會出現問題 如果數據修改時使用 @CachePut 就可以在修改後同時修改redis中的數據 這樣再一次查詢時就可以保持一致了(注意要保證兩者在redis中緩存的鍵一致 這樣改的纔是同一個數據)
**
本人只是爲了記錄自己的經歷,如果侵犯到您的權益 ,請與[email protected]聯繫
**