redis基础(2)

简介: redis基础

redis基础(1)https://developer.aliyun.com/article/1530751

四,在java中操作redis

Redis的Java客户端很多,官方推荐的有三种:.

  • Jedis
  • Lettuce
  • Redisson
    Spring对Redis客户端进行了整合,提供了Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即spring-boot-starter-data-redis

jedis

<dependency>  
    <groupId>redis.clients</groupId>  
    <artifactId>jedis</artifactId>  
    <version>3.7.0</version>  
</dependency>
<dependency>
<groupid>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</ artifactId>
    <version>5.7.0</version>
<scope>test</ scope>
</dependency>

使用Jedis操作Redis的步骤:

  1. 获取连接
private Jedis jedis;
@BeforeEach
void setUp() {
//建立连接
jedis = new Jedis ( "192.168.150.101",6379);
//设置密码
jedis.auth ( "123321");
//选择库
jedis.select(0);
}
  1. 执行操作
@Test
void testString() {
//插入数据,方法名称就是redis命令名称,非常简单
 String result = jedis.set( "name","张三");
System.out.println( "result " +result) ;
    //获取数据
String name = jedis.get( "name" ) ;
system.out.println ( "name = " + name) ;
}
  1. 关闭连接
@AfterEach
void tearDown() {
//释放资源
if (jedis != null) {
  jedis.close();
}
}

Jedis连接池

public class JedisconnectionFactory {
private static final JedisPool jedisPool;
static {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();//最大连接
jedisPoolConfig.setMaxTotal(8);//最大空闲连接
jedisPoolConfig.setMaxIdle(8);//最小空闲连接
jedisPoolConfig.setMinIdle(0);//设置最长等待时间,ms
jedisPoolConfig.setMaxwaitMillis(200);
jedisPool = new JedisPool(jedisPoolConfig,"192.168.150.101",6379,
1000,"123321");
}
//获取Jedis对象
public static Jedis getJedis(){
return jedisPool.getResource();
}

Spring Data Redis

SpringData是Spring中数据操作的模块包含对各种数据库的集成,其中对Redis的集成就是SpringData Redis

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

导入坐标

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-data-redis</artifactId>  
</dependency>\
<!--连接池依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</ artifactId>
 </ dependency>

Spring Data Redis中提供了一个高度封装的类: RedisTemplate,针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

ValueOperations:简单K-V操作

SetOperations: set类型数据操作

ZSetOperations: zset类型数据操作

HashOperations:针对map类型的数据操作

ListOperations:针对list类型的数据操作

spring:  
  redis:  
    host: localhost  
    port: 6379  
    #passworld : 123456
    database: 0  
    jedis:  
      pool:  
        max-active: 8 #最大连接数  
        max-wait: 1ms #连接池最大阻塞等待时间  
        max-idle: 4  #连接池最大空闲时间  
        min-idle: 0  #连接池中的最小空闲连接

测试

@SpringBootTest(classes = ReggieApplication.class)  
@RunWith(SpringRunner.class)  
 public class test{  
    @Autowired  
    private RedisTemplate redisTemplate;  
  
    @Test  
    public  void test() {  
        ValueOperations valueOperations = redisTemplate.opsForValue();  
        valueOperations.set("city","beijing");  
  
  
  
    }  
}

需要配置一下

不然会序列化成这样

自定义序列化

RedisTemplate可以接收任意Object作为值写入Redis:

只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

缺点:

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

一般来说序列化string类型用String序列化器,用对象类型的时候用JSON序列化器

@Configuration  
public class RedisConfig extends CachingConfigurerSupport {  
    @Bean  
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {  
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();  
        //默认的Key序列化器为:JdkSerializationRedisSerializer  
        redisTemplate.setKeySerializer(new StringRedisSerializer());  
        redisTemplate.setConnectionFactory(connectionFactory);  
        return redisTemplate;  
    }  
}

我们可以自定义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序列化方式。最终结果如图:

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

StringRedisTemplate

为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

也就是我们手动转JSON存入redis而不是JSON序列化器帮我们转

因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了。

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

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

@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON序列化工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
    // 创建对象
    User user = new User("虎哥", 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);
}

操控string类型的数据

@SpringBootTest(classes = ReggieApplication.class)  
@RunWith(SpringRunner.class)  
 public class test{  
    @Autowired  
    private RedisTemplate redisTemplate;  
  
    @Test  
    public  void test() {  
        ValueOperations valueOperations = redisTemplate.opsForValue();  
        valueOperations.set("city","beijing");  
        String city = (String) valueOperations.get("city");  
        System.out.println(city);  
        //设置过期时间  
        valueOperations.set("key1","value1",101, TimeUnit.MILLISECONDS);  
        //不存在则设置  
        valueOperations.setIfAbsent("city124", "苏州");  
          
    }  
}
相关文章
|
存储 关系型数据库 MySQL
ES和mysql的区别
ES和mysql的区别
|
NoSQL Redis 数据安全/隐私保护
Docker安装redis(保姆级教程&图文并茂)
Docker安装redis(保姆级教程&图文并茂)
Docker安装redis(保姆级教程&图文并茂)
|
设计模式
趣解设计模式之《当代毕加索小王》
趣解设计模式之《当代毕加索小王》
129 0
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
本文是Java基础的进阶篇,对异常、集合、泛型、Java8新特性、I/O流等知识进行深入浅出的介绍,并附有对应的代码示例,重要的地方带有对性能、底层原理、源码的剖析。适合Java初学者。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
|
前端开发 JavaScript Java
如何使用 Spring Boot 和 Angular 开发全栈应用程序:全面指南
如何使用 Spring Boot 和 Angular 开发全栈应用程序:全面指南
524 1
|
JavaScript Java 测试技术
基于SpringBoot+Vue的城市公交调度系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的城市公交调度系统的详细设计和实现(源码+lw+部署文档+讲解等)
208 5
|
存储 前端开发 数据库
MVC模式和三层架构
MVC模式和三层架构
|
存储 Prometheus 监控
Java后端服务的监控与日志管理
Java后端服务的监控与日志管理
|
前端开发 JavaScript
基于Html对父页面打开子页面Dialog()的使用
作者在使用基于QUI的前端项目中遇到一个问题:无法在Dialog组件中提交后刷新列表页面。经过搜索和努力,找到了解决方案。通过创建新的`top.Dialog()`,设置相关属性如标题、URL、尺寸,并在OK事件中调用子页面的提交方法及刷新列表的方法实现了需求。提供的代码示例展示了如何打开编辑窗体并处理提交事件以刷新列表。
269 0
|
Java Android开发
【dbeaver】IDEA 运行 dbeaver源码
【dbeaver】IDEA 运行 dbeaver源码
1656 1

热门文章

最新文章