准备工作

kafka版本:kafka_2.10-0.10.1.0

spring版本:spring4.3

配置文件

pom文件配置(也可以直接下载jar包)

Kafka和spring集成的支持类库,spring和kafka通信监听

  1. <dependency>
  2.   <groupId>org.springframework.integration</groupId>
  3.   <artifactId>spring-integration-kafka</artifactId>
  4.   <version>1.3.0.RELEASE</version>
  5. </dependency>

kafka发送消息以及接受消息使用的类库

  1. <dependency>
  2. <groupId>org.apache.kafka</groupId>
  3. <artifactId>kafka-clients</artifactId>
  4. <version>0.10.1.0</version>
  5. </dependency>

使用高版本是因为低版本无法支持kafka监听,spring和kafka集成不好

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-webmvc</artifactId>
  4. <version>4.3.0.RELEASE</version>
  5. </dependency>

kafka自带监听器,依赖于spring,所以需要和pring-integration-kafka结合使用

  1. <dependency>
  2. <groupId>org.springframework.kafka</groupId>
  3. <artifactId>spring-kafka</artifactId>
  4. <version>1.0.0.RC1</version>
  5. </dependency>

producer配置

  1.如果你的topic没有设置名称,按照默认的topic的名字生成对应的数据文件夹。

  2.producerListener用来判断kafka发送数据是否成功以及发送反馈信息。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd
  6. http://www.springframework.org/schema/context
  7. http://www.springframework.org/schema/context/spring-context.xsd">
  8.  
  9. <!-- 定义producer的参数 -->
  10. <bean id="producerProperties" class="java.util.HashMap">
  11. <constructor-arg>
  12. <map>
  13. <entry key="bootstrap.servers" value="localhost:7000" />
  14. <entry key="group.id" value="0" />
  15. <entry key="retries" value="1" />
  16. <entry key="batch.size" value="16384" />
  17. <entry key="linger.ms" value="1" />
  18. <entry key="buffer.memory" value="33554432" />
  19. <entry key="key.serializer"
  20. value="org.apache.kafka.common.serialization.StringSerializer" />
  21. <entry key="value.serializer"
  22. value="org.apache.kafka.common.serialization.StringSerializer" />
  23. </map>
  24. </constructor-arg>
  25. </bean>
  26.  
  27. <!-- 创建kafkatemplate需要使用的producerfactory bean -->
  28. <bean id="producerFactory"
  29. class="org.springframework.kafka.core.DefaultKafkaProducerFactory">
  30. <constructor-arg>
  31. <ref bean="producerProperties" />
  32. </constructor-arg>
  33. </bean>
  34.  
  35. <!-- 创建kafkatemplate bean,使用的时候,只需要注入这个bean,即可使用template的send消息方法 -->
  36. <bean id="KafkaTemplate" class="org.springframework.kafka.core.KafkaTemplate">
  37. <constructor-arg ref="producerFactory" />
  38. <constructor-arg name="autoFlush" value="true" />
  39. <property name="defaultTopic" value="defaultTopic" />
  40. <property name="producerListener" ref="producerListener"/>
  41. </bean>
  42.  
  43. <bean id="producerListener" class="com.git.kafka.producer.KafkaProducerListener" />
  44. </beans>

consumer配置

  1.使用kafka的listener进行消息消费监听,如果有消费消息进入会自动调用OnMessage方法进行消息消费以及后续业务处理。

  2.如果要配置多个topic,需要创建新的消费者容器,然后统一指向listner的消息处理类,统一让这个类进行后续业务处理。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  7. http://www.springframework.org/schema/tx
  8. http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  9. http://www.springframework.org/schema/jee
  10. http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
  11. http://www.springframework.org/schema/context
  12. http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  13.  
  14. <!-- 定义consumer的参数 -->
  15. <bean id="consumerProperties" class="java.util.HashMap">
  16. <constructor-arg>
  17. <map>
  18. <entry key="bootstrap.servers" value="127.0.0.1:7000"/>
  19. <entry key="group.id" value="0"/>
  20. <entry key="enable.auto.commit" value="false"/>
  21. <entry key="auto.commit.interval.ms" value="1000"/>
  22. <entry key="session.timeout.ms" value="15000"/>
  23. <entry key="key.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer"/>
  24. <entry key="value.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer"/>
  25. </map>
  26. </constructor-arg>
  27. </bean>
  28.  
  29. <!-- 创建consumerFactory bean -->
  30. <bean id="consumerFactory" class="org.springframework.kafka.core.DefaultKafkaConsumerFactory">
  31. <constructor-arg>
  32. <ref bean="consumerProperties"/>
  33. </constructor-arg>
  34. </bean>
  35.  
  36. <!-- 实际执行消息消费的类 -->
  37. <bean id="messageListernerConsumerService" class="com.git.kafka.consumer.KafkaConsumerServer"/>
  38.  
  39. <!-- 消费者容器配置信息 -->
  40. <bean id="containerProperties_trade" class="org.springframework.kafka.listener.config.ContainerProperties">
  41. <constructor-arg value="order_test_topic"/>
  42. <property name="messageListener" ref="messageListernerConsumerService"/>
  43. </bean>
  44. <bean id="containerProperties_other" class="org.springframework.kafka.listener.config.ContainerProperties">
  45. <constructor-arg value="other_test_topic"/>
  46. <property name="messageListener" ref="messageListernerConsumerService"/>
  47. </bean>
  48.  
  49. <!-- 创建messageListenerContainer bean,使用的时候,只需要注入这个bean -->
  50. <bean id="messageListenerContainer_trade" class="org.springframework.kafka.listener.KafkaMessageListenerContainer"
  51. init-method="doStart">
  52. <constructor-arg ref="consumerFactory"/>
  53. <constructor-arg ref="containerProperties_trade"/>
  54. </bean>
  55.  
  56. <bean id="messageListenerContainer_other" class="org.springframework.kafka.listener.KafkaMessageListenerContainer"
  57. init-method="doStart">
  58. <constructor-arg ref="consumerFactory"/>
  59. <constructor-arg ref="containerProperties_other"/>
  60. </bean>
  61.  
  62. </beans>

applicationContext配置

  1. <import resource="classpath:kafkaConsumer.xml" />
  2. <import resource="classpath:kafkaProducer.xml" />

具体实现

constant.java  //常量类

  1. package com.git.kafka.constant;
  2.  
  3. /**
  4. * kafkaMessageConstant
  5. * @author wangb
  6. *
  7. */
  8. public class KafkaMesConstant {
  9.  
  10. public static final String SUCCESS_CODE = "00000";
  11. public static final String SUCCESS_MES = "成功";
  12.  
  13. /*kakfa-code*/
  14. public static final String KAFKA_SEND_ERROR_CODE = "30001";
  15. public static final String KAFKA_NO_RESULT_CODE = "30002";
  16. public static final String KAFKA_NO_OFFSET_CODE = "30003";
  17.  
  18. /*kakfa-mes*/
  19. public static final String KAFKA_SEND_ERROR_MES = "发送消息超时,联系相关技术人员";
  20. public static final String KAFKA_NO_RESULT_MES = "未查询到返回结果,联系相关技术人员";
  21. public static final String KAFKA_NO_OFFSET_MES = "未查到返回数据的offset,联系相关技术人员";
  22.  
  23. }

KafkaConsumerServer.java  //消费者监听

  1. package com.git.kafka.consumer;
  2.  
  3. import org.apache.kafka.clients.consumer.ConsumerRecord;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.kafka.listener.MessageListener;
  7.  
  8. /**
  9. * kafka监听器启动
  10. * 自动监听是否有消息需要消费
  11. * @author wangb
  12. *
  13. */
  14. public class KafkaConsumerServer implements MessageListener<String, String> {
  15. protected final Logger LOG = LoggerFactory.getLogger("kafkaConsumer");
  16. /**
  17. * 监听器自动执行该方法
  18. * 消费消息
  19. * 自动提交offset
  20. * 执行业务代码
  21. * (high level api 不提供offset管理,不能指定offset进行消费)
  22. */
  23. @Override
  24. public void onMessage(ConsumerRecord<String, String> record) {
  25. LOG.info("=============kafkaConsumer开始消费=============");
  26. String topic = record.topic();
  27. String key = record.key();
  28. String value = record.value();
  29. long offset = record.offset();
  30. int partition = record.partition();
  31. LOG.info("-------------topic:"+topic);
  32. LOG.info("-------------value:"+value);
  33. LOG.info("-------------key:"+key);
  34. LOG.info("-------------offset:"+offset);
  35. LOG.info("-------------partition:"+partition);
  36. LOG.info("~~~~~~~~~~~~~kafkaConsumer消费结束~~~~~~~~~~~~~");
  37. }
  38.  
  39. }

kafkaProducerListener.java  //生产者监听-打印日志

  1. package com.git.kafka.producer;
  2.  
  3. import org.apache.kafka.clients.producer.RecordMetadata;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.kafka.support.ProducerListener;
  7.  
  8. /**
  9. * kafkaProducer监听器,在producer配置文件中开启
  10. * @author wangb
  11. *
  12. */
  13. @SuppressWarnings("rawtypes")
  14. public class KafkaProducerListener implements ProducerListener{
  15. protected final Logger LOG = LoggerFactory.getLogger("kafkaProducer");
  16. /**
  17. * 发送消息成功后调用
  18. */
  19. @Override
  20. public void onSuccess(String topic, Integer partition, Object key,
  21. Object value, RecordMetadata recordMetadata) {
  22. LOG.info("==========kafka发送数据成功(日志开始)==========");
  23. LOG.info("----------topic:"+topic);
  24. LOG.info("----------partition:"+partition);
  25. LOG.info("----------key:"+key);
  26. LOG.info("----------value:"+value);
  27. LOG.info("----------RecordMetadata:"+recordMetadata);
  28. LOG.info("~~~~~~~~~~kafka发送数据成功(日志结束)~~~~~~~~~~");
  29. }
  30.  
  31. /**
  32. * 发送消息错误后调用
  33. */
  34. @Override
  35. public void onError(String topic, Integer partition, Object key,
  36. Object value, Exception exception) {
  37. LOG.info("==========kafka发送数据错误(日志开始)==========");
  38. LOG.info("----------topic:"+topic);
  39. LOG.info("----------partition:"+partition);
  40. LOG.info("----------key:"+key);
  41. LOG.info("----------value:"+value);
  42. LOG.info("----------Exception:"+exception);
  43. LOG.info("~~~~~~~~~~kafka发送数据错误(日志结束)~~~~~~~~~~");
  44. exception.printStackTrace();
  45. }
  46.  
  47. /**
  48. * 方法返回值代表是否启动kafkaProducer监听器
  49. */
  50. @Override
  51. public boolean isInterestedInSuccess() {
  52. LOG.info("///kafkaProducer监听器启动///");
  53. return true;
  54. }
  55.  
  56. }

KafkaProducerServer.java  //生产者

  1. package com.git.kafka.producer;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import java.util.Random;
  6. import java.util.concurrent.ExecutionException;
  7.  
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.kafka.core.KafkaTemplate;
  10. import org.springframework.kafka.support.SendResult;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.util.concurrent.ListenableFuture;
  13.  
  14. import com.alibaba.fastjson.JSON;
  15. import com.git.kafka.constant.KafkaMesConstant;
  16.  
  17. /**
  18. * kafkaProducer模板
  19. * 使用此模板发送消息
  20. * @author wangb
  21. *
  22. */
  23. @Component
  24. public class KafkaProducerServer{
  25.  
  26. @Autowired
  27. private KafkaTemplate<String, String> kafkaTemplate;
  28.  
  29. /**
  30. * kafka发送消息模板
  31. * @param topic 主题
  32. * @param value messageValue
  33. * @param ifPartition 是否使用分区 0是\1不是
  34. * @param partitionNum 分区数 如果是否使用分区为0,分区数必须大于0
  35. * @param role 角色:bbc app erp...
  36. */
  37. public Map<String,Object> sndMesForTemplate(String topic, Object value, String ifPartition,
  38. Integer partitionNum, String role){
  39. String key = role+"-"+value.hashCode();
  40. String valueString = JSON.toJSONString(value);
  41. if(ifPartition.equals("0")){
  42. //表示使用分区
  43. int partitionIndex = getPartitionIndex(key, partitionNum);
  44. ListenableFuture<SendResult<String, String>> result = kafkaTemplate.send(topic, partitionIndex, key, valueString);
  45. Map<String,Object> res = checkProRecord(result);
  46. return res;
  47. }else{
  48. ListenableFuture<SendResult<String, String>> result = kafkaTemplate.send(topic, key, valueString);
  49. Map<String,Object> res = checkProRecord(result);
  50. return res;
  51. }
  52. }
  53.  
  54. /**
  55. * 根据key值获取分区索引
  56. * @param key
  57. * @param partitionNum
  58. * @return
  59. */
  60. private int getPartitionIndex(String key, int partitionNum){
  61. if (key == null) {
  62. Random random = new Random();
  63. return random.nextInt(partitionNum);
  64. }
  65. else {
  66. int result = Math.abs(key.hashCode())%partitionNum;
  67. return result;
  68. }
  69. }
  70.  
  71. /**
  72. * 检查发送返回结果record
  73. * @param res
  74. * @return
  75. */
  76. @SuppressWarnings("rawtypes")
  77. private Map<String,Object> checkProRecord(ListenableFuture<SendResult<String, String>> res){
  78. Map<String,Object> m = new HashMap<String,Object>();
  79. if(res!=null){
  80. try {
  81. SendResult r = res.get();//检查result结果集
  82. /*检查recordMetadata的offset数据,不检查producerRecord*/
  83. Long offsetIndex = r.getRecordMetadata().offset();
  84. if(offsetIndex!=null && offsetIndex>=0){
  85. m.put("code", KafkaMesConstant.SUCCESS_CODE);
  86. m.put("message", KafkaMesConstant.SUCCESS_MES);
  87. return m;
  88. }else{
  89. m.put("code", KafkaMesConstant.KAFKA_NO_OFFSET_CODE);
  90. m.put("message", KafkaMesConstant.KAFKA_NO_OFFSET_MES);
  91. return m;
  92. }
  93. } catch (InterruptedException e) {
  94. e.printStackTrace();
  95. m.put("code", KafkaMesConstant.KAFKA_SEND_ERROR_CODE);
  96. m.put("message", KafkaMesConstant.KAFKA_SEND_ERROR_MES);
  97. return m;
  98. } catch (ExecutionException e) {
  99. e.printStackTrace();
  100. m.put("code", KafkaMesConstant.KAFKA_SEND_ERROR_CODE);
  101. m.put("message", KafkaMesConstant.KAFKA_SEND_ERROR_MES);
  102. return m;
  103. }
  104. }else{
  105. m.put("code", KafkaMesConstant.KAFKA_NO_RESULT_CODE);
  106. m.put("message", KafkaMesConstant.KAFKA_NO_RESULT_MES);
  107. return m;
  108. }
  109. }
  110.  
  111. }

KafkaProducerTest.java  //kafka生产者测试(消费者使用spring启动监听,自动执行onMessage方法)

  1. package com.git.test;
  2.  
  3. import java.util.Map;
  4.  
  5. import com.git.kafka.producer.KafkaProducerServer;
  6.  
  7. public class KafkaProducerTest {
  8. public static void main(String[] args) {
  9.  
  10. KafkaProducerServer kafkaProducer = new KafkaProducerServer();
  11. String topic = "orderTopic";
  12. String value = "test";
  13. String ifPartition = "0";
  14. Integer partitionNum = 3;
  15. String role = "test";//用来生成key
  16. Map<String,Object> res = kafkaProducer.sndMesForTemplate
  17. (topic, value, ifPartition, partitionNum, role);
  18.  
  19. System.out.println("测试结果如下:===============");
  20. String message = (String)res.get("message");
  21. String code = (String)res.get("code");
  22.  
  23. System.out.println("code:"+code);
  24. System.out.println("message:"+message);
  25. }
  26. }

具体项目代码

项目地址:https://git.oschina.net/wsmd/kafka-0.10-demo

kafka与Spring的集成的更多相关文章

  1. Spring boot 集成Kafka

    搭建Kafka集群,参考: https://www.cnblogs.com/jonban/p/kafka.html 源码示例如下: 1.新建 Maven 项目 kafka 2.pom.xml < ...

  2. Kafka 入门和 Spring Boot 集成

    目录 Kafka 入门和 Spring Boot 集成 标签:博客 概述 应用场景 基本概念 基本结构 和Spring Boot 集成 集成概述 集成环境 kafka 环境搭建 Spring Boot ...

  3. Spring 对Apache Kafka的支持与集成

    1. 引言 Apache Kafka 是一个分布式的.容错的流处理系统.在本文中,我们将介绍Spring对Apache Kafka的支持,以及原生Kafka Java客户端Api 所提供的抽象级别. ...

  4. quartz与spring进行集成

    上一篇将了quartz框架的使用,spring同样也提供了对quartz的集成.这次就尝试一下在spring中集成quartz. 要在spring中使用job,Trigger和Scheduler,就要 ...

  5. 在Spring下集成ActiveMQ

    1.参考文献 Spring集成ActiveMQ配置 Spring JMS异步发收消息 ActiveMQ 2.环境 在前面的一篇ActiveMQ入门实例中我们实现了消息的异步传送,这篇博文将如何在spr ...

  6. maven,spring,mybatis集成错误

    maven,spring,mybatis集成的时候单元测试junit测试没问题,但mvn jetty:run 就报错误 错误: org.apache.ibatis.binding.BindingExc ...

  7. Spring Boot集成Jasypt安全框架

    Jasypt安全框架提供了Spring的集成,主要是实现 PlaceholderConfigurerSupport类或者其子类. 在Sring 3.1之后,则推荐使用PropertySourcesPl ...

  8. Struts2+Spring+Ibatis集成合并

    上一篇博客讲述了Struts2+Spring的集成合并,主要是利用了一个中间jar包,这篇博客在加上Ibatis持久层框架,三个框架进行合并.其中Struts2和Spring部分和前边的一样,主要是讲 ...

  9. spring+springMVC集成(annotation方式)

    spring+springMVC集成(annotation方式) SpringMVC+Spring4.0+Hibernate 简单的整合 MyBatis3整合Spring3.SpringMVC3

随机推荐

  1. kendo ui中grid页面参数问题

    kendo ui 中grid 算是最长用的控件之一,当使用分页效果时,我们要传递分页参数与自己定义的参数如: var dataSource = new kendo.data.DataSource({ ...

  2. Three Families

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  3. 自己实现一个SQL解析引擎

    自己实现一个SQL解析引擎 功能:将用户输入的SQL语句序列转换为一个可运行的操作序列,并返回查询的结果集. SQL的解析引擎包含查询编译与查询优化和查询的执行,主要包含3个步骤: 查询分析: 制定逻 ...

  4. grub2手动引导ubuntu

    測试机OS为ubuntu 14.04.1 LTS x86_64 磁盘分区情况为: Filesystem     1K-blocks    Used Available Use% Mounted on ...

  5. listener笔记

    listener 分四步: 在被观察者类中创建 onXXListener Interface,包含一个方法:xxxListener(object o),参数根据需要观察者需要设定. public in ...

  6. Android入门2:从GridView控件使用到自定义Adapter

    在日常手机app的使用中,出现频率最高的便是ListView和GridView.ListView的例子是微信主界面,而GridView的例子则是支付宝的主界面,不明白的小伙伴打开手机便一目了然.然而这 ...

  7. IOS中对于一些控件的抖动效果

    这两天在网上看到一个帖子讨论关于有些app 输入账密时候 错误的话会有抖动效果出现,然后自己琢磨了下如何实现,下面上代码!!! 首先 写一个UIView的分类 #import <UIKit/UI ...

  8. MYSQLI DEMO

    1.Select // DEMO mysqli连接方式参考 $db = new mysqli("localhost:3306", "root", "& ...

  9. Java系列--目录

    因工作项目的需要,从C#转Java也有很长一段时间了,决定记载归纳一下这半年到底学了什么,到了一个什么程度,当然其间可能会有一些关于.NET的对比. 这是这个系列的目录,我准备按照我的归纳学习点来写, ...

  10. Oracle11g R2学习系列 之三教程选择

    工欲善其事必先利其器,选择一本入门教程也是很重要的,本人使用的也是这位同事推荐的电子工业出版社的<<Oracle 实用教程(第3版)>>郑阿奇主编,可以至这里购买到,我个人还是 ...