Spring整合Redis

步骤

1.引入依赖包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.5.2</version>
</dependency>

2.配置Redis

2.1配置数据库参数

// properties
# 配置Redis: RedisProperties ( 用哪个库,访问库的IP,Redis端口号: 默认6379)
spring.redis.database=11
spring.redis.host=localhost
spring.redis.port=6379

2.2编写配置类,构造RedisTemplate.

/**
 * 配置一个 bean
 */
@Configuration
public class RedisConfig {

    @Bean  // (参数:连接工厂)
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 实例化这个 bean
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory); // 设置连接工厂,使其具备连接数据库的能力。
        // 如何将java类型数据 存到 redis 数据库中. (需要指定数据转换的方式)
        // 设置key的序列化方式 (序列化成 字符串)
        template.setKeySerializer(RedisSerializer.string());
        // 设置普通的value的序列化方式 (序列化成 json 格式)
        template.setValueSerializer(RedisSerializer.json());
        
        // 设置hash的key的序列化方式
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置hash的value的序列化方式
        template.setHashValueSerializer(RedisSerializer.json());
        
        // 设置完,需要触发生效.
        template.afterPropertiesSet();
        return template;
    }
}

3.访问Redis

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = Community02Application.class)
public class RedisTests {

    @Autowired  // 用户可直接通过RedisTemplate进行多种操作
    private RedisTemplate redisTemplate; // RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

    @Test // String(字符串)
    public void testStrings() {

        String redisKey = "test:count";  // 声明一个 K ;
        redisTemplate.opsForValue().set(redisKey, 1); // 存一个 v 值.

        System.out.println(redisTemplate.opsForValue().get(redisKey)); // 通过 k, 取 v 值.
        System.out.println(redisTemplate.opsForValue().increment(redisKey)); //对 v 值,+1.
        System.out.println(redisTemplate.opsForValue().decrement(redisKey)); //对 v 值,-1.
    }

    @Test // Hash(散列)
    public void testHashes() {

        String redisKey = "test:user"; // 声明一个 K
        // 存 V 值: 一个 id 和 用户名.
        redisTemplate.opsForHash().put(redisKey, "id", 1);
        redisTemplate.opsForHash().put(redisKey, "username", "zhangsan");
        // 通过 K 取 V : id 和 用户名.
        System.out.println(redisTemplate.opsForHash().get(redisKey, "id"));
        System.out.println(redisTemplate.opsForHash().get(redisKey, "username"));
    }

    @Test // List(列表)
    public void testLists() {

        String redisKey = "test:ids"; // 声明一个 K ;

        redisTemplate.opsForList().leftPush(redisKey, 101); // 从左边添加 3 个 V 的值.
        redisTemplate.opsForList().leftPush(redisKey, 102);
        redisTemplate.opsForList().leftPush(redisKey, 103);

        System.out.println(redisTemplate.opsForList().size(redisKey));  // 获取列表中有几个数据.
        System.out.println(redisTemplate.opsForList().index(redisKey, 0)); // 查看索引 0 的值.
        System.out.println(redisTemplate.opsForList().range(redisKey, 0, 2)); // 查看索引0 到 2 的值.

        System.out.println(redisTemplate.opsForList().leftPop(redisKey)); // 从左边随机弹出一个值.
        System.out.println(redisTemplate.opsForList().leftPop(redisKey));
        System.out.println(redisTemplate.opsForList().leftPop(redisKey));
    }

    @Test // Set(集合)
    public void testSets() {
        String redisKey = "test:teachers"; // 声明一个 K ;

        redisTemplate.opsForSet().add(redisKey, "刘备", "关羽", "张飞", "赵云", "诸葛亮");

        System.out.println(redisTemplate.opsForSet().size(redisKey)); // 查看集合中有几个数据.
        System.out.println(redisTemplate.opsForSet().pop(redisKey)); // 随机弹出一个值
        System.out.println(redisTemplate.opsForSet().members(redisKey)); // 查看里面所有 V 值.
    }

    @Test // Zset(有序集合)
    public void testSortedSets() {

        String redisKey = "test:students"; // 声明一个 K ;

        redisTemplate.opsForZSet().add(redisKey, "唐僧", 80);
        redisTemplate.opsForZSet().add(redisKey, "悟空", 90);
        redisTemplate.opsForZSet().add(redisKey, "八戒", 50);
        redisTemplate.opsForZSet().add(redisKey, "沙僧", 70);
        redisTemplate.opsForZSet().add(redisKey, "白龙马", 60);

        System.out.println(redisTemplate.opsForZSet().zCard(redisKey)); // 统计一共有多少个数据
        System.out.println(redisTemplate.opsForZSet().score(redisKey, "八戒")); // 查看某个人,的分数.
        System.out.println(redisTemplate.opsForZSet().reverseRank(redisKey, "八戒")); //查看 八戒的排名(倒序,由大到小;默认小到大)
        System.out.println(redisTemplate.opsForZSet().reverseRange(redisKey, 0, 2)); // 由大到小,取前三名.
    }

    @Test  // 公共命令
    public void testKeys() {

        redisTemplate.delete("test:user"); // 删除一个 K ;

        System.out.println(redisTemplate.hasKey("test:user")); // 判断 K ,存不存在。

        // 指定 ( 设置:K 的过期时间,
        redisTemplate.expire("test:students", 10, TimeUnit.SECONDS);

    }

    //对次访问同一K,批量发送命令,节约网络开销
    @Test
    public void testBoundOperations() {

        String redisKey = "test:count"; // 声明一个 K
        // 以绑定的形式 存在
        BoundValueOperations operations = redisTemplate.boundValueOps(redisKey);

        operations.increment();
        operations.increment();
        operations.increment();
        operations.increment();
        operations.increment();
        System.out.println(operations.get());

    }

    // 编程式事务
    @Test
    public void testTransaction() {

        Object result = redisTemplate.execute(new SessionCallback() {

            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {
                String redisKey = "text:tx";

                // 启用事务 : 不能在中间做查询。
                redisOperations.multi();
                redisOperations.opsForSet().add(redisKey, "zhangsan");
                redisOperations.opsForSet().add(redisKey, "lisi");
                redisOperations.opsForSet().add(redisKey, "wangwu");

                System.out.println(redisOperations.opsForSet().members(redisKey));

                // 提交事务
                return redisOperations.exec();
            }
        });
        System.out.println(result);
    }


    // 统计 20 万个重复数据的独立总数.
    @Test
    public void testHyperLogLog() {
        String redisKey = "test:hll:01";

        for (int i = 1; i <= 100000; i++) {
            redisTemplate.opsForHyperLogLog().add(redisKey, i);
        }

        for (int i = 1; i <= 100000; i++) {
            int r = (int) (Math.random() * 100000 + 1);
            redisTemplate.opsForHyperLogLog().add(redisKey, r);
        }

        Long size = redisTemplate.opsForHyperLogLog().size(redisKey);
        System.out.println(size);
    }

    // 统计3组数据的布尔值,并对这3组数据,进行重复处理
    @Test
    public void testHyperLogLogUnion() {
        String redisKey2 = "test:hll:02";
        for (int i = 0; i <= 10000; i++) {
            redisTemplate.opsForHyperLogLog().add(redisKey2, i);
        }

        String redisKey3 = "test:hll:03";
        for (int i = 5001; i <= 15000; i++) {
            redisTemplate.opsForHyperLogLog().add(redisKey3, i);
        }

        String redisKey4 = "test:hll:04";
        for (int i = 10001; i <= 20000; i++) {
            redisTemplate.opsForHyperLogLog().add(redisKey4, i);
        }

        String unionKey = "test:hll:union";
        redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);

        Long size = redisTemplate.opsForHyperLogLog().size(unionKey);
        System.out.println(size);
    }

    // 统计一组数据的布尔值
    @Test
    public void testBitMap() {
        String redisKey = "test:bm:01";

        // 记录
        redisTemplate.opsForValue().setBit(redisKey, 1, true);
        redisTemplate.opsForValue().setBit(redisKey, 2, true);
        redisTemplate.opsForValue().setBit(redisKey, 4, true);
        redisTemplate.opsForValue().setBit(redisKey, 7, true);

        // 查询
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 0));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 1));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 2));

        // 统计
        Object obj = redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.bitCount(redisKey.getBytes());
            }
        });

        System.out.println(obj);
    }

    // 统计3组数据的布尔值, 并对这3组数据做OR运算.
    @Test
    public void testBitMapOperation() {
        String redisKey2 = "test:bm:02";
        redisTemplate.opsForValue().setBit(redisKey2, 0, true);
        redisTemplate.opsForValue().setBit(redisKey2, 1, true);
        redisTemplate.opsForValue().setBit(redisKey2, 2, true);

        String redisKey3 = "test:bm:03";
        redisTemplate.opsForValue().setBit(redisKey3, 2, false);
        redisTemplate.opsForValue().setBit(redisKey3, 3, true);
        redisTemplate.opsForValue().setBit(redisKey3, 4, true);

        String redisKey4 = "test:bm:04";
        redisTemplate.opsForValue().setBit(redisKey4, 4, false);
        redisTemplate.opsForValue().setBit(redisKey4, 5, true);
        redisTemplate.opsForValue().setBit(redisKey4, 6, true);

        String redisKey = "test:bm:or";
        Object obj = redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.bitOp(RedisStringCommands.BitOperation.OR,
                        redisKey.getBytes(), redisKey2.getBytes(), redisKey3.getBytes(), redisKey4.getBytes());
                return connection.bitCount(redisKey.getBytes());
            }
        });

        System.out.println(obj);

        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 0));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 1));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 2));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 3));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 4));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 5));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 6));
    }
}

案例

/**
 * 生成 K 工具类
 */
public class RedisKeyUtil {

    private static final String SPLIT = ":";
    private static final String PREFIX_ENTITY_LIKE = "like:entity"; // K 前缀

    private static final String PREFIX_USER_LIKE = "like:user";  // 获赞数量,user 为 K
    //某个实体的赞 (帖子类型,帖子id)
    // like:entity : entityType : entityId  ->  set(userId)
    public static String getEntityLikeKey(int entityType, int entityId) {
        return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;
    }

    // 某个用户的 K, 获取用户赞数量。
    // like:user:userId  -> int
    public static String getUserLikeKey(int userId) {
        return PREFIX_USER_LIKE + SPLIT + userId;
    }

/**
 * 点赞
 * */
@Controller
public class LikeController implements CommunityConstant {

    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping(path = "like", method = RequestMethod.POST)
    @ResponseBody
    public String like(int postId) {
      // Redis:存值
      String redisKey = RedisKeyUtil.getPostScoreKey();
      redisTemplate.opsForSet().add(redisKey, postId);
      return null;
    }
}

 // Redis:取值
    public long findEntityLikeCount(int entityType, int entityId) {
        // 声明一个 K
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
        // size:统计 K 的数量,【获取变量中元素值的长度】
        return redisTemplate.opsForSet().size(entityLikeKey);
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值