Jedis及SpringBoot整合

  • Post author:
  • Post category:其他


Jedis详解—Java通过原生API操作Redis


  1. 导入依赖
 <!--导入Jedis--> 
<dependency>
     <groupId>redis.clients</groupId>
         <artifactId>jedis</artifactId>
         <version>3.5.1</version>
 </dependency>
 <!--导入fastjson-->
 <dependency>
     <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.75</version>
</dependency>



2

. 连接步骤

  • 连接Redis服务器(指定主机+Redis服务端口号)
import redis.clients.jedis.Jedis;

/**
 * 饿汉式单例模式建造Redis连接工具
 */
public class ConnectionUtils {
    private static final String HOST = "localhost";
    private static final Integer PORT = 6379;
    private final static Jedis redis = new Jedis(HOST,PORT);

    public static Jedis getRedis(){
        return redis;
    }
}
  • 测试连接
public class JedisTest {

    static Jedis jedis = ConnectionUtils.getRedis();
    public static void main(String[] args) {
        System.out.println("========添加数据===========");
        addData();
        System.out.println("========获取数据===========");
        getData();
    }
    private static void addData(){
        //Stringl类型
        jedis.set("username","guaika");
        jedis.set("password","guaika0210");
        //List类型
        jedis.lpush("lKey","1","2","3","4");
        //Set类型
        jedis.sadd("sKey","s1","s2","s3","s4");
        //Hash类型
        Map<String,String> elements = new HashMap<>();
        elements.put("k1","v1");
        elements.put("k2","v2");
        jedis.hset("hKey",elements);
        //zset类型
        jedis.zadd("zKey",1,"z1");
        jedis.zadd("zKey",2,"z2");
        jedis.zadd("zKey",5,"z5");
    }
    private static void getData(){
        System.out.println("=======keys:"+jedis.keys("*"));
        System.out.println("=======String:【username:"+jedis.get("username")+"】-----【password:"+jedis.get("password")+"】");
        System.out.println("=======List:【"+jedis.lrange("lKey",0,-1).toString()+"】");
        System.out.println("弹出栈顶元素:"+jedis.lpop("lKey"));
        System.out.println("List:【"+jedis.lrange("lKey",0,-1).toString()+"】");
        System.out.println("=======Set:【"+jedis.smembers("sKey").toString()+"】");
        System.out.println("随机获取元素:"+jedis.srandmember("sKey",2).toString());
        System.out.println("随机删除元素:"+jedis.spop("sKey"));
        System.out.println("Set:【"+jedis.smembers("sKey").toString()+"】");
        System.out.println("=======Hash:【"+jedis.hgetAll("hKey")+"】");
        System.out.println("获取哈希表中指定字段的值:"+jedis.hget("hKey","k1"));
        System.out.println("删除指定字段:"+jedis.hdel("hKey","k1"));
        System.out.println("判断字段是否存在:k1【"+jedis.hexists("hKey","k1")+"】");
        System.out.println("Hash:【"+jedis.hgetAll("hKey")+"】");
        System.out.println("=======Zset:【"+jedis.zrange("zKey",0,-1)+"】");
        System.out.println("按照字段进行正序排序:"+jedis.zrangeByScore("zKey",Integer.MIN_VALUE,Integer.MAX_VALUE));
        System.out.println("按照字段进行逆序排序:"+jedis.zrevrangeByScore("zKey",Integer.MIN_VALUE,Integer.MAX_VALUE));
    }
}
  • 测试结果【控制台+Redis后台】

Java控制台查看

========添加数据===========
========获取数据===========
=======keys:[sKey, lKey, password, zKey, username, num, hKey]
=======String:【username:guaika】-----【password:guaika0210】
=======List:【[4, 3, 2, 1]】
弹出栈顶元素:4
List:【[3, 2, 1]】
=======Set:【[s4, s3, s1, s2]】
随机获取元素:[s4, s3]
随机删除元素:s1
Set:【[s4, s3, s2]】
=======Hash:【{k1=v1, k2=v2}】
获取哈希表中指定字段的值:v1
删除指定字段:1
判断字段是否存在:k1【false】
Hash:【{k2=v2}】
=======Zset:【[z1, z2, z5]】
按照字段进行正序排序:[z1, z2, z5]
按照字段进行逆序排序:[]

Redis后台查看

127.0.0.1:6379> keys *
    1) "username"
    2) "zKey"
    3) "num"
    4) "hKey"
    5) "password"
    6) "sKey"
    7) "lKey"

SpringBoot整合Redis


  • Springboot通过Spring-data-redis操作Redis;


  • Springboot2.x之后,原始Jedis被替换成了lettuce


  • Jedis和Lettuce的区别

    • Jedis 采用直连的方式,线程不安全,可以通过Jedis pool连接池来避免这种不安全性【BIO】
    • Lettuce 底层使用netty,实例可以在多个线程中共享,不存在线程不安全的情况【NIO】


整合步骤


  1. 导入依赖【spring-data-redis    lettuce-core】

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
      <groupId>io.lettuce</groupId>
      <artifactId>lettcue-core</artifactId>
      <version>6.0.2 RELEASE</version>        
</dependency>



2.

配置主机和端口号【在“application.properties”中】

#配置主机
spring.redis.host=localhost

#配置端口号
spring.redis.port=6379

3.

测试连接+测试结果


Springboot通过RedisTemplate模板引擎操作Redis,需要注入redisTemplate到Springboot中。

========测试代码=============

@SpringBootTest
class BootRedisApplicationTests {

    @Autowired
    @Qualifier("redisTemplate")
    //注入redisTemplate
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        redisTemplate.opsForValue().set("key1","value1");
        System.out.println("测试数据:"+redisTemplate.opsForValue().get("key1"));
    }
}



===========测试结果==========

测试数据:value1

自定义RedisTemplate


Redis一般通过JSON 字符串来传递对象,如果需要传递对象时,应该进行序列化!

======1.自定义RedisTemplate对对象进行序列化======

@Configuration
public class RedisConfig {
    //将自定义的template注册到springboot容器中
    @Bean
    public RedisTemplate<String, Object> template(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        //json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        
        //String序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //key采用string的序列化方式
        template.setKeySerializer(stringRedisSerializer);

        //hash的key采用String的序列化形式
        template.setHashKeySerializer(stringRedisSerializer);

        //value采用json序列化形式
        template.setValueSerializer(jackson2JsonRedisSerializer);

        //hash-value采用json序列化形式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }
}

========2.使用自定义的RedisTemplate========

class BootRedisApplicationTests {

    @Autowired
    @Qualifier("template")
    private RedisTemplate redisTemplate;
    @Test
    void contextLoads() {
        redisTemplate.opsForValue().set("key1","value1");
        redisTemplate.opsForValue().set("user",new User("guaika",25));
        System.out.println("测试数据:"+redisTemplate.opsForValue().get("key1"));
        System.out.println("测试数据:"+redisTemplate.opsForValue().get("user"));
    }
}

========3.测试结果==========

测试数据:value1
测试数据:User(name=guaika, age=25)


===扩展:IO体系设计===


  • 相关概念


    • 阻塞和非阻塞

      • 阻塞:调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回。

      • 非阻塞:在不能立刻得到结果之前,该调用不会阻塞当前线程。


    • 同步和异步

      • 同步:调用结果未返回之前,不能执行其他后续操作。

      • 异步:调用结果未返回之前,可以继续执行后续操作。该调用结果通过:监听状态、通知和回调来通知调用者结果。


    • 优势

      • 同步:按顺序处理请求,可以避免死锁和脏读发生。

      • 异步:发送请求不等待返回结果,可以提高运行效率,保证并发。


    • 并行和并发(是否同时进行)


      • 并行:(


        多个处理机


        )当一个


        CPU


        执行一个线程时,另一个


        CPU


        可以执行另一个线程,两个线程互不抢占


        CPU


        资源,可以同时进行。


      • 并发:(


        单个处理机





        同一时间段





        同一个处理机


        上运行多个处于已启动





        运行完毕状态之间的程序,任意时刻只有一个程序在处理机上运行。(来回切换,耗费


        CPU


        资源)。


  • 三种


    IO


    模式


    • BIO


      模式

      :同步阻塞I/O模式—–synchronous同步、blocking阻塞

      • 数据的读写必须阻塞在一个线程内等待完成。(

        示例:一排开水壶烧开水


    • NIO


      模式

      :同步非阻塞I/O模式—synchronous同步,non-blocking非阻塞

      • 数据的读写都是通过通道(channel)在缓冲区(buffer)中完成的,即是面向缓冲区的.

      • 应用场景:各种分布式、即时通信和中间件系统中。

        • Dubbo

        • Netty:Java开源NIO框架,提供异步、事件驱动的网络应用程序框架和工具,用于快速开发高性能和高可靠性的网络服务器和客户端程序。

        • Zookeeper


    • AIO


      模式

      :异步非阻塞I/O模式—asynchronous异步,non-blocking非阻塞



版权声明:本文为Guaike0210原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。