1. 简介

Redis是一个基于内存的数据结构存储系统,它可以用作数据库或者缓存。它支持多种类型的数据
结构,这些数据结构类型分别为String(字符串)、List(列表)、Set(集合)、Hash(散列)和
Zset(有序集合)。

配置连接工厂 -> 配置模板 -> 使用接口

SpringDataRedis 提供的连接工厂:

  1. JedisConnectionFactory
  2. JredisConnectionFactory
  3. LettuceConnectionFactory
  4. SrpConnectionFactory

与其他的Spring Data项目类似,Spring Data Redis以模板的形式提供了较高等级的数据访问方案。实际上,Spring Data Redis提供了两个模板:

  • RedisTemplate
  • StringRedisTemplate


SpringData Redis的作用是通过一段简单的配置即可访问redis服务,它的底层是对java提供的
redis开发包(比如jedis等)进行了高度封装,主要提供了如下功能:

  • 连接池自动管理,提供了一个高度封装的RedisTemplate类,基于这个类的对象可以对redis进行各
    种操作
  • 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
    • ValueOperations:简单字符串类型数据操作
    • SetOperations:set类型数据操作
    • ZSetOperations:zset类型数据操作
    • HashOperations:map类型的数据操作
    • ListOperations:list类型的数据操作

RedisTemplate的很多功能是以子API的形式提供的,它们区分了单个值和集合值的场景
image.png


2. 入门案例

2.1 引入坐标

pom.xml 文件中引入

  1. <dependency>
  2. <groupId>org.springframework.data</groupId>
  3. <artifactId>spring-data-redis</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>redis.clients</groupId>
  7. <artifactId>jedis</artifactId>
  8. </dependency>

2.2 配置文件(注解方式)

tips:

  • JedisConnectionFactory 要配置 RedisStandaloneConfiguration 对象和 JedisClientConfiguration

image.png

RedisConfig.java

  1. @Configuration
  2. public class RedisConfig {
  3. @Value("${spring.redis.host}")
  4. private String host;
  5. @Value("${spring.redis.port}")
  6. private int port;
  7. @Value("${spring.redis.password}")
  8. private String password;
  9. @Bean
  10. public JedisPoolConfig jedisPoolConfig() {
  11. JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
  12. // 最大空闲数
  13. jedisPoolConfig.setMaxIdle(300);
  14. // 在提取一个jedis实例时,是否提前进行验证操作;如果为true,则得到的jedis实例均是可用的
  15. jedisPoolConfig.setTestOnBorrow(false);
  16. return jedisPoolConfig;
  17. }
  18. @Bean
  19. public RedisStandaloneConfiguration redisStandaloneConfiguration() {
  20. RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
  21. configuration.setHostName(host);
  22. configuration.setPassword(password);
  23. configuration.setPort(port);
  24. return configuration;
  25. }
  26. @Bean
  27. public JedisClientConfiguration clientConfiguration() {
  28. JedisClientConfiguration.JedisClientConfigurationBuilder builder = JedisClientConfiguration.builder();
  29. return builder.usePooling()
  30. .poolConfig(jedisPoolConfig())
  31. .build();
  32. }
  33. @Bean
  34. public JedisConnectionFactory jedisConnectionFactory() {
  35. return new JedisConnectionFactory(redisStandaloneConfiguration(), clientConfiguration());
  36. }
  37. @Bean
  38. public RedisTemplate redisTemplate() {
  39. // 注意这里使用的是StringRedisTempalte
  40. StringRedisTemplate template = new StringRedisTemplate(jedisConnectionFactory());
  41. GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
  42. // 设置值的序列化器
  43. template.setValueSerializer(jackson2JsonRedisSerializer);
  44. return template;
  45. }
  46. }

application.yml

  1. spring:
  2. redis:
  3. port: 6379
  4. password: qazwsx123!@#
  5. host: 1.117.30.61

2.3 常见操作

在Redis中有五种常见类型,SpringData Redis对每一种数据类型都提供了一个xxxOperations的API,他们
分别是:

  • ValueOperations valueOps;
  • ListOperations listOps;
  • SetOperations setOps;
  • ZSetOperations zSetOps;
  • HashOperations hashOps;

2.3.1 ValueOperations

  1. @SpringBootTest
  2. public class RedisStringTest {
  3. @Autowired
  4. private RedisTemplate redisTemplate;
  5. ValueOperations<String, String> operations = null;
  6. @Before
  7. public void init() {
  8. redisTemplate.setKeySerializer(new StringRedisSerializer());
  9. redisTemplate.setValueSerializer(new StringRedisSerializer());
  10. operations = redisTemplate.opsForValue();
  11. }
  12. @Test
  13. public void testSet() {
  14. //向数据库中保存name--heima
  15. //operations.set("name","heima");
  16. //相关数据库保存name1--heima1 有效时间为10s
  17. //operations.set("name1", "heima1", 10, TimeUnit.SECONDS);
  18. //替换 heima ---> heXXa offset 索引位置是从0开始
  19. //operations.set("name", "XX", 2);
  20. //当key不存在的时候,执行保存操作;当key存在的时候,什么都不做
  21. //operations.setIfAbsent("name1","heima");
  22. //批量保存
  23. // Map map = new HashMap();
  24. // map.put("name2", "heima2");
  25. // map.put("name3", "heima3");
  26. // map.put("name4", "heima4");
  27. //
  28. // operations.multiSet(map);
  29. //追加 当key存在时,会执行追加操作;当key不存在时,会执行保存操作
  30. operations.append("name5", "Heima");
  31. }
  32. @Test
  33. public void testGet() {
  34. //根据key获取value
  35. /* String value = operations.get("name");
  36. System.out.println(value);//heXXaHeima*/
  37. //首先根据key获取value,然后再根据value进行截取,从start位置截取到end位置[包含start和end]
  38. /* String value2 = operations.get("name", 5, 7);
  39. System.out.println(value2);//heXXaHeima-->Hei*/
  40. //批量获取
  41. // List<String> keys = new ArrayList<>();
  42. // keys.add("name2");
  43. // keys.add("name3");
  44. // keys.add("name4");
  45. // List<String> values = operations.multiGet(keys);
  46. // for (String s : values) {
  47. // System.out.println(s);
  48. // }
  49. //根据key获取value的长度
  50. Long size = operations.size("name");
  51. System.out.println(size);
  52. }
  53. //自增
  54. @Test
  55. public void testIncrement() {
  56. operations.set("age", "18");
  57. operations.increment("age");//自增1--->19
  58. System.out.println(operations.get("age"));
  59. operations.increment("age", 5);//自增5
  60. System.out.println(operations.get("age"));//---->24
  61. //自减
  62. //operations.decrement("age")
  63. }
  64. //删除
  65. @Test
  66. public void testDelete() {
  67. //单个删除
  68. redisTemplate.delete("name");
  69. List<String> keys = new ArrayList<>();
  70. keys.add("name2");
  71. keys.add("name3");
  72. keys.add("name4");
  73. //批量删除
  74. redisTemplate.delete(keys);
  75. }
  76. }

2.3.2 ListOperations

  1. public class RedisListTest {
  2. @Autowired
  3. private RedisTemplate redisTemplate;
  4. ListOperations<String, String> operations = null;
  5. @Before
  6. public void init() {
  7. redisTemplate.setKeySerializer(new StringRedisSerializer());
  8. redisTemplate.setValueSerializer(new StringRedisSerializer());
  9. operations = redisTemplate.opsForList();
  10. }
  11. //增加
  12. @Test
  13. public void testAdd() {
  14. //从左边添加一个元素
  15. operations.leftPush("students", "zhangsan");
  16. //从左边添加多个元素
  17. operations.leftPushAll("students", "lisi", "wangwu", "zhaoliu");
  18. //从右边添加一个元素
  19. operations.rightPush("students", "zhangsan1");
  20. //从右边添加多个元素
  21. operations.rightPushAll("students", "lisi", "wangwu", "zhaoliu");
  22. }
  23. //查询
  24. @Test
  25. public void testFind() {
  26. //根据key和索引进行查询
  27. //0和正数代表从左边开始 0 1 2
  28. //负数代表从右边开始 -1 -2 -3
  29. String student = operations.index("students", 1);
  30. System.out.println(student);
  31. String student1 = operations.index("students", -2);
  32. System.out.println(student1);
  33. //范围查询
  34. //根据key [start,end] 包括首尾
  35. List<String> students = operations.range("students", 0, 2);
  36. for (String s : students) {
  37. System.out.println(s);
  38. }
  39. }
  40. //删除
  41. @Test
  42. public void testRemove(){
  43. //从左边删除第一个元素
  44. //String s = operations.leftPop("students");
  45. //从右边删除第一个元素
  46. //operations.rightPop("students");
  47. // count > 0:删除左边起第几个等于指定值的元素
  48. // count < 0:删除右边起第几个等于指定值的元素
  49. // count = 0:删除所有等于value的元素。
  50. //删除左边起第二个wangwu
  51. operations.remove("students",2,"wangwu");
  52. }
  53. }

2.3.3 SetOperations

  1. public class RedisSetTest {
  2. @Autowired
  3. private RedisTemplate redisTemplate;
  4. SetOperations<String, String> operations = null;
  5. @Before
  6. public void init() {
  7. redisTemplate.setKeySerializer(new StringRedisSerializer());
  8. redisTemplate.setValueSerializer(new StringRedisSerializer());
  9. operations = redisTemplate.opsForSet();
  10. }
  11. //增加
  12. @Test
  13. public void testAdd() {
  14. operations.add("students","zhangsan","lisi","wangwu","zhangsan");
  15. }
  16. //查询
  17. @Test
  18. public void testFind() {
  19. //查询所有元素
  20. /* Set<String> students = operations.members("students");
  21. for (String student : students) {
  22. System.out.println(student);
  23. }*/
  24. //随机获取一个元素
  25. /* String student = operations.randomMember("students");
  26. System.out.println(student);*/
  27. //随机多个元素[可能会重复]
  28. List<String> stus = operations.randomMembers("students", 2);
  29. for (String stu : stus) {
  30. System.out.println(stu);
  31. }
  32. }
  33. //删除
  34. @Test
  35. public void testRemove() {
  36. //移除元素,并返回移除成功个数
  37. Long count = operations.remove("students", "zhangsan", "wangwu","sunliu");
  38. System.out.println(count);
  39. //随机移除指定集合中的多少个元素
  40. List<String> students = operations.pop("students", 2);
  41. for (String student : students) {
  42. System.out.println(student);
  43. }
  44. }
  45. //多集合操作
  46. @Test
  47. public void testMoreSet(){
  48. operations.add("names1", "zhangsan", "li", "wangwu");
  49. operations.add("names2", "zhangsan", "li", "zhaoliu");
  50. //取交集
  51. /* Set<String> sets1 = operations.intersect("names1", "names2");
  52. for (String s : sets1) {
  53. System.out.println(s);
  54. }*/
  55. //取并集
  56. /* Set<String> sets2 = operations.union("names1", "names2");
  57. for (String s : sets2) {
  58. System.out.println(s);
  59. }*/
  60. //取差集[第一个集合中存在,但是在第二个集合中不存在的元素]
  61. Set<String> sets3 = operations.difference("names2", "names1");
  62. for (String s : sets3) {
  63. System.out.println(s);
  64. }
  65. }
  66. }

2.3.4 ZSetOperations

  1. public class RedisZSetTest {
  2. @Autowired
  3. private RedisTemplate redisTemplate;
  4. ZSetOperations<String, String> operations = null;
  5. @Before
  6. public void init() {
  7. redisTemplate.setKeySerializer(new StringRedisSerializer());
  8. redisTemplate.setValueSerializer(new StringRedisSerializer());
  9. operations = redisTemplate.opsForZSet();
  10. }
  11. //增加
  12. @Test
  13. public void testAdd() {
  14. operations.add("students", "zhangsan", 100);
  15. operations.add("students", "lisi", 60);
  16. operations.add("students", "wangwu", 80);
  17. }
  18. //分数的增减
  19. @Test
  20. public void testScore() {
  21. //incrementScore 可以用来增减分数 增加就用正数 减少用负数
  22. //增加分数
  23. operations.incrementScore("students", "wangwu", 30);
  24. //减少分数
  25. operations.incrementScore("students", "wangwu", -70);
  26. }
  27. //查询一个元素的信息
  28. @Test
  29. public void testFindOne() {
  30. //查询一个元素的分数
  31. Double score = operations.score("students", "wangwu");
  32. System.out.println(score);
  33. //查询一个元素在集合中的排名 排名从0开始
  34. Long rank = operations.rank("students", "zhangsan");
  35. System.out.println(rank);
  36. }
  37. //根据一个区间获得一个列表
  38. @Test
  39. public void testFindList() {
  40. //根据排名区间来获取元素列表
  41. Set<String> students = operations.range("students", 0, 2);
  42. for (String student : students) {
  43. System.out.println(student);
  44. }
  45. System.out.println("=============");
  46. Set<ZSetOperations.TypedTuple<String>> set = operations.rangeWithScores("students", 0, 2);
  47. for (ZSetOperations.TypedTuple<String> tuple : set) {
  48. System.out.println(tuple.getValue() + "同学,得了" + tuple.getScore() + "分");
  49. }
  50. System.out.println("---------------------------------");
  51. //根据分数区间来获取列表
  52. Set<String> students2 = operations.rangeByScore("students", 60, 90);
  53. for (String student : students2) {
  54. System.out.println(student);
  55. }
  56. System.out.println("=============");
  57. Set<ZSetOperations.TypedTuple<String>> set2 = operations.rangeByScoreWithScores("students", 60, 90);
  58. for (ZSetOperations.TypedTuple<String> tuple : set2) {
  59. System.out.println(tuple.getValue() + "同学,得了" + tuple.getScore() + "分");
  60. }
  61. }
  62. //统计
  63. @Test
  64. public void testCount() {
  65. //统计一个集合中元素
  66. Long zCard = operations.zCard("students");
  67. System.out.println(zCard);
  68. //根据一个分数区间统计元素数量
  69. Long count = operations.count("students", 50, 100);
  70. System.out.println(count);
  71. }
  72. //删除
  73. @Test
  74. public void testRemove() {
  75. //根据key-value删除 value允许传入多个
  76. //operations.remove("students","zhangsan","lisi");
  77. //根据排名区间删除
  78. //operations.removeRange("students", 0, 1);
  79. //根据分数区间删除
  80. operations.removeRangeByScore("students", 70, 100);
  81. }
  82. }

2.3.5 HashOperations

  1. public class RedisHashTest {
  2. @Autowired
  3. private RedisTemplate redisTemplate;
  4. HashOperations<String, String, Article> operations = null;
  5. @Before
  6. public void init() {
  7. redisTemplate.setKeySerializer(new StringRedisSerializer());
  8. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
  9. redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
  10. operations = redisTemplate.opsForHash();
  11. }
  12. //保存
  13. @Test
  14. public void testPut() {
  15. Article article = new Article();
  16. article.setTitle("黑马");
  17. article.setAuthor("黑马程序员");
  18. article.setCreateTime(new Date());
  19. operations.put("article", "3", article);
  20. }
  21. //获取
  22. @Test
  23. public void testGet() {
  24. //判断hashkey是否存在
  25. Boolean flag = operations.hasKey("article", "3");
  26. System.out.println(flag);
  27. //根据key和hashkay获取操作
  28. Article article = operations.get("article", "2");
  29. System.out.println(article);
  30. //根据key获取所有的hashkey
  31. Set<String> set = operations.keys("article");
  32. for (String s : set) {
  33. System.out.println(s);
  34. }
  35. List<Article> articles = operations.values("article");
  36. for (Article art : articles) {
  37. System.out.println(art);
  38. }
  39. Map<String, Article> map = operations.entries("article");
  40. for (Map.Entry<String, Article> entry : map.entrySet()) {
  41. System.out.println(entry.getKey() + ":" + entry.getValue());
  42. }
  43. }
  44. //删除
  45. @Test
  46. public void testDelete() {
  47. //当hash中的数据全部被删除后,整个hash就没了
  48. operations.delete("article", "2", "3");
  49. }
  50. }

参考

  1. Redis学习之Spring-data-redis使用