使用 Java 来操作 Redis

1. Jedis 的基本使用

什么是 Jedis? github 上面是这样描述的:

  • Jedis is a blazingly small and sane Redis java client.
  • Jedis was conceived to be EASY to use.
  • Jedis is fully compatible with redis 2.8.x, 3.x.x and above*.

大致意思:Jedis 是 Redis 官方推荐的 Java 连接开发工具!使用 Java 来操作 Redis 中间件。类似于 JDBC 吧。

如果想要使用 Java 来操作 Redis,那么就一定要对 Jedis 十分地熟悉(即:对 Redis 五大基本数据类型的操作命令熟悉)

例如:String 类型的命令

set key value				# 给 key 设置 value
get key						# 获取 key 对应的 value
append key value			# 如果 key 存在,则追加;否则,相当于 set 命令
setnx key value				# 如果 key 不存在,就设置
getset key value			# 先 get,再 set
...

实战

1、创建一个 Maven 项目,并导入 Pom 依赖

<!-- jedis -->
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>3.2.0</version>
</dependency>

<!-- fastjson -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.62</version>
</dependency>

2、编码测试

  1. 连接 redis
  2. 操作命令
  3. 断开连接
public class TestPing {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        System.out.println(jedis.ping());
    }
}

在这里插入图片描述
Jedis 对象中的方法就是 Redis 中数据类型的操作命令
在这里插入图片描述
如果程序返回 PONG,表示使用 Java 连接 Redis 成功!

接下来,简单地操作下 String 类型:

public class TestPing {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);

        System.out.println("清空数据:" + jedis.flushDB());
        System.out.println("判断某个键是否存在:" + jedis.exists("username"));
        System.out.println("添加一个键值对:" + jedis.set("username", "zzc"));
        System.out.println("系统中所有的键如下:");
        System.out.println(jedis.keys("*"));
    }
}

结果如下:
在这里插入图片描述
重点是要对 Redis 的操作命令熟悉,这样使用 Jedis 时才能得心应手!!

2 Jedis 中使用事务

public class TestTx {

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);

        JSONObject json = new JSONObject();
        json.put("name", "zzc");
        json.put("age", 18);

        jedis.flushDB();
        // 1. 开启事务
        Transaction ts = jedis.multi();
        try {
            ts.set("user", json.toString());
            // 2. 执行事务
            ts.exec();
        } catch (Exception e) {
            // 回滚事务
            ts.discard();
        } finally {
            System.out.println(jedis.get("user"));
            jedis.close();
        }
    }
}

3. 使用 SpringBoot 整合 Redis

创建一个 SpringBoot 项目,并引入依赖 Redis

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

点进去 spring-boot-starter-data-redis,查看其 POM 文件:

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-redis</artifactId>
  <version>2.4.3</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>io.lettuce</groupId>
  <artifactId>lettuce-core</artifactId>
  <version>6.0.2.RELEASE</version>
  <scope>compile</scope>
</dependency>

这个里面只有 lettuce,而没有 jedis。

【注意】:SpringBoot 2.x 之后,原来使用的 jedis 被替换为了 lettuce

jedis 与 lettuce 之间区别?

  • jedis:采用直连的方式,多线程是不安全的;要想避免多线程安全,则需要使用 jedis pool 连接池!类似于 BIO
  • lettuce:采用 Netty 的方式,实例可以在多个线程中共享,多线程安全。类似于 NIO

在 Springboot 配置原理中,涉及到以下两方面:

  1. SpringBoot 中所有的配置类,都有一个自动配置类。RedisAutoConfiguration
  2. 自动配置类都会绑定一个配置文件 properties。RedisProperties

源码分析:

@Bean
// 这个注解@ConditionalOnMissingBean表示:如果name为“redisTemplate”的bean存在,这该注解修饰的代码块不执行。
@ConditionalOnMissingBean(name = {"redisTemplate"})
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
	// 默认的 RedisTemplate 没有过多的设置,redis 对象都是需要序列化的(类似于 Dubbo)
    RedisTemplate<Object, Object> template = new RedisTemplate();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
}

@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
    StringRedisTemplate template = new StringRedisTemplate();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
}

使用 SpringBoot 操作 Redis:

  1. 导入依赖
  2. 配置连接:可以使用默认配置
  3. 编码测试

单元测试:

@SpringBootTest
class SbApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test () {
        redisTemplate.opsForValue().set("name", "zzc");
        System.out.println(redisTemplate.opsForValue().get("name"));
    }
}

但是,在命令行中查看时,key 会出现乱码(如果存储的是中文也会出现乱码)
在这里插入图片描述
这是因为序列化导致的。

查看 RedisTemplate.class 源码:
RedisTemplate 中有好多 序列化器
在这里插入图片描述
其中,默认的序列化是 JDK 序列化(它会让字符串转义)
在这里插入图片描述
这里我们使用 json 来序列化,就需要我们自定义一个配置类

4. 自定义 RedisTemplate

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        // json 序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // String 序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // 所有的 key 采用 string 的序列化
        template.setKeySerializer(stringRedisSerializer);
        // hash 的 key 采用 string 的序列化
        template.setHashKeySerializer(stringRedisSerializer);
        // 所有的 value 采用 jackson 的序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash 的 value 采用 jackson 的序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }
}

再次执行测试代码:
在这里插入图片描述
key 没有乱码了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值