redis教程 二 redis客户端Jedis使用

文章目录

  • Redis的Java客户端-Jedis
    • Jedis快速入门
      • 创建工程:
      • 引入依赖:
      • 建立连接
      • 测试:
      • 释放资源
      • Jedis连接池
        • 创建Jedis的连接池
        • 改造原始代码
    • Redis的Java客户端-SpringDataRedis
      • 快速入门
        • 导入pom坐标
        • 配置文件
        • 测试代码
      • 数据序列化器
      • StringRedisTemplate
      • Hash结构操作
  • 项目仓库

Redis的Java客户端-Jedis

在Redis官网中提供了各种语言的客户端,地址:https://redis.io/docs/clients/

其中Java客户端也包含很多但在开发中用的最多的还是Jedis,接下来就让我们以Jedis开始我们的快速实战。

Jedis快速入门

入门案例详细步骤

案例分析:

创建工程:

创建一个maven管理的java项目
redis教程 二 redis客户端Jedis使用_第1张图片

引入依赖:

在pom.xml文件下添加以下依赖


<dependencies>
    
    <dependency>
        <groupId>redis.clientsgroupId>
        <artifactId>jedisartifactId>
        <version>4.4.3version>
    dependency>
    <dependency>
        <groupId>org.junit.jupitergroupId>
        <artifactId>junit-jupiterartifactId>
        <version>RELEASEversion>
        <scope>testscope>
    dependency>
dependencies>

建立连接

新建一个单元测试类,内容如下:

private Jedis jedis;

@BeforeEach
void setUp() {
    // 1.建立连接
    jedis = new Jedis("192.168.218.134", 6379);
   // jedis = JedisConnectionFactory.getJedis();
    // 2.设置密码
    jedis.auth("123456");
    // 3.选择库
    jedis.select(0);
}

测试:

@Test
void testString() {
    // 存入数据
    String result = jedis.set("name", "onenewcode");
    System.out.println("result = " + result);
    // 获取数据
    String name = jedis.get("name");
    System.out.println("name = " + name);
}

@Test
void testHash() {
    // 插入hash数据
    jedis.hset("user:1", "name", "Jack");
    jedis.hset("user:1", "age", "21");

    // 获取
    Map<String, String> map = jedis.hgetAll("user:1");
    System.out.println(map);
}

释放资源

@AfterEach
void tearDown() {
    if (jedis != null) {
        jedis.close();
    }
}

Jedis连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式

有关池化思想,并不仅仅是这里会使用,很多地方都有,比如说我们的数据库连接池,比如我们tomcat中的线程池,这些都是池化思想的体现。

创建Jedis的连接池
public class JedisConnectionFacotry {

     private static final JedisPool jedisPool;

     static {
         //配置连接池
         JedisPoolConfig poolConfig = new JedisPoolConfig();
         poolConfig.setMaxTotal(8);
         poolConfig.setMaxIdle(8);
         poolConfig.setMinIdle(0);
         poolConfig.setMaxWaitMillis(1000);
         //创建连接池对象
         jedisPool = new JedisPool(poolConfig,
                 "192.168.218.134",6379,1000,"123456");
     }

     public static Jedis getJedis(){
          return jedisPool.getResource();
     }
}

代码说明:

  • 1) JedisConnectionFacotry:工厂设计模式是实际开发中非常常用的一种设计模式,我们可以使用工厂,去降低代的耦合,比如Spring中的Bean的创建,就用到了工厂设计模式

  • 2)静态代码块:随着类的加载而加载,确保只能执行一次,我们在加载当前工厂类的时候,就可以执行static的操作完成对 连接池的初始化

  • 3)最后提供返回连接池中连接的方法.

改造原始代码

代码说明:

1.在我们完成了使用工厂设计模式来完成代码的编写之后,我们在获得连接时,就可以通过工厂来获得。

,而不用直接去new对象,降低耦合,并且使用的还是连接池对象。

2.当我们使用了连接池后,当我们关闭连接其实并不是关闭,而是将Jedis还回连接池的。

    @BeforeEach
    void setUp(){
        //建立连接
        /*jedis = new Jedis("127.0.0.1",6379);*/
        jedis = JedisConnectionFacotry.getJedis();
         //选择库
        jedis.select(0);
    }

   @AfterEach
    void tearDown() {
        if (jedis != null) {
            jedis.close();
        }
    }

Redis的Java客户端-SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:https://spring.io/projects/spring-data-redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK.JSON.字符串.Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

redis教程 二 redis客户端Jedis使用_第2张图片

快速入门

SpringBoot已经提供了对SpringDataRedis的支持,使用非常简,首先创建一个spring boot项目

导入pom坐标

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <groupId>com.onenewcodegroupId>
    <artifactId>MyRedisartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>MyRedisname>
    <description>MyRedisdescription>
    <properties>
        <java.version>17java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>3.0.2spring-boot.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>

        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-pool2artifactId>
        dependency>
        
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.30version>
        dependency>
    dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.8.1version>
                <configuration>
                    <source>17source>
                    <target>17target>
                    <encoding>UTF-8encoding>
                configuration>
            plugin>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>${spring-boot.version}version>
                <configuration>
                    <mainClass>com.onenewcode.myredis.MyRedisApplicationmainClass>
                    <skip>trueskip>
                configuration>
                <executions>
                    <execution>
                        <id>repackageid>
                        <goals>
                            <goal>repackagegoal>
                        goals>
                    execution>
                executions>
            plugin>
        plugins>
    build>

project>

配置文件

在application.yml文件下添加以下内容

spring:
  data:
    redis:
      host: 192.168.218.134
      port: 6379
      password: 123456
      lettuce:
        pool:
          max-active: 8  #最大连接
          max-idle: 8   #最大空闲连接
          min-idle: 0   #最小空闲连接
          max-wait: 100ms #连接等待时间

测试代码
@SpringBootTest
class MyRedisApplicationTests {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    void testString() {
        // 写入一条String数据
        redisTemplate.opsForValue().set("name", "onenewcode");
        // 获取string数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }
}

贴心小提示:SpringDataJpa使用起来非常简单,记住如下几个步骤即可

SpringDataRedis的使用步骤:

  • 引入spring-boot-starter-data-redis依赖
  • 在application.yml配置Redis信息
  • 注入RedisTemplate

目录结构

redis教程 二 redis客户端Jedis使用_第3张图片

数据序列化器

RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

redis教程 二 redis客户端Jedis使用_第4张图片

缺点:

  • 可读性差
  • 内存占用较大

我们可以自定义RedisTemplate的序列化方式,代码如下:

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = 
            							new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:

redis教程 二 redis客户端Jedis使用_第5张图片

整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。

StringRedisTemplate

尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,自动进行序列化时会负载多余的信息。

为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。

为了减少内存的消耗,我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就不需要在内存中就不用多存储数据,从而节约我们的内存空间
redis教程 二 redis客户端Jedis使用_第6张图片

这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。

省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:

@SpringBootTest
class MyRedisApplicationTests {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    // JSON工具
    private static final ObjectMapper mapper = new ObjectMapper();
    @Test
    void testString() {
        // 写入一条String数据
        redisTemplate.opsForValue().set("1", "onenewcode");
        // 获取string数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }
    @Test
    void testSaveUser() throws JsonProcessingException {
        // 创建对象
        User user = new User("onenewcode", 21);
        // 手动序列化
        String json = mapper.writeValueAsString(user);
        // 写入数据
        stringRedisTemplate.opsForValue().set("user:200", json);

        // 获取数据
        String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
        // 手动反序列化
        User user1 = mapper.readValue(jsonUser, User.class);
        System.out.println("user1 = " + user1);
    }
}

此时我们再来看一看存储的数据,小伙伴们就会发现那个class数据已经不在了,节约了我们的空间~

redis教程 二 redis客户端Jedis使用_第7张图片

最后小总结:

RedisTemplate的两种序列化实践方案:

  • 方案一:

    • 自定义RedisTemplate
    • 修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
  • 方案二:

    • 使用StringRedisTemplate
    • 写入Redis时,手动把对象序列化为JSON
    • 读取Redis时,手动把读取到的JSON反序列化为对象

Hash结构操作

在基础篇的最后,咱们对Hash结构操作一下,收一个小尾巴,这个代码咱们就不再解释啦

马上就开始新的篇章~~~进入到我们的Redis实战篇

@SpringBootTest
class RedisStringTests {

···
    @Test
    void testHash() {
        stringRedisTemplate.opsForHash().put("user:400", "name", "onenewcode");
        stringRedisTemplate.opsForHash().put("user:400", "age", "21");

        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400");
        System.out.println("entries = " + entries);
    }
}

项目仓库

https://github.com/onenewcode/MyRedis.git

你可能感兴趣的:(Spring,Boot整合,redis,数据库,缓存,笔记,java)