当前位置:首页 > 技术 > 正文内容

Jedis 与 RedisTemplate 的 Java 实践指南

访客 技术 2026年6月25日 1

Jedis 是 Java 生态中直接操作 Redis 的轻量级客户端,而 RedisTemplate 则是 Spring 框架提供的高层抽象。本文将围绕这两种技术路线,展示从环境搭建到典型业务场景的完整实践。

一、工程构建与依赖配置

采用多模块 Maven 工程结构,父工程统筹依赖版本管理,子模块分别承载不同技术方案。

1.1 Jedis 模块依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.5.2</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

1.2 Spring 模块依赖

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.3.2.RELEASE</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

二、Jedis 核心操作

2.1 服务端配置要点

若需远程连接 Redis 服务,需调整配置文件:

  • 注释 bind 127.0.0.1 行,或修改为指定网卡
  • protected-mode 设为 no
  • 重启服务使配置生效

2.2 基础数据类型操作

public class JedisBasicTests {

    @Test
    public void testStringCommands() throws InterruptedException {
        Jedis client = new Jedis("192.168.126.129", 6379);
        
        client.set("sessionToken", "xyz789");
        client.setex("verifyCode", 120, "8823");
        
        client.set("counter", "10");
        client.incr("counter");
        client.incrBy("counter", 5);
        
        String token = client.get("sessionToken");
        Long ttl = client.ttl("verifyCode");
        
        System.out.println("Token: " + token);
        System.out.println("验证码剩余秒数: " + ttl);
        
        client.close();
    }

    @Test
    public void testHashCommands() {
        Jedis client = new Jedis("192.168.126.129", 6379);
        
        client.hset("employee:1001", "name", "Alice");
        client.hset("employee:1001", "department", "Engineering");
        client.hset("employee:1001", "level", "P6");
        
        Map<String, String> profile = client.hgetAll("employee:1001");
        System.out.println(profile);
        
        client.close();
    }

    @Test
    public void testListCommands() {
        Jedis client = new Jedis("192.168.126.129", 6379);
        
        client.rpush("taskQueue", "task-A", "task-B", "task-C");
        client.lpush("taskQueue", "urgent-task");
        
        List<String> tasks = client.lrange("taskQueue", 0, -1);
        String nextTask = client.lpop("taskQueue");
        
        System.out.println("队列内容: " + tasks);
        System.out.println("取出任务: " + nextTask);
        
        client.close();
    }
}

2.3 JSON 对象序列化处理

@Test
public void testJsonSerialization() {
    Jedis conn = new Jedis("192.168.126.129", 6379);
    
    Map<String, Object> commodity = new HashMap<>();
    commodity.put("sku", "SKU-2024-008");
    commodity.put("itemName", "无线降噪耳机");
    commodity.put("price", 899.00);
    
    Gson gson = new Gson();
    String payload = gson.toJson(commodity);
    
    conn.set("product:detail", payload);
    
    String retrieved = conn.get("product:detail");
    Map<?, ?> result = gson.fromJson(retrieved, Map.class);
    
    System.out.println("反序列化结果: " + result);
    
    conn.close();
}

三、典型业务场景实现

3.1 分布式唯一 ID 生成

public class DistributedIdWorker {
    
    private static final String REDIS_HOST = "192.168.126.129";
    private static final int REDIS_PORT = 6379;
    private static final String COUNTER_KEY = "global:sequence";
    
    public static long fetchNextId() {
        try (Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT)) {
            return jedis.incr(COUNTER_KEY);
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> 
                System.out.println(Thread.currentThread().getName() 
                    + " 获取 ID: " + fetchNextId())
            ).start();
        }
    }
}

3.2 基于 Token 的会话管理

public class TokenAuthService {
    
    private static final String HOST = "192.168.126.129";
    private static final int PORT = 6379;
    private static final int SESSION_TTL = 3600;

    public String performLogin(String account, String credential) {
        if (!validateCredentials(account, credential)) {
            throw new SecurityException("认证信息无效");
        }
        
        try (Jedis conn = new Jedis(HOST, PORT)) {
            String sessionToken = UUID.randomUUID().toString().replace("-", "");
            conn.setex("session:" + sessionToken, SESSION_TTL, account);
            return sessionToken;
        }
    }
    
    public String accessResource(String token) {
        if (token == null || token.trim().isEmpty()) {
            throw new IllegalArgumentException("缺少有效凭证");
        }
        
        try (Jedis conn = new Jedis(HOST, PORT)) {
            String account = conn.get("session:" + token);
            if (account == null) {
                throw new RuntimeException("会话已过期,请重新登录");
            }
            return "用户 " + account + " 的资源数据";
        }
    }
    
    private boolean validateCredentials(String account, String credential) {
        return "admin".equals(account) && "Secure#123".equals(credential);
    }
}

3.3 投票去重系统

public class VoteService {
    
    private static final String SERVER = "192.168.126.128";
    private static final int SERVER_PORT = 6379;

    public boolean hasParticipated(String eventId, String participantId) {
        try (Jedis conn = new Jedis(SERVER, SERVER_PORT)) {
            return conn.sismember("vote:" + eventId, participantId);
        }
    }
    
    public void castVote(String eventId, String participantId) {
        if (hasParticipated(eventId, participantId)) {
            System.out.println("该用户已投过票");
            return;
        }
        
        try (Jedis conn = new Jedis(SERVER, SERVER_PORT)) {
            conn.sadd("vote:" + eventId, participantId);
        }
    }
    
    public long tallyVotes(String eventId) {
        try (Jedis conn = new Jedis(SERVER, SERVER_PORT)) {
            return conn.scard("vote:" + eventId);
        }
    }
    
    public Set<String> listParticipants(String eventId) {
        try (Jedis conn = new Jedis(SERVER, SERVER_PORT)) {
            return conn.smembers("vote:" + eventId);
        }
    }
}

3.4 购物车数据维护

public class ShoppingCartDao {
    
    private static final String HOST_ADDR = "192.168.126.128";
    private static final int HOST_PORT = 6379;
    private static final String CART_PREFIX = "cart:";

    public void addItem(String buyerId, String merchandiseId, int quantity) {
        try (Jedis conn = new Jedis(HOST_ADDR, HOST_PORT)) {
            conn.hincrBy(CART_PREFIX + buyerId, merchandiseId, quantity);
        }
    }
    
    public Map<String, String> retrieveCart(String buyerId) {
        try (Jedis conn = new Jedis(HOST_ADDR, HOST_PORT)) {
            return conn.hgetAll(CART_PREFIX + buyerId);
        }
    }
    
    public void removeItem(String buyerId, String merchandiseId) {
        try (Jedis conn = new Jedis(HOST_ADDR, HOST_PORT)) {
            conn.hdel(CART_PREFIX + buyerId, merchandiseId);
        }
    }
    
    public void clearCart(String buyerId) {
        try (Jedis conn = new Jedis(HOST_ADDR, HOST_PORT)) {
            conn.del(CART_PREFIX + buyerId);
        }
    }
}

3.5 秒杀请求队列

public class FlashSaleQueue {
    
    private static final String QUEUE_NAME = "flashsale:requests";

    public void enqueueRequest(String requestData) {
        try (Jedis conn = new Jedis("192.168.126.129", 6379)) {
            conn.lpush(QUEUE_NAME, requestData);
        }
    }
    
    public String dequeueRequest() {
        try (Jedis conn = new Jedis("192.168.126.129", 6379)) {
            List<String> result = conn.brpop(30, QUEUE_NAME);
            return result != null ? result.get(1) : null;
        }
    }

    public static void main(String[] args) {
        FlashSaleQueue queue = new FlashSaleQueue();
        
        Thread producer = new Thread(() -> {
            int seq = 1;
            while (true) {
                queue.enqueueRequest("order-" + seq++);
                try {
                    Thread.sleep(800);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        });
        
        Thread consumer = new Thread(() -> {
            while (true) {
                String request = queue.dequeueRequest();
                if (request != null) {
                    System.out.println("处理请求: " + request);
                }
            }
        });
        
        producer.start();
        consumer.start();
    }
}

四、连接池优化配置

4.1 连接池基础使用

public class PoolConfigurationTest {
    
    @Test
    public void demonstratePoolUsage() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(32);
        poolConfig.setMaxIdle(10);
        poolConfig.setMinIdle(4);
        
        try (JedisPool pool = new JedisPool(poolConfig, "192.168.126.128", 6379)) {
            try (Jedis client = pool.getResource()) {
                client.set("poolDemo", "connectedViaPool");
                System.out.println(client.get("poolDemo"));
            }
        }
    }
}

4.2 封装数据源组件

public class RedisDatasource {
    
    private static final JedisPool connectionPool;
    private static final String SERVER_HOST = "192.168.126.129";
    private static final int SERVER_PORT = 6379;
    
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(24);
        config.setMaxIdle(8);
        config.setMaxWaitMillis(3000);
        connectionPool = new JedisPool(config, SERVER_HOST, SERVER_PORT);
    }
    
    public static Jedis borrowConnection() {
        return connectionPool.getResource();
    }
    
    public static void returnConnection(Jedis conn) {
        if (conn != null) {
            conn.close();
        }
    }
}

五、Spring Data Redis 实践

5.1 配置文件

spring:
  redis:
    host: 192.168.64.129
    port: 6379
    lettuce:
      pool:
        max-active: 16
        max-idle: 8

5.2 字符串类型操作

@SpringBootTest
public class StringTemplateTests {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void testValueOperations() {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        
        ops.set("config:theme", "dark");
        ops.set("config:refresh", "5000", 60, TimeUnit.SECONDS);
        
        ops.increment("stats:pageView");
        
        String theme = ops.get("config:theme");
        System.out.println("当前主题: " + theme);
    }
}

5.3 哈希结构操作

@Test
void testHashOperations() {
    HashOperations<String, Object, Object> ops = stringRedisTemplate.opsForHash();
    
    ops.put("profile:user:10086", "nickname", "Explorer");
    ops.put("profile:user:10086", "region", "Shanghai");
    ops.put("profile:user:10086", "badges", "3");
    
    Object region = ops.get("profile:user:10086", "region");
    List<Object> allValues = ops.values("profile:user:10086");
    
    System.out.println("地区: " + region);
    System.out.println("完整信息: " + allValues);
}

5.4 JSON 数据交互

@Test
void testJsonExchange() throws JsonProcessingException {
    ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
    ObjectMapper mapper = new ObjectMapper();
    
    Map<String, Object> article = new HashMap<>();
    article.put("articleId", "A-2024-001");
    article.put("headline", "Redis 高性能实践");
    article.put("viewCount", 15200);
    
    String jsonPayload = mapper.writeValueAsString(article);
    ops.set("article:content", jsonPayload);
    
    String stored = ops.get("article:content");
    Map<?, ?> parsed = mapper.readValue(stored, Map.class);
    
    System.out.println("解析结果: " + parsed);
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。