Jedis Jedis是官网推荐的Java连接工具,类似就是在Java和Redis中增加一层辅助层,辅助你用Java使用Redis。
简单的测试一下使用。
首先创建一个maven项目,导入相关的依赖。
1 2 3 4 5 6 <dependency > <groupId > redis.clients</groupId > <artifactId > jedis</artifactId > <version > 3.5.1</version > </dependency >
连接使用Redis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.yww;import redis.clients.jedis.Jedis;public class config { public static void main (String[] args) { Jedis jedis = new Jedis("127.0.0.1" , 6379 ); System.out.println(jedis.ping()); jedis.close(); } }
事务的使用。
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 package com.yww;import redis.clients.jedis.Jedis;import redis.clients.jedis.Transaction;public class config { public static void main (String[] args) { Jedis jedis = new Jedis("127.0.0.1" , 6379 ); Transaction multi = jedis.multi(); try { multi.exec(); } catch (Exception e) { multi.discard(); e.printStackTrace(); } finally { jedis.close(); } } }
Lettuce 整合就先创建一个SpringBoot的项目,导入SpringData项目的redis依赖。
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > <version > 2.4.2</version > </dependency >
在比较新的SpringBoot版本中,放弃了Jedis对redis的直接连接,因为多个线程会出现线程不安全的情况,所以官方已经替换成了lettuce。 lettuce采用netty,实例可以在多个线程中进行共享,减少线程数量,不存在线程不安全的情况。
在配置文件中,配置Redis的连接。
1 2 3 spring.redis.host =127.0.0.1 spring.redis.port =6379
简单的测试。
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 package com.yww;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.core.RedisTemplate;@SpringBootTest class RedisTestApplicationTests { @Autowired private RedisTemplate redisTemplate; @Test void contextLoads () { redisTemplate.opsForValue().set("name" ,"yww" ); System.out.println(redisTemplate.opsForValue().get("name" )); RedisConnection connection = redisTemplate.getConnectionFactory().getConnection(); connection.flushDb(); } }
上述的测试其实是没有经过序列化的,这是一个很不安全的操作,特别是传输对象的时候,没有序列化就会报错。
先简单的创建一个对象来测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.yww;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.stereotype.Component;@Component @AllArgsConstructor @NoArgsConstructor @Data public class User implements Serializable { private String name; private int age; }
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.yww;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.RedisTemplate;@SpringBootTest class RedisTestApplicationTests { @Autowired private RedisTemplate redisTemplate; @Test void contextLoads () throws JsonProcessingException { User user = new User("yww" , 20 ); String json = new ObjectMapper().writeValueAsString(user); redisTemplate.opsForValue().set("user" ,json); System.out.println(redisTemplate.opsForValue().get("user" )); } }
默认是会使用jdk的序列化方式,在后期使用会出现一些麻烦,所以开发中一般会自己定义RedisTemplate的序列化方式,所以就需要自己定义一个RedisTemplate来使用。
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 @EnableCaching @Configuration public class RedisConfig extends CachingConfigurationSelector { @Bean @SuppressWarnings(value = { "unchecked", "rawtypes", "deprecation" }) public RedisTemplate<Object, Object> redisTemplate (RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(mapper); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean @SuppressWarnings(value = { "unchecked", "rawtypes" }) public CacheManager cacheManager (RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); jackson2JsonRedisSerializer.setObjectMapper(om); RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600 )) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); return RedisCacheManager.builder(factory).cacheDefaults(config).build(); } }
测试。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @SpringBootTest class RedisTestApplicationTests { @Autowired @Qualifier("redisTemplate") private RedisTemplate redisTemplate; @Test void contextLoads () throws JsonProcessingException { User user = new User("yww" , 20 ); redisTemplate.opsForValue().set("user" ,json); System.out.println(redisTemplate.opsForValue().get("user" )); } }
使用注解 注解的使用会更加方便的为接口返回的数据添加到缓存里。
Cacheable 这个注解有几个参数。
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 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Cacheable { @AliasFor("cacheNames") String[] value() default {}; @AliasFor("value") String[] cacheNames() default {}; String key () default "" ; String keyGenerator () default "" ; String cacheManager () default "" ; String cacheResolver () default "" ; String condition () default "" ; String unless () default "" ; boolean sync () default false ; }
首先在这个注解中,value
或者是cacheNames
这个参数是必须的。
1 2 3 4 5 6 @Cacheable("yww") @GetMapping("/") public Result getInfo () { List<User> list = service.list(); return Result.ok().data("list" ,list); }
最经常用的组合。
1 2 3 4 5 6 @Cacheable(value = "yww",key = "111") @GetMapping("/") public Result getInfo () { List<User> list = service.list(); return Result.ok().data("list" ,list); }
condition
这个参数是用来定义缓存的条件的,比如下面这个例子。
1 2 3 4 5 @Cacheable(value = "yww",condition = "#id > 50") @GetMapping("/{id}") public Result getInfo (@PathVariable("id") int id) { }
CachePut 这个注解和Cacheable
作用是一样的,参数也是一样的,不一样的是这个注解是只负责将返回的结果存入缓存,再次查询的时候,是不走缓存的。
CacheEvict 这个注解主要是用来清除缓存的。
主要使用的参数是allEntries
,让它为true会将缓存清空
1 2 3 4 @Cacheable(value = "yww",key = "111",condition = "#id > 50",allEntries = true) public void clear () { }
Zset实现一个排行榜 Zset这个数据结构是一个有序的集合,它会根据score
来自动帮你进行排序。以下为Zset的一些操作进行一个封装。
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 99 @Component @SuppressWarnings(value = { "unchecked", "rawtypes" }) public class RedisUtil { @Resource private RedisTemplate redisTemplate; public void addZset (String sortedSetKey, Object member, double score) { redisTemplate.opsForZSet().add(sortedSetKey,member,score); } public Set<Object> getTop (String sortedSetKey, long number) { return redisTemplate.opsForZSet().reverseRange(sortedSetKey, 0L , number); } public Double getScore (String sortedSetKey, Object member) { return redisTemplate.opsForZSet().score(sortedSetKey, member); } public Set<ZSetOperations.TypedTuple<Object>> getTop(String sortedSetKey, long top) { return redisTemplate.opsForZSet().reverseRangeWithScores(sortedSetKey, 0 , top); } public void incrementScore (String sortedSetKey, Object member, double score) { redisTemplate.opsForZSet().incrementScore(sortedSetKey,member,score); } public Long getTotal (String sortedSetKey) { return redisTemplate.opsForZSet().size(sortedSetKey); } public boolean containsZsetKey (String sortedSetKey, Object member) { return redisTemplate.opsForZSet().score(sortedSetKey, member) != null ; } public void incrementScore (String sortedSetKey, Object member, double score) { redisTemplate.opsForZSet().incrementScore(sortedSetKey,member,score); } public Long getTotal (String sortedSetKey) { return redisTemplate.opsForZSet().size(sortedSetKey); } }
然后使用这个封装类的方法,定义出一个Zset,在点击等操作的逻辑中增加一些操作,将需要排行的数据加入到指定的Zset中,就可以实现一个简单排行榜了。
测试。
1 2 3 4 5 6 7 8 9 10 11 12 @SpringBootTest class MyprojectApplicationTests { @Resource private RedisUtil util; @Test void contextLoads () { System.out.println(util.getScore("video" ,"e720a1f03858488b854564954dde7047" )); } }