SpringBoot依赖之Spring Data Redis的功能抽离公共服务

前几期我们针对在SpringBoot中的 Spring Data Redis 依赖对Redis不同类型的存储格式进行了细分学习,今天在这里进行汇总,当然如果你的项目使用的是Spring Data Redis这个原生官方以来,下面的汇总类RedisService 也可以作为公共类用在你们的项目当中。

往期文章

SpringBoot依赖之Spring Data Redis 一 String类型

SpringBoot依赖之Spring Data Redis 一 List 类型

SpringBoot依赖之Spring Data Redis 一 Hash类型

SpringBoot依赖之Spring Data Redis一集合Set

SpringBoot依赖之Spring Data Redis一有序集合Sorted Set

SpringBoot依赖之Spring Data Redis实现位图Bitmap

SpringBoot依赖之Spring Data Redis 实现地理坐标(Geospatial)

我们可以在 RedisService 和 RedisController 中实现对 Redis 其他几种类型(String、List、Set、Sorted Set、Bitmap、HyperLogLog 等)的操作。以下是所有 Redis 数据类型的实现。

1. 更新 Redis 服务类

在 RedisService 类中添加所有类型的操作方法。

java 复制代码
package com.dependencies.springdataredis;

import org.springframework.data.domain.Range;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author zhizhou   2024/8/17 12:01
 */
@Service
public class RedisService {
    
    private final RedisTemplate<String, Object> redisTemplate;
    private final HashOperations<String, String, Object> hashOperations;
    private final ListOperations<String, Object> listOperations;
    private final ValueOperations<String, Object> valueOperations;
    private final SetOperations<String, Object> setOperations;
    private final ZSetOperations<String, Object> zSetOperations;
    private final HyperLogLogOperations<String, Object> hyperLogLogOperations;
    private final GeoOperations<String, Object> geoOperations;
    
    public RedisService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.valueOperations = redisTemplate.opsForValue();
        this.hashOperations = redisTemplate.opsForHash();
        this.listOperations = redisTemplate.opsForList();
        this.setOperations = redisTemplate.opsForSet();
        this.zSetOperations = redisTemplate.opsForZSet();
        this.hyperLogLogOperations = redisTemplate.opsForHyperLogLog();
        this.geoOperations = redisTemplate.opsForGeo();
    }
    
    public void saveValue(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }
    
    public String getValue(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }
    
    //hash
    
    // 保存哈希数据
    public void saveToHash(String key, String field, String value) {
        hashOperations.put(key, field, value);
    }
    
    // 从哈希中获取数据
    public String getFromHash(String key, String field) {
        return (String) hashOperations.get(key, field);
    }
    
    // 删除哈希中的某个字段
    public void deleteFromHash(String key, String field) {
        hashOperations.delete(key, field);
    }
    
    // 获取哈希中的所有键值对
    public Map<String, Object> getAllFromHash(String key) {
        return hashOperations.entries(key);
    }
    
    //list
    
    // 向列表左侧推入值
    public void pushToListLeft(String key, String value) {
        listOperations.leftPush(key, value);
    }
    
    // 向列表右侧推入值
    public void pushToListRight(String key, String value) {
        listOperations.rightPush(key, value);
    }
    
    // 从列表左侧弹出值
    public String popFromListLeft(String key) {
        return (String) listOperations.leftPop(key);
    }
    
    // 从列表右侧弹出值
    public String popFromListRight(String key) {
        return (String) listOperations.rightPop(key);
    }
    
    // 获取列表中所有值
    public List<Object> getList(String key) {
        return listOperations.range(key, 0, -1);
    }
    
    
    //Set
    
    // Set操作
    public void addToSet(String key, String value) {
        setOperations.add(key, value);
    }
    
    public Set<Object> getSetMembers(String key) {
        return setOperations.members(key);
    }
    
    public boolean isMemberOfSet(String key, String value) {
        return setOperations.isMember(key, value);
    }
    
    public void removeFromSet(String key, String value) {
        setOperations.remove(key, value);
    }
    
    // Sorted Set操作
    public void addToSortedSet(String key, String value, double score) {
        zSetOperations.add(key, value, score);
    }
    
    public Set<Object> getSortedSetRange(String key, long start, long end) {
        return zSetOperations.range(key, start, end);
    }
    
    public void removeFromSortedSet(String key, String value) {
        zSetOperations.remove(key, value);
    }
    
    // HyperLogLog操作
    public void addToHyperLogLog(String key, String value) {
        hyperLogLogOperations.add(key, value);
    }
    
    public long countInHyperLogLog(String key) {
        return hyperLogLogOperations.size(key);
    }
    
    // Bitmap操作
    public void setBit(String key, long offset, boolean value) {
        valueOperations.setBit(key, offset, value);
    }
    
    public boolean getBit(String key, long offset) {
        return valueOperations.getBit(key, offset);
    }
    
    private static final String GEO_KEY = "locations";
    
    // 添加地理坐标
    public void addLocation(String member, double longitude, double latitude) {
        geoOperations.add(GEO_KEY, new Point(longitude, latitude), member);
    }
    
    // 根据坐标查询附近的地点
    public List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> getNearbyLocations(double longitude, double latitude, double radius) {
        Circle within = new Circle(new Point(longitude, latitude), new Distance(radius, RedisGeoCommands.DistanceUnit.KILOMETERS));
        return geoOperations.radius(GEO_KEY, within).getContent();
    }
    
    // 获取两地之间的距离
    public Distance getDistance(String member1, String member2) {
        return geoOperations.distance(GEO_KEY, member1, member2, RedisGeoCommands.DistanceUnit.METERS);
    }
   
  
}

2. 更新控制器类

在 RedisController 中添加处理这些数据类型操作的端点。

java 复制代码
package com.dependencies.springdataredis;

import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author zhizhou   2024/8/17 12:02
 */
@RestController
public class RedisController {
    private final RedisService redisService;
    
    public RedisController(RedisService redisService) {
        this.redisService = redisService;
    }
    
    @GetMapping("/set")
    public String setKey(@RequestParam String key, @RequestParam String value) {
        redisService.saveValue(key, value);
        return "保存成功";
    }
    
    @GetMapping("/get")
    public String getKey(@RequestParam String key) {
        return redisService.getValue(key);
    }
     
    @GetMapping("/hash/set")
    public String setHash(@RequestParam String key, @RequestParam String field, @RequestParam String value) {
        redisService.saveToHash(key, field, value);
        return "哈希值保存成功";
    }
    
    // 获取哈希中的数据
    @GetMapping("/hash/get")
    public String getHash(@RequestParam String key, @RequestParam String field) {
        return redisService.getFromHash(key, field);
    }
    
    // 删除哈希中的某个字段
    @GetMapping("/hash/delete")
    public String deleteHashField(@RequestParam String key, @RequestParam String field) {
        redisService.deleteFromHash(key, field);
        return "哈希字段已删除";
    }
    
    // 获取哈希中的所有字段和值
    @GetMapping("/hash/getall")
    public Map<String, Object> getAllHash(@RequestParam String key) {
        return redisService.getAllFromHash(key);
    }
    
   
    // 向列表左侧推入值
    @GetMapping("/list/leftpush")
    public String leftPushToList(@RequestParam String key, @RequestParam String value) {
        redisService.pushToListLeft(key, value);
        return "值被推到列表的左侧";
    }
    
    // 向列表右侧推入值
    @GetMapping("/list/rightpush")
    public String rightPushToList(@RequestParam String key, @RequestParam String value) {
        redisService.pushToListRight(key, value);
        return "值被推到列表的右侧";
    }
    
    // 从列表左侧弹出值
    @GetMapping("/list/leftpop")
    public String leftPopFromList(@RequestParam String key) {
        return redisService.popFromListLeft(key);
    }
    
    // 从列表右侧弹出值
    @GetMapping("/list/rightpop")
    public String rightPopFromList(@RequestParam String key) {
        return redisService.popFromListRight(key);
    }
    
    // 获取列表中所有值
    @GetMapping("/list/getall")
    public List<Object> getAllFromList(@RequestParam String key) {
        return redisService.getList(key);
    }
    
    
    // Set操作
    @GetMapping("/set/add")
    public String addToSet(@RequestParam String key, @RequestParam String value) {
        redisService.addToSet(key, value);
        return "值已加入集合set";
    }
    
    @GetMapping("/set/members")
    public Set<Object> getSetMembers(@RequestParam String key) {
        return redisService.getSetMembers(key);
    }
    
    @GetMapping("/set/ismember")
    public boolean isMemberOfSet(@RequestParam String key, @RequestParam String value) {
        return redisService.isMemberOfSet(key, value);
    }
    
    @GetMapping("/set/remove")
    public String removeFromSet(@RequestParam String key, @RequestParam String value) {
        redisService.removeFromSet(key, value);
        return "值已从集合set移除";
    }
    
    // Sorted Set操作
    @GetMapping("/zset/add")
    public String addToSortedSet(@RequestParam String key, @RequestParam String value, @RequestParam double score) {
        redisService.addToSortedSet(key, value, score);
        return "值已加入有序集合sorted set";
    }
    
    @GetMapping("/zset/range")
    public Set<Object> getSortedSetRange(@RequestParam String key, @RequestParam long start, @RequestParam long end) {
        return redisService.getSortedSetRange(key, start, end);
    }
    
    @GetMapping("/zset/remove")
    public String removeFromSortedSet(@RequestParam String key, @RequestParam String value) {
        redisService.removeFromSortedSet(key, value);
        return "值已从有序集合sorted set移除";
    }
    
    // HyperLogLog操作
    @GetMapping("/hyperloglog/add")
    public String addToHyperLogLog(@RequestParam String key, @RequestParam String value) {
        redisService.addToHyperLogLog(key, value);
        return "Value added to HyperLogLog";
    }
    
    @GetMapping("/hyperloglog/count")
    public long countInHyperLogLog(@RequestParam String key) {
        return redisService.countInHyperLogLog(key);
    }
    
    // Bitmap操作
    @GetMapping("/bitmap/set")
    public String setBit(@RequestParam String key, @RequestParam long offset, @RequestParam boolean value) {
        redisService.setBit(key, offset, value);
        return "Bit set in bitmap";
    }
    
    @GetMapping("/bitmap/get")
    public boolean getBit(@RequestParam String key, @RequestParam long offset) {
        return redisService.getBit(key, offset);
    }
    
   
    // Geo操作
    //添加地理位置
    @GetMapping("/add-location")
    public String addLocation(@RequestParam String member, @RequestParam double longitude, @RequestParam double latitude) {
        redisService.addLocation(member, longitude, latitude);
        return "Location added.";
    }
    //查询附近的地点
    @GetMapping("/nearby")
    public List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> getNearbyLocations(@RequestParam double longitude, @RequestParam double latitude, @RequestParam double radius) {
        return redisService.getNearbyLocations(longitude, latitude, radius);
    }
    //# 如果使用 Lettuce 作为客户端 lettuce
    
    //获取两地之间的距离
    @GetMapping("/distance")
    public Distance getDistance(@RequestParam String member1, @RequestParam String member2) {
        return redisService.getDistance(member1, member2);
    }
}

3. 测试操作

启动项目后,可以通过以下 URL 测试各种 Redis 数据类型的功能:

  • String操作:

    • 设置值: http://localhost:8080/set?key=myKey&value=myValue

    • 获取值: http://localhost:8080/get?key=myKey

  • List操作:

    • 向列表左侧推入值: http://localhost:8080/list/leftpush?key=myList&value=value1
    • 向列表右侧推入值: http://localhost:8080/list/rightpush?key=myList&value=value2
    • 从列表左侧弹出值: http://localhost:8080/list/leftpop?key=myList
    • 从列表右侧弹出值: http://localhost:8080/list/rightpop?key=myList
    • 获取列表中所有值: http://localhost:8080/list/getall?key=myList
  • Hash操作:

    • 保存哈希数据: http://localhost:8080/hash/set?key=user:1001&field=name&value=一周一志程序员

    • 获取哈希数据: http://localhost:8080/hash/get?key=user:1001&field=name

    • 删除哈希字段: http://localhost:8080/hash/delete?key=user:1001&field=name

    • 获取所有哈希数据: http://localhost:8080/hash/getall?key=user:1001

  • Set 操作:

    • 添加成员到集合: http://localhost:8080/set/add?key=mySet&value=value1
    • 获取集合中的所有成员: http://localhost:8080/set/members?key=mySet
    • 检查成员是否在集合中: http://localhost:8080/set/ismember?key=mySet&value=value1
    • 删除集合中的成员: http://localhost:8080/set/remove?key=mySet&value=value1
  • Sorted Set 操作:

    • 添加成员到有序集合: http://localhost:8080/zset/add?key=myZSet&value=value1&score=1.0
    • 获取有序集合中的成员范围: http://localhost:8080/zset/range?key=myZSet&start=0&end=-1
    • 删除有序集合中的成员: http://localhost:8080/zset/remove?key=myZSet&value=value1
  • HyperLogLog 操作:

    • 添加成员到 HyperLogLog: http://localhost:8080/hyperloglog/add?key=myHLL&value=value1
    • 获取 HyperLogLog 的基数估算: http://localhost:8080/hyperloglog/count?key=myHLL
  • Bitmap 操作:

    • 设置 Bitmap 中某个位的值: http://localhost:8080/bitmap/set?key=myBitmap&offset=7&value=true
    • 获取 Bitmap 中某个位的值: http://localhost:8080/bitmap/get?key=myBitmap&offset=7
  • Geospatial 操作:

    • 添加地理位置:http://localhost:8080/add-location?member=location1&longitude=13.361389&latitude=38.115556
    • 查询附近的地点:http://localhost:8080/nearby?longitude=13.361389&latitude=38.115556&radius=10
    • 获取两地之间的距离: http://localhost:8080/distance?member1=location1&member2=location2

4. 总结

通过这些步骤,我们在 Spring Boot 项目中成功实现了对 Redis 各种数据类型(String、List、Set、Sorted Set、Bitmap、HyperLogLog 等)的操作。可以处理和管理 Redis 中的各种复杂数据结构,适应不同的应用场景需求。汇总到此结束。关注我一起为Java程序员蓄能,努力为职业生涯续航!

相关推荐
Small-Young29 分钟前
数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南
数据库·spring boot·mysql·postgresql·乐观锁·并发控制
java_nnnn1 小时前
Spring IoC & DI 从入门到理解:控制反转、依赖注入与 Bean 管理详解
数据库·sql·spring
她的男孩2 小时前
租户 A 的验证码,却用了租户 B 的 AccessKey:Forge Admin 修跨租户短信串发
java·spring boot·saas
小蒜学长2 小时前
基于SpringBoot+Vue的云南地区扶贫助农系统的设计与实现(代码+数据库+LW)
java·vue.js·spring boot·后端·乡村振兴
码剑客2 小时前
Gin+GORM+Redis 项目开发常见性能坑汇总(Go后端避坑指南)
redis·后端·golang·gin
RuoyiOffice2 小时前
Hyper-V+Kubernetes 搭建实战:保留 Windows,构建三节点 Linux 容器集群
linux·spring boot·kubernetes·containerd·hyper-v·微服务部署·ruoyi office
骑着蜗牛撵大象3272 小时前
Spring Boot 4.1 + Spring AI 2.0:RAG 供文、图谱供关系、MCP 供工具的 Java Agent 平台
java·spring boot·spring·微服务·知识图谱·rag·mcp
java_nnnn2 小时前
Spring Boot 配置文件详解:从基础语法到 YAML 配置
spring boot·后端·github
snow@li2 小时前
redis:RedisDesktopManager(RDM/RESP.app)Redis 数据可视化全景深度梳理
数据库·redis·缓存
CoderYanger3 小时前
Java EE 进阶:6.SpringBoot 配置文件(第二弹)
java·spring boot·spring·面试·职场和发展·java-ee·程序员创富