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中缓存的键一致 这样改的才是同一个数据)
**
本人只是为了记录自己的经历,如果侵犯到您的权益 ,请与1194821568@qq.com联系
**