Redis——Jedis操作Redis

即通过 Java 操作 Redis

1. Jedis基本操作

Ⅰ. 测试连接

连接Redis注意事项

禁用Linux的防火墙:Linux(CentOS7)里执行命令:systemctl stop/disable firewalld.service

redis.conf中注释掉bind 127.0.0.1,然后 protected-mode no

  • 引入依赖
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.2.0</version>
</dependency>
  • 测试连接
    如果Redis安装在云服务器中,注意配置服务器的防护墙安全组。
public static void main(String[] args) {
    
    Jedis jedis = new Jedis("你的redis所在服务器的IP地址", 6379);
    // 如果你的Redis设置了密码,执行这步
    jedis.auth("你的redis密码");

    String ping = jedis.ping();
    System.out.println(ping);
    
    jedis.close();
}

控制台打印:

redis.clients.jedis.Jedis操作 使用jedis操作redis_nosql

说明连接成功。

Ⅱ. 操作 Redis

  • Key
@Test
public void testKey() {
    jedis.set("k1", "v1");
	jedis.set("k2", "v2");
	jedis.set("k3", "v3");
	Set<String> keys = jedis.keys("*");
	System.out.println(keys.size());
    
	for (String key : keys) {
		System.out.println(key);
	}
	System.out.println(jedis.exists("k1"));
	System.out.println(jedis.ttl("k1"));                
	System.out.println(jedis.get("k1"));
    
    jedis.close();
}

redis.clients.jedis.Jedis操作 使用jedis操作redis_nosql_02

  • String
@Test
public void testString() {
    String set = jedis.set("key1", "v1");
    System.out.println(set);

    String key1 = jedis.get("key1");
    System.out.println(key1);
    
    // 设置多个key-value
    jedis.mset("k1", "v1", "k2", "v2");
    List<String> mget = jedis.mget("k1", "k2");
    System.out.println(mget);

    jedis.close();
}

redis.clients.jedis.Jedis操作 使用jedis操作redis_数据库_03

  • List
@Test
public void testList() {
    jedis.lpush("list1", "v1", "v2", "v3");

    List<String> list = jedis.lrange("list1", 0, -1);
    list.forEach(System.out::println);
    
    jedis.close();
}

redis.clients.jedis.Jedis操作 使用jedis操作redis_redis_04

  • Set
@Test
public void testSet() {
    Long sadd = jedis.sadd("set1", "tom", "jerry", "jack");
    Set<String> set = jedis.smembers("set1");
    System.out.println(set);
    
    jedis.close();
}

redis.clients.jedis.Jedis操作 使用jedis操作redis_数据库_05

  • Hash
@Test
public void testHash() {
    Map<String, String> map = new HashMap<>();
    map.put("id", "1");
    map.put("name", "Tom");
    map.put("age", "18");

    jedis.hset("map1", map);

    String id = jedis.hget("map1", "id");
    String name = jedis.hget("map1", "name");
    String age = jedis.hget("map1", "age");

    System.out.println("id = " + id);
    System.out.println("name = " + name);
    System.out.println("age = " + age);
    
    jedis.close();
}

redis.clients.jedis.Jedis操作 使用jedis操作redis_java_06

  • zset
@Test
public void testZSet() {
    jedis.zadd("zset1", 100d, "java");
    jedis.zadd("zset1", 50d, "c++");
    jedis.zadd("zset1", 25d, "php");

    Set<String> set = jedis.zrange("zset1", 0, -1);

    System.out.println(set);
    
    jedis.close();
}

redis.clients.jedis.Jedis操作 使用jedis操作redis_nosql_07

2. 模拟验证码案例

完成一个手机验证码功能

业务需求

  • 输入手机号,点击发送后随机生成 redis.clients.jedis.Jedis操作 使用jedis操作redis_redis_08 位数字码,redis.clients.jedis.Jedis操作 使用jedis操作redis_redis_09
  • 输入验证码,点击验证,返回成功或失败
  • 每个手机号每天只能输入 redis.clients.jedis.Jedis操作 使用jedis操作redis_redis_10

需求分析

redis.clients.jedis.Jedis操作 使用jedis操作redis_redis_11

代码实现

package com.lyc.jedis;

import redis.clients.jedis.Jedis;

import java.util.Random;

public class PhoneCodeTest {

    private static Jedis jedis = new Jedis("192.168.232.102", 6379);
    private static final int TIMEOUT_CODE = 60 * 2; // 验证码过期时间
    private static final int TIMEOUT_PHONE = 60 * 60 * 24; // 一天的时间

    public static void main(String[] args) {
        // 模拟验证码发送
        verifyCode("123123123");
        // 验证码校验
        //checkVerifyCode("123123123", "057931");
        jedis.close();
    }

    // 随机生成6位数字验证码
    public static String getCode() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }

    // 发送验证码:每个手机每天最多只能发送三次,验证码放到redis中,设置过期时间为120s
    public static void verifyCode(String phone) {
        // 拼接key
        // 手机发送次数key
        String countKey = "VerifyCode" + phone + ":count";
        // 验证码key
        String codeKey = "VerifyCode" + phone + ":code";

        // 每个手机每天只能发送三次短信
        String count = jedis.get(countKey);
        if (count == null) {
            // 没有发送次数,第一次发送
            // 设置发送次数是1
            jedis.setex(countKey, TIMEOUT_PHONE, "1");
        } else if (Integer.parseInt(count) < 3) {
            // 发送次数+1
            jedis.incr(countKey);
        } else {
            // 发送三次,不能再发送
            System.out.println("今天已经发送了3次验证码!");
            jedis.close();
            return;
        }

        // 设置验证码 放到redis中 设置过期时间为120s
        String code = getCode();
        jedis.setex(codeKey, TIMEOUT_CODE, code);
    }

    // 验证码校验
    public static void checkVerifyCode(String phone, String code) {
        // 从redis获取验证码
        String codeKey = "VerifyCode" + phone + ":code";
        String redisCode = jedis.get(codeKey);

        if (code.equals(redisCode)) {
            System.out.println("验证通过!");
        } else {
            System.out.println("验证失败!");
        }
    }
}

测试

  • 发送 redis.clients.jedis.Jedis操作 使用jedis操作redis_redis_10

当再发送第 redis.clients.jedis.Jedis操作 使用jedis操作redis_缓存_13

redis.clients.jedis.Jedis操作 使用jedis操作redis_数据库_14

  • 验证码校验
  • 发送验证码
  • 执行校验方法

3. SpringBoot整合Redis

  • 引入依赖
<!-- redis -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring2.X集成redis所需common-pool2 -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
	<version>2.6.0</version>
</dependency>
<!-- 还需引入jackson的依赖(redis的配置类会用到) -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.7.1</version>
</dependency>
  • application.properties配置redis
#Redis服务器地址
spring.redis.host=192.168.232.102
#Redis服务器连接端口
spring.redis.port=6379
#Redis数据库索引(默认为0)
spring.redis.database= 0
#连接超时时间(毫秒)
spring.redis.timeout=1800000
#连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=20
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=5
#连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
  • 添加redis配置类
package com.lyc.redis_springboot.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@EnableCaching // 开启缓存(开启redis操作)
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        // key序列化方式
        template.setKeySerializer(redisSerializer);
        // value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }

    @Bean
    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.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}
  • 测试
  • RedisTestController中添加测试方法
package com.lyc.redis_springboot.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/redisTest")
public class RedisTestController {

    @Autowired
    private RedisTemplate redisTemplate;
    
    @GetMapping
    public String testRedis() {
        // 设置值到redis
        redisTemplate.opsForValue().set("name", "lucy");
        // 从redis获取值
        String name = (String) redisTemplate.opsForValue().get("name");
        return name;
    }
}
  • http://localhost:8080/redisTest

redis.clients.jedis.Jedis操作 使用jedis操作redis_java_15