Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Quarkus集成redis,与Redisson数据互通(12)

Quarkus集成redis,与Redisson数据互通(12)

作者头像
kl博主
发布于 2023-11-18 05:14:24
发布于 2023-11-18 05:14:24
41100
代码可运行
举报
文章被收录于专栏:kl的专栏kl的专栏
运行总次数:0
代码可运行

前言

博主所在公司大量使用了redis缓存,redis客户端用的Redisson。在Quarkus集成redis时,博主尝试使用Redisson客户端直接集成,发现,在jvm模式下运行quarkus没点问题,但是在打native image时,就报错了,尝试了很多方式都是莫名其妙的异常。最后决定采用quarkus官方的redis客户端,但是Redisson客户端数据序列化方式是特有的,不是简单的String,所以quarkus中的redis需要操作Redisson的数据,就要保持序列化方式一致,本文就是为了解决这个问题。

Quarkus版本:1.7.0.CR1

集成redis

首先你的quarkus版本一定要1.7.0.CR1版本及以上才行,因为redis的扩展包是这个版本才发布的,添加依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-redis-client</artifactId>
        </dependency>

新增redis链接配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
quarkus.redis.hosts=127.0.0.1:6379
quarkus.redis.database=0
quarkus.redis.timeout=10s
quarkus.redis.password=sasa

复制Redisson序列化

Redisson里内置了很多的序列化方式,我们用的JsonJacksonCodec,这里将Redisson中的实现复制后,稍加改动,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 和Redisson的序列化数据互相反序列化的编解码器
 * @author keking
 */
public class JsonJacksonCodec{

    public static final JsonJacksonCodec INSTANCE = new JsonJacksonCodec();

    @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
    @JsonAutoDetect(fieldVisibility = Visibility.ANY,
                    getterVisibility = Visibility.PUBLIC_ONLY,
                    setterVisibility = Visibility.NONE,
                    isGetterVisibility = Visibility.NONE)
    public static class ThrowableMixIn {

    }
    protected final ObjectMapper mapObjectMapper;

    public JsonJacksonCodec() {
        this(new ObjectMapper());
    }

    public JsonJacksonCodec(ObjectMapper mapObjectMapper) {
        this.mapObjectMapper = mapObjectMapper.copy();
        init(this.mapObjectMapper);
        initTypeInclusion(this.mapObjectMapper);
    }

    protected void initTypeInclusion(ObjectMapper mapObjectMapper) {
        TypeResolverBuilder<?> mapTyper = new DefaultTypeResolverBuilder(DefaultTyping.NON_FINAL) {
            @Override
            public boolean useForType(JavaType t) {
                switch (_appliesFor) {
                case NON_CONCRETE_AND_ARRAYS:
                    while (t.isArrayType()) {
                        t = t.getContentType();
                    }
                    // fall through
                case OBJECT_AND_NON_CONCRETE:
                    return (t.getRawClass() == Object.class) || !t.isConcrete();
                case NON_FINAL:
                    while (t.isArrayType()) {
                        t = t.getContentType();
                    }
                    // to fix problem with wrong long to int conversion
                    if (t.getRawClass() == Long.class) {
                        return true;
                    }
                    if (t.getRawClass() == XMLGregorianCalendar.class) {
                        return false;
                    }
                    return !t.isFinal(); // includes Object.class
                default:
                    // case JAVA_LANG_OBJECT:
                    return t.getRawClass() == Object.class;
                }
            }
        };
        mapTyper.init(JsonTypeInfo.Id.CLASS, null);
        mapTyper.inclusion(JsonTypeInfo.As.PROPERTY);
        mapObjectMapper.setDefaultTyping(mapTyper);
    }

    protected void init(ObjectMapper objectMapper) {
        objectMapper.setSerializationInclusion(Include.NON_NULL);
        objectMapper.setVisibility(objectMapper.getSerializationConfig()
                                                    .getDefaultVisibilityChecker()
                                                        .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                                                        .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                                                        .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                                                        .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.enable(Feature.WRITE_BIGDECIMAL_AS_PLAIN);
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        objectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
        objectMapper.addMixIn(Throwable.class, ThrowableMixIn.class);
    }

    /**
     * 解码器
     * @param val
     * @return
     */
    public Object decoder(String val){
        try {
            ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
            try (ByteBufOutputStream os = new ByteBufOutputStream(buf)) {
                os.write(val.getBytes());
            }
            return mapObjectMapper.readValue((InputStream) new ByteBufInputStream(buf), Object.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 编码器
     * @param obj
     * @return
     */
    public String encoder(Object obj){
        ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
        try {
            ByteBufOutputStream os = new ByteBufOutputStream(out);
            mapObjectMapper.writeValue((OutputStream) os, obj);
            return os.buffer().toString(StandardCharsets.UTF_8);
        } catch (IOException e) {
            out.release();
        }
        return null;
    }
}

使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Dependent
@Startup
public class Test {
    @Inject
    RedisClient redisClient;
    @Inject
    Logger logger;

    void initializeApp(@Observes StartupEvent ev) {
        //使用JsonJacksonCodec编解码,保持和redisson互通
        JsonJacksonCodec codec = JsonJacksonCodec.INSTANCE;
        Map<String, String> map = new HashMap<>();
        map.put("key","666");
        redisClient.set(Arrays.asList("AAAKEY", codec.encoder(map)));

        String str = redisClient.get("AAAKEY").toString(StandardCharsets.UTF_8);
        Map<String,String> getVal = (Map<String, String>) codec.decoder(str);
        logger.info(getVal.get("key"));
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-08-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
redisson序列化采坑那些事儿
如果对springcloud-gateway有了解的同学,应该会知道springcloud-gateway默认提供了一个基于内存的路由定义仓库。
lyb-geek
2024/03/12
6920
redisson序列化采坑那些事儿
RedisTemplate基本配置类
RedisConfig import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.ja
benym
2023/05/18
9880
spring boot redis 缓存_redis本地缓存
查询操作是应用中最常见的操作,如果每次查询都从 MySQL 中查询则会影响效率,通常需要引入缓存来实现查询性能的优化。缓存可以选择本地缓存,远程缓存或本地缓存结合远程缓存。本地缓存可以使用 Guava 或 Caffeine 提供的解决方案,而远程缓存则可以选择 Redis 这样的内存数据库。本文记录一下 SpringBoot 集成 Redis 做缓存的相关配置。
全栈程序员站长
2022/09/30
2.3K0
springboot集成了哪些框架_redis java客户端
使用注解进行缓存操作涉及CacheManage RedisCacheManager源码
全栈程序员站长
2022/11/08
1.2K0
Redis - Spring Data Redis 操作 Jedis 、Lettuce 、 Redisson
https://spring.io/projects/spring-data-redis
小小工匠
2021/08/17
2.7K0
SpringCache基本配置类
benym
2024/05/18
1160
SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)
共同点:都提供了基于Redis操作的Java API,只是封装程度,具体实现稍有不同。
架构师修炼
2021/09/10
4.1K0
SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)
Springboot中的redis配置类
简单记录一下 首先依赖: <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- spring2.X集成redis所需common-pool2-->
Tom2Code
2022/11/21
7080
SpringBoot整合redis
前言 使用注解实现Redis缓存功能的具体代码 1 引入jar包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 2 添加配置 spring.redis.host=xxxxxxx spring.redis.port=6379 // 如
在水一方
2022/10/04
3140
springboot高级特性-redis作为缓存
springboot版本为2.5.4 redis版本 3.2 引入starter
暴躁的程序猿
2022/03/23
4340
springboot高级特性-redis作为缓存
Redis---整合SpringBoot篇
Redis6 1、引入redis相关依赖 2、application.properties配置redis配置 3.添加redis配置类 4.测试一下 RedisTemplate基本使用如下 ---- 1、引入redis相关依赖 <!-- redis的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </depende
大忽悠爱学习
2021/11/15
3130
SpringBoot集成Redis引起的序列化问题
想必大家对SpringBoot可能已经很熟悉了,包括集成Redis这种常用的技术,之前一直用一贯的写法去集成Redis,写配置类没发现过任何问题,但是上周在给Redis配置类加了一个Bean之后就出现了很难发现的问题。
一个程序员的成长
2020/11/25
1.5K0
Redis乱码配置
package com.zr.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.
P轴
2022/11/28
1K0
Redis乱码配置
SpringBoot 整合 Redis
因为 Redis 有 这5种基本数据结构类型分别为:String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。
收心
2022/01/17
4010
SpringBoot 整合 Redis
redis过期监听
今天写拼团功能,如果24小时后还没有人满,则此次拼团就失败了,那么这里我用redis过期监听来实现,键过期去处理订单状态等业务
adu
2022/10/30
2.4K0
redis过期监听
2 Springboot中使用redis,配置redis的key value生成策略
上一篇里讲过了redis在spring boot中的简单使用,对于单个对象的增删改查的默认操作。
天涯泪小武
2019/01/17
4K2
Sprint Boot 集成 Redis  介绍及开发
Redis是一个内存数据存储,可以用作用作数据库,缓存和消息代理。它支持数据结构,例如字符串,哈希,列表,集合,带范围查询的排序集合,位图,日志,带有半径查询和流的地理空间索引。Redis具有内置的复制,Lua脚本,LRU逐出,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供了高可用性。
Freedom123
2024/03/29
1470
【SpringBoot】34、SpringBoot整合Redis实现序列化存储Java对象
前面我们已经介绍过【SpringBoot】十七、SpringBoot 中整合 Redis,我们可以看出,在 SpringBoot 对 Redis 做了一系列的自动装配,使用还是非常方便的
全栈程序员站长
2022/06/25
1.1K0
【SpringBoot】34、SpringBoot整合Redis实现序列化存储Java对象
高性能/并发的保证-Netty在Redisson的应用
​ Redisson Github: https://github.com/redisson/redisson
sanshengshui
2020/04/14
2.7K0
SpringBoot集成Redis缓存
https://www.cnblogs.com/noneplus/p/11532065.html
Noneplus
2019/09/24
6130
SpringBoot集成Redis缓存
相关推荐
redisson序列化采坑那些事儿
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验