了解Java中Redis作为缓存如何使用
目的: 了解Java中Redis作为缓存如何使用参考: https://www.cnblogs.com/jinbuqi/p/11038731.html
使用: 1.准备redis环境 1.下载 下载地址:https://github.com/MicrosoftArchive/redis/releases
版本3.0.503.zip
2.解压到指定位置
3.启动redis服务器: 解压目录中新建文件startup.cmd,内容为:redis-server redis.windows.conf
启动redis服务器:双击startup.cmd
4.测试 打开同一个文件夹下的 redis-cli.exe 输入测试语句
结果:
2.java中使用 1.项目环境 我的环境 idea:2018.3.3 jdk:1.8.0_131 idea新建springboot项目
maven添加jar包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <!--注释掉,开启junit--> <!--<scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions>--> </dependency> <!--Web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--json包--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- log --> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>
2.添加配置文件 application.properties中添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # REDIS (RedisProperties) # Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=localhost # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=0
新建log4j.properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 log4j.rootLogger=CONSOLE,FILE log4j.addivity.org.apache=true # 应用于控制台 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.Threshold=INFO log4j.appender.CONSOLE.Target=System.out log4j.appender.CONSOLE.Encoding=UTF-8 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n # 每天新建日志 log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender log4j.appender.A1.File=D:/log4j/log log4j.appender.A1.Encoding=UTF-8 log4j.appender.A1.Threshold=DEBUG log4j.appender.A1.DatePattern='.'yyyy-MM-dd log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%n #应用于文件 log4j.appender.FILE=org.apache.log4j.FileAppender log4j.appender.FILE.File=E:/log4j/file.log log4j.appender.FILE.Append=false log4j.appender.FILE.Encoding=UTF-8 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
3.包结构
4.配置Redis 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 /** * Description: redis配置 配置序列化方式以及缓存管理器 * * @author hxr * @version 1.0 */ @EnableCaching//开启以注解方式使用缓存。 @Configuration//这是一个配置类 @AutoConfigureAfter(RedisAutoConfiguration.class) public class RedisConfig { /** * Description: json序列化 */ @Bean public RedisSerializer<Object> jackson2JsonRedisSerializer() { //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); return serializer; } /** * Description:配置自定义redisTemplate * * @param connectionFactory * @return */ @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){ RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setValueSerializer(jackson2JsonRedisSerializer()); //使用StringRedisSerializer来序列化和反序列化redis的key值 template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(jackson2JsonRedisSerializer()); template.afterPropertiesSet(); return template; } /** * 配置缓存管理器 * @param redisConnectionFactory * @return */ @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { // 生成一个默认配置,通过config对象即可对缓存进行自定义配置 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 设置缓存的默认过期时间,也是使用Duration设置 config = config.entryTtl(Duration.ofMinutes(1)) // 设置 key为string序列化 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // 设置value为json序列化 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer())) // 不缓存空值 .disableCachingNullValues(); // 设置一个初始化的缓存空间set集合 Set<String> cacheNames = new HashSet<>(); cacheNames.add("timeGroup"); cacheNames.add("user"); // 对每个缓存空间应用不同的配置 Map<String, RedisCacheConfiguration> configMap = new HashMap<>(); configMap.put("timeGroup", config); configMap.put("user", config.entryTtl(Duration.ofSeconds(120))); // 使用自定义的缓存配置初始化一个cacheManager RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory) // 一定要先调用该方法设置初始化的缓存名,再初始化相关的配置 .initialCacheNames(cacheNames) .withInitialCacheConfigurations(configMap) .build(); return cacheManager; } /** * 缓存的key是 包名+方法名+参数列表 */ @Bean public KeyGenerator keyGenerator() { return (target, method, objects) -> { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append("::" + method.getName() + ":"); for (Object obj : objects) { sb.append(obj.toString()); } return sb.toString(); }; } }
5.实体类pojo 使用了lombok
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.xiaoruiit.redis_cache.pojo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; /** * Description: * * @author hxr * @version 1.0 */ @Data @NoArgsConstructor //无参构造 @AllArgsConstructor //有参构造 public class User { private long id; private String nickname; private String mobile; @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)//在输出的Json数据中隐藏密码,只能输入不输出 private String password; private String role; }
6.Controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 /** * Description: * * @author hxr * @version 1.0 */ @RestController @EnableAutoConfiguration @RequestMapping("/user") public class UserController { @Resource private UserService userService; @Resource private RedisTemplate<String, Object> redis; @RequestMapping(value = "{id}", method = RequestMethod.GET, produces = "application/json") public User getUserById(@PathVariable long id){ User user = userService.getUserById(id); return user; } @RequestMapping(value = "{id}/change-nick", method = RequestMethod.POST, produces = "application/json") public User updateNickname(@PathVariable long id) throws Exception{ String nickname = "ww-" + Math.random(); User user = userService.updateUserNickname(id, nickname); return user; } @RequestMapping(value = "{id}/change-nick", method = RequestMethod.POST, produces = "application/json") public User updateMobile(@PathVariable long id) throws Exception{ String mobile = "134" + Math.random(); User user = userService.updateUserNickname(id, mobile); return user; } // 使用RedisTemplate访问redis服务器 @RequestMapping(value="/redis", method=RequestMethod.GET, produces="application/json") public String redis() throws Exception { // 设置键"key",值"value" redis.opsForValue().set("key", "value"); String value = (String) redis.opsForValue().get("key"); return value; } }
7.Service + ServiceImpl
@Cacheable - 表明对应方法的返回结果可以被缓存,首次调用后,下次就从缓存中读取结果,方法不会再被执行了。
@CachePut - 更新缓存,方法每次都会执行
@CacheEvict - 清除缓存,方法每次都会执行
Service
1 2 3 4 5 6 7 8 9 10 11 12 /** * Description: * * @author hxr * @version 1.0 */ public interface UserService { public User getUserById(long userId); public User updateUserNickname(long userId, String nickname); public User updateUserMobile(long userId, String mobile); }
ServiceImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 /** * Description: * * @author hxr * @version 1.0 */ @Service public class UserServiceImpl implements UserService { private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class); private User user = new User(11, "zs", "13400000000", "123456", "admin"); @Cacheable(value = "user", key = "#userId") //表明对应方法的返回结果可以被缓存,首次调用后,下次就从缓存中读取结果,可以查到时,方法不会被执行。 @Override public User getUserById(long userId) { log.info("加载user"); return user; } @CacheEvict(value = "user", key= "#userId") //清除缓存,方法每次都会执行 @Override public User updateUserNickname(long userId, String nickname) { log.info("修改名字,清除缓存"); user.setNickname(nickname); return user; } @CachePut(value = "user", key= "#userId") //更新缓存,方法每次都会执行 @Override public User updateUserMobile(long userId, String mobile) { log.info("修改手机,更新缓存"); user.setMobile(mobile); return user; } }
8.启动redis监控 进入redis安装目录,双击redis-cli.exe,输入monitor
9.APIPost测试q 启动springboot项目,打开Apipost
1.@Cacheable测试 发送请求,查看redis监控器中的变化
再发送三次
加载user只打印了一次,方法内部只执行了一次
2.@CacheEvict测试 发送两次请求
3.CachePut测试 发送两次请求