Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作高性能的key-value数据库、缓存和消息中间件,掌握它是程序员的必备技能,下面是一个springboot访问redis的demo。
新建一个springboot项目,这里取名spring-boot-demo
项目结构目录如下
pom.xml文件内容

1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.carry</groupId> 8 <artifactId>spring-boot-demo</artifactId> 9 <version>0.0.1-SNAPSHOT</version> 10 <packaging>jar</packaging> 11 12 <name>spring-boot-demo</name> 13 <description>Demo project for Spring Boot</description> 14 15 <parent> 16 <groupId>org.springframework.boot</groupId> 17 <artifactId>spring-boot-starter-parent</artifactId> 18 <version>2.0.2.RELEASE</version> 19 <relativePath /> <!-- lookup parent from repository --> 20 </parent> 21 22 <properties> 23 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 24 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 25 <java.version>1.8</java.version> 26 <mybatis.version>1.3.2</mybatis.version> 27 </properties> 28 29 <dependencies> 30 <dependency> 31 <groupId>org.springframework.boot</groupId> 32 <artifactId>spring-boot-starter-data-redis</artifactId> 33 </dependency> 34 <dependency> 35 <groupId>org.springframework.boot</groupId> 36 <artifactId>spring-boot-starter-web</artifactId> 37 </dependency> 38 <dependency> 39 <groupId>org.mybatis.spring.boot</groupId> 40 <artifactId>mybatis-spring-boot-starter</artifactId> 41 <version>${mybatis.version}</version> 42 </dependency> 43 <dependency> 44 <groupId>org.apache.commons</groupId> 45 <artifactId>commons-pool2</artifactId> 46 </dependency> 47 <dependency> 48 <groupId>org.springframework.boot</groupId> 49 <artifactId>spring-boot-devtools</artifactId> 50 <scope>runtime</scope> 51 </dependency> 52 <dependency> 53 <groupId>mysql</groupId> 54 <artifactId>mysql-connector-java</artifactId> 55 <scope>runtime</scope> 56 </dependency> 57 <dependency> 58 <groupId>org.springframework.boot</groupId> 59 <artifactId>spring-boot-starter-test</artifactId> 60 <scope>test</scope> 61 </dependency> 62 </dependencies> 63 64 <build> 65 <plugins> 66 <plugin> 67 <groupId>org.springframework.boot</groupId> 68 <artifactId>spring-boot-maven-plugin</artifactId> 69 <configuration> 70 <fork>true</fork> 71 </configuration> 72 </plugin> 73 </plugins> 74 </build> 75 76 77 </project>
下面我们来配置redis,因为需要用到mysql数据库,这里使用mybatis访问
application.yml文件内容

1 #mybatis配置 2 mybatis: 3 mapper-locations: classpath:mapper/*Mapper.xml 4 type-aliases-package: com.carry.domain 5 #数据源 6 spring: 7 datasource: 8 url: jdbc:mysql://192.168.68.100:3306/test 9 driver-class-name: com.mysql.jdbc.Driver 10 username: root 11 password: 123456 12 #jackson时间格式化 13 jackson: 14 time-zone: GMT+8 15 date-format: yyyy-MM-dd HH:mm:ss 16 #redis配置 17 redis: 18 cluster: 19 nodes: 192.168.68.100:7000,192.168.68.100:7001,192.168.68.101:7000,192.168.68.101:7001,192.168.68.102:7000,192.168.68.102:7001 20 timeout: 6000ms 21 password: 123456 22 lettuce: 23 pool: 24 max-active: 8 25 max-wait: -1ms 26 max-idle: 8 27 min-idle: 0 28 database: 0
新建文件RedisConfig.java,内容如下

1 package com.carry.config; 2 3 import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 import com.fasterxml.jackson.annotation.PropertyAccessor; 5 import com.fasterxml.jackson.databind.ObjectMapper; 6 import org.springframework.boot.autoconfigure.AutoConfigureAfter; 7 import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.context.annotation.Configuration; 10 import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; 11 import org.springframework.data.redis.core.RedisTemplate; 12 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 13 14 @Configuration 15 @AutoConfigureAfter(RedisAutoConfiguration.class) 16 public class RedisConfig { 17 18 @Bean 19 public RedisTemplate<String, Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) { 20 //redis序列化器 21 Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); 22 ObjectMapper om = new ObjectMapper(); 23 om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 24 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 25 jackson2JsonRedisSerializer.setObjectMapper(om); 26 RedisTemplate<String, Object> template = new RedisTemplate<>(); 27 template.setConnectionFactory(redisConnectionFactory); 28 template.setKeySerializer(jackson2JsonRedisSerializer); 29 template.setValueSerializer(jackson2JsonRedisSerializer); 30 template.setHashKeySerializer(jackson2JsonRedisSerializer); 31 template.setHashValueSerializer(jackson2JsonRedisSerializer); 32 return template; 33 } 34 }
最后在项目启动类SpringBootDemoApplication上加上注解@EnableCaching开启缓存
配置至此结束,下面我们来通过代码来访问redis集群
先写一个访问mysql的mapper,其中只包含一个方法List<User> findAll();
对应SQL语句为select * from user
User实体类跟user表字段一一对应
UserServiceImpl代码内容

1 package com.carry.service.impl; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.cache.annotation.Cacheable; 7 import org.springframework.stereotype.Service; 8 9 import com.carry.domain.User; 10 import com.carry.mapper.UserMapper; 11 import com.carry.service.UserService; 12 13 @Service 14 public class UserServiceImpl implements UserService { 15 16 @Autowired 17 private UserMapper userMapper; 18 19 @Cacheable(value = "findAll", key = "'test'") 20 public List<User> findAll() { 21 System.out.println("如果没打印这句话,说明走了缓存!"); 22 return userMapper.findAll(); 23 } 24 }
UserController代码内容

1 package com.carry.controller; 2 3 import java.util.List; 4 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.web.bind.annotation.GetMapping; 7 import org.springframework.web.bind.annotation.RestController; 8 9 import com.carry.domain.User; 10 import com.carry.service.UserService; 11 12 @RestController 13 public class UserController { 14 15 @Autowired 16 private UserService userService; 17 18 @GetMapping("/getUsers") 19 public List<User> getUsers(){ 20 return userService.findAll(); 21 } 22 23 }
最后启动项目在浏览器中访问http://localhost:8080/getUsers
第一次访问控制台输出“如果没打印这句话,说明走了缓存!”
再次访问控制台则没有输出。
我们通过redis-cli连接redis会发现key值是一个很奇怪的值
其实就是我们在@Cacheable注解配的值拼起来的
需要注意的是key的值需要用单引号''引起来不然会报错
最后写了几个test case,读者自己去运行看看控制台会输出什么

1 package com.carry; 2 3 import java.util.Date; 4 import java.util.HashSet; 5 import java.util.List; 6 import java.util.Map; 7 import java.util.Set; 8 import java.util.concurrent.ExecutorService; 9 import java.util.concurrent.Executors; 10 import java.util.stream.IntStream; 11 12 import org.junit.Test; 13 import org.junit.runner.RunWith; 14 import org.slf4j.Logger; 15 import org.slf4j.LoggerFactory; 16 import org.springframework.beans.factory.annotation.Autowired; 17 import org.springframework.boot.test.context.SpringBootTest; 18 import org.springframework.data.redis.core.Cursor; 19 import org.springframework.data.redis.core.DefaultTypedTuple; 20 import org.springframework.data.redis.core.HashOperations; 21 import org.springframework.data.redis.core.ListOperations; 22 import org.springframework.data.redis.core.RedisTemplate; 23 import org.springframework.data.redis.core.ScanOptions; 24 import org.springframework.data.redis.core.SetOperations; 25 import org.springframework.data.redis.core.StringRedisTemplate; 26 import org.springframework.data.redis.core.ValueOperations; 27 import org.springframework.data.redis.core.ZSetOperations; 28 import org.springframework.test.context.junit4.SpringRunner; 29 30 import com.carry.domain.User; 31 32 @RunWith(SpringRunner.class) 33 @SpringBootTest 34 public class SpringBootDemoApplicationTests { 35 36 private static final Logger log = LoggerFactory.getLogger(SpringBootDemoApplicationTests.class); 37 38 39 @Autowired 40 private StringRedisTemplate stringRedisTemplate; 41 42 @Autowired 43 private RedisTemplate<String, Object> redisCacheTemplate; 44 45 46 @Test 47 public void redisTest() { 48 ExecutorService executorService = Executors.newFixedThreadPool(1000); 49 IntStream.range(0, 1000).forEach(i -> 50 executorService.execute(() -> stringRedisTemplate.opsForValue().increment("kk", 1)) 51 ); 52 } 53 54 @Test 55 public void redisTestString() { 56 stringRedisTemplate.opsForValue().set("carry", "chan"); 57 final String v1 = stringRedisTemplate.opsForValue().get("carry"); 58 log.info("[字符缓存结果] - [{}]", v1); 59 } 60 61 @Test 62 public void redisTestObject() { 63 //以下只演示整合,具体Redis命令可以参考官方文档,Spring Data Redis 只是改了个名字而已,Redis支持的命令它都支持 64 String key = "carry:user:1"; 65 ValueOperations<String, Object> valueOperations = redisCacheTemplate.opsForValue(); 66 valueOperations.set(key, new User(1, "carry", new Date(), "longhua")); 67 //对应 String(字符串) 68 final User user = (User) valueOperations.get(key); 69 log.info("[对象缓存结果] - [{}]", user); 70 } 71 72 @Test 73 public void redisTestList() { 74 ListOperations<String, Object> listOperations = redisCacheTemplate.opsForList(); 75 listOperations.trim("key1", 1, 0); 76 List<Object> list = listOperations.range("key1", 0, -1); 77 log.info("[对象缓存结果] - {}", list); 78 listOperations.leftPush("key1", 1); 79 listOperations.leftPush("key1", 2); 80 listOperations.rightPush("key1", 3); 81 list = listOperations.range("key1", 0, -1); 82 log.info("[对象缓存结果] - {}", list); 83 } 84 85 @Test 86 public void redisTestHash() { 87 HashOperations<String, Object, Object> hashOperations = redisCacheTemplate.opsForHash(); 88 hashOperations.put("hkey", "k1", "v1"); 89 hashOperations.put("hkey", "k2", "v2"); 90 hashOperations.put("hkey", "k3", "v3"); 91 Map<Object, Object> map = hashOperations.entries("hkey"); 92 log.info("[对象缓存结果] - [{}]", map); 93 } 94 95 @Test 96 public void redisTestSet() { 97 SetOperations<String, Object> setOperations = redisCacheTemplate.opsForSet(); 98 setOperations.add("skey", "v1", "v2", "v3", "v4"); 99 Cursor<Object> cursor = setOperations.scan("skey", ScanOptions.NONE); 100 while (cursor.hasNext()) { 101 System.out.println(cursor.next()); 102 } 103 log.info("[对象缓存结果] - [{}]", cursor); 104 } 105 106 @Test 107 public void redisTestZSet() { 108 ZSetOperations<String, Object> zSetOperations = redisCacheTemplate.opsForZSet(); 109 ZSetOperations.TypedTuple<Object> tuple1 = new DefaultTypedTuple<>("v1", 9.6); 110 ZSetOperations.TypedTuple<Object> tuple2 = new DefaultTypedTuple<>("v2", 9.9); 111 Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>(); 112 tuples.add(tuple1); 113 tuples.add(tuple2); 114 zSetOperations.add("zkey", tuples); 115 Set<Object> set = zSetOperations.range("zkey", 0, -1); 116 log.info("[对象缓存结果] - {}", set); 117 } 118 }