keycloak~EventListenerProvider初始化kafka引出的类加载问题

这篇具有很好参考价值的文章主要介绍了keycloak~EventListenerProvider初始化kafka引出的类加载问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

EventListenerProvider初始

keycloak提供的事件处理机制,可以通过实现EventListenerProvider接口来实现自定义的事件处理逻辑。在keycloak启动时,会通过ServiceLoader机制加载所有的EventListenerProvider实现类,并将其注册到keycloak的事件处理机制中。

  • 构造方法,在每个keycloak后台操作时,它都会重新构建实例
  • OnEvent方法,在事件发生时执行,不会出现类加载问题,因为这样类已经被加载了

EventListenerProviderFactory

EventListenerProviderFactory是进行事件处理器的生产工厂,用于创建EventListenerProvider实例。在keycloak启动时,会通过ServiceLoader机制加载所有的EventListenerProviderFactory实现类,并将其注册到keycloak的事件处理机制中。文章来源地址https://www.toymoban.com/news/detail-582626.html

  • init方法:keycloak启动时会执行,用于初始化EventListenerProviderFactory实例,可以在此方法中进行一些初始化操作。
  • postInit方法:keycloak启动时会执行,在init方法之后,会执行这个方法
  • create方法:在kc后台开启这个EventListenerProviderFactory之后,每次请求都会执行这个create方法,对于它生产的provider对象,可能考虑使用单例的方式, 避免每次请求都创建一个新的对象
  • close方法:在keycloak程序关闭后或者当前事件被注册时,这个方法才会执行

问题

  • 问题描述:在EventListenerProviderFactory的init方法中,通过kafka发送消息,会出现类加载问题,因为在keycloak启动时,kafka的类的加载器还没有被加载,所以会出现类加载问题。
  • 解决:需要将类加载器这块,修改成当前类加载器去加载对应的文件,如下代码解决了类无法加载的问题
  @Override
  public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
    try {
      this.executorService = Executors.newFixedThreadPool(2);
      Properties kafkaProperties = new Properties();
      kafkaProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
          ConfigFactory.getInstance().getStrPropertyValue("kafka.host"));
      kafkaProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "kc-ListenerProviderFactory");
      kafkaProperties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
      kafkaProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
      kafkaProperties.put(ConsumerConfig.HEARTBEAT_INTERVAL_MS_CONFIG, 1000);
      kafkaProperties.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 10 * 1000);
      kafkaProperties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 10);
      kafkaProperties.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, 30 * 1000);
      // 需要使用当前类加载器,否则会出现无法加载StringDeserializer的情况
      Class<?> stringDeserializerClass =
          getClass().getClassLoader().loadClass("org.apache.kafka.common.serialization.StringDeserializer");
      kafkaProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, stringDeserializerClass);
      kafkaProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, stringDeserializerClass);
      this.kafkaConsumerAdd = new KcKafkaConsumer(keycloakSessionFactory,kafkaProperties, "black_list_add");
      executorService.submit(kafkaConsumerAdd);
      this.kafkaConsumerRemove=new KcKafkaConsumer(keycloakSessionFactory,kafkaProperties, "black_list_remove");
      executorService.submit(kafkaConsumerRemove);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e);
    }
  }
  • 对于kafka-clients实现消费者的话,代码还是比较简单的
public class KcKafkaConsumer implements Runnable {
  private static final Logger logger = Logger.getLogger(ConfigFactory.class);
  private final AtomicBoolean closed = new AtomicBoolean(false);
  private final KeycloakSessionFactory keycloakSessionFactory;
  private KafkaConsumer<String, String> kafkaConsumer;

  public KcKafkaConsumer(KeycloakSessionFactory keycloakSessionFactory, Properties properties, String topic)
      throws ClassNotFoundException {
    this.keycloakSessionFactory = keycloakSessionFactory;
    this.kafkaConsumer = new KafkaConsumer<>(properties);
    this.kafkaConsumer.subscribe(Collections.singleton(topic));
  }

@Override
  public void run() {
    try {

      while (!closed.get()) {
        ConsumerRecords<String, String> records = kafkaConsumer.poll(Duration.ofMillis(100));
        // 处理Kafka消息
        for (ConsumerRecord<String, String> record : records) {
          System.out.println("Topic:" + record.topic() + ",Received message: " + record.value());
          //TODO: 处理Kafka消息的具体逻辑
        }
      }
    } finally {
      kafkaConsumer.close();
    }
  }
  public void shutdown() {
    closed.set(true);
    kafkaConsumer.close();
  }
}

到了这里,关于keycloak~EventListenerProvider初始化kafka引出的类加载问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux内存初始化-启动阶段的内存初始化

    本文代码基于ARM64平台, Linux kernel 5.15 在加载kernel 之前, kernel对于系统是有一定要求的,明确规定了boot阶段必须要把MMU关闭: 那么在进入kernel之后, 就必须有一个使能MMU, 建立映射的过程, 本文描述kernel启动阶段进行内存初始化相关的操作。 在初始化阶段,我们mapping二段

    2024年02月08日
    浏览(67)
  • 【温故而知新】JavaScript初始化/初始化加载

    在JavaScript中,对象、数组、函数、类等都可以通过不同的方式进行初始化。以下是几种常见的初始化方式: 对象初始化: 使用字面量方式: 使用构造函数方式: 数组初始化: 使用字面量方式: 使用构造函数方式: 函数初始化: 类初始化: 使用Array的of和from方法进行数组

    2024年01月24日
    浏览(54)
  • 深度学习参数初始化(二)Kaiming初始化 含代码

    目录 一、介绍 二、基础知识 三、Kaiming初始化的假设条件  四、Kaiming初始化的简单的公式推导 1.前向传播 2.反向传播 五、Pytorch实现 深度学习参数初始化系列: (一)Xavier初始化 含代码 (二)Kaiming初始化 含代码         Kaiming初始化论文地址:https://arxiv.org/abs/1502.01

    2024年02月04日
    浏览(62)
  • 【随机种子初始化】一个神经网络模型初始化的大坑

    半年前写了一个模型,取得了不错的效果(简称项目文件1),于是整理了一番代码,保存为了一个新的项目(简称项目文件2)。半年后的今天,我重新训练这个整理过的模型,即项目文件2,没有修改任何的超参数,并且保持完全一致的随机种子,但是始终无法完全复现出半

    2024年02月09日
    浏览(50)
  • 初始化磁盘选哪个格式 初始化磁盘分区形式选什么好

    在 初始化磁盘 之前,我们应该先明确什么时候需要初始化磁盘,通常是在电脑安装了SSD固态硬盘,计算机无法正常读取该固态硬盘时。或者需要腾空移动磁盘,以做它用时。那么初始化磁盘时,有哪些格式呢?如今主流的是NTFS格式。也有FAT 32格式,但读写性能会比较差。

    2024年02月09日
    浏览(35)
  • c# 初始化列表,并给列表里面所有的元素进行初始化

    Enumerable.Repeat 方法是用于生成一个包含指定元素重复若干次的序列。它接受两个参数,第一个参数是要重复的元素,第二个参数是重复次数。 下面是 Enumerable.Repeat 方法的用法和示例:

    2024年02月13日
    浏览(33)
  • 官答|初始化GreatSQL报错无法找到数据目录或初始化数据字典失败

    GreatSQL推出新栏目——官答 官答栏目针对GreatSQL数据库中的问题,选取官方论坛和讨论群中的典型提问进行深入解答。内容涵盖数据库安装部署、配置优化、故障排查、性能测试等方面。 在文章中,我们不仅提供解决方案,还会结合实例深入剖析问题的成因,提升读者对GreatSQL数据

    2024年02月04日
    浏览(53)
  • media设备节点初始化与Video4Linux初始化

    media_devnode_init函数是一个内核初始化函数,用于在Linux内核启动期间进行设备节点初始化。 函数的主要作用是创建媒体设备节点(device node)并将其注册到系统的设备树中。媒体设备节点用于表示媒体设备(如摄像头、音频设备等),它们在/dev目录下以特定的名称存在,并允

    2024年02月05日
    浏览(32)
  • C语言字符串初始化详解:用常量字符串进行字符数组初始化

    简介 字符串初始化 用常量字符串 初始化过程 示范代码 结论 在C语言中,字符串被定义为字符数组。字符串的初始化是指将一个常量字符串复制到字符数组中。本文将详细介绍字符串的初始化方法,并提供相应的示范代码。 在C语言中,有几种常用的方法可以用常量字符串来

    2024年02月15日
    浏览(37)
  • 数组初始化

    C语言中,数组初始化的方式主要有三种: 1、声明时,使用 {0} 初始化; 2、使用memset; 3、用for循环赋值。 那么,这三种方法的原理以及效率如何呢? 请看下面的测试代码: #define ARRAY_SIZE_MAX  (1*1024*1024)  void function1()  {      char array[ARRAY_SIZE_MAX] = {0};  //声明时使用{0}初始

    2024年02月14日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包