=========正文分割线====================
作为一个MQ做基本的功能自然就是消息的生产和消费,本章以XML配置的方式实现消息的生产和消费。
一、生产者
1.1.配置
spring-kafka 提供了org.springframework.kafka.core.KafkaTemplate
xml配置如下,producerProperties中的具体配置暂时不用在意,后面有一章专门讲xml配置:
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-3.0.xsd
6 http://www.springframework.org/schema/context
7 http://www.springframework.org/schema/context/spring-context.xsd">
8 <context:property-placeholder location="classpath*:config/application.properties" />
9 <!-- 定义producer的参数 -->
10 <bean id="producerProperties" class="java.util.HashMap">
11 <constructor-arg>
12 <map>
13 <entry key="bootstrap.servers" value="${bootstrap.servers}" />
14 <entry key="group.id" value="${group.id}" />
15 <entry key="retries" value="${retries}" />
16 <entry key="batch.size" value="${batch.size}" />
17 <entry key="linger.ms" value="${linger.ms}" />
18 <entry key="buffer.memory" value="${buffer.memory}" />
20 <entry key="acks" value="${acks}" />
22 <entry key="key.serializer"
23 value="org.apache.kafka.common.serialization.StringSerializer" />
24 <entry key="value.serializer"
25 value="org.apache.kafka.common.serialization.StringSerializer" />
26 </map>
27 </constructor-arg>
28 </bean>
29
30 <!-- 创建kafkatemplate需要使用的producerfactory bean -->
31 <bean id="producerFactory"
32 class="org.springframework.kafka.core.DefaultKafkaProducerFactory">
33 <constructor-arg>
34 <ref bean="producerProperties" />
35 </constructor-arg>
36 </bean>
37
38 <!-- 创建kafkatemplate bean,使用的时候,只需要注入这个bean,即可使用template的send消息方法 -->
39 <bean id="kafkaTemplate" class="org.springframework.kafka.core.KafkaTemplate">
40 <constructor-arg ref="producerFactory" />
41 <constructor-arg name="autoFlush" value="true" />
42 <property name="defaultTopic" value="default" />
43 </bean>
46 </beans>
如上图,xml主要配置了KafkaTemplate的构造参数producerFactory和autoFlush,对应了一个KafkaTemplate源码中的2参构造函数。
producerProperties:设置生产者公产需要的配置
producerFactory:定义了生产者工厂构造方法
kafkaTemplate:定义了使用producerFactory和是否自动刷新,2个参数来构造kafka生产者模板类。
1.2 发送kafka消息
1.根据topic、partition、key发送数据data。
2.接收ListenableFuture添加成功、失败回调函数。
1 ListenableFuture<SendResult<String, String>> listenableFuture = kafkaTemplate.send("topic", "partition","key","data");
2 //发送成功回调
3 SuccessCallback<SendResult<String, String>> successCallback = new SuccessCallback<SendResult<String, String>>() {
4 @Override
5 public void onSuccess(SendResult<String, String> result) {
6 //成功业务逻辑
7 }
8 }
9 //发送失败回调
10 FailureCallback failureCallback = new FailureCallback() {
11 @Override
12 public void onFailure(Throwable ex) {
13 //失败业务逻辑
14 }
15 }
16 listenableFuture.addCallback(successCallback, failureCallback);
二、消费者
2.1配置
consumerProperties中的具体配置暂时不用在意,后面有一章专门讲xml配置
1 <!-- 1.定义consumer的参数 -->
2 <bean id="consumerProperties" class="java.util.HashMap">
3 <constructor-arg>
4 <map>
5 <entry key="bootstrap.servers" value="${bootstrap.servers}" />
6 <entry key="group.id" value="${group.id}" />
7 <entry key="enable.auto.commit" value="${enable.auto.commit}" />
8 <entry key="session.timeout.ms" value="${session.timeout.ms}" />
9 <entry key="key.deserializer"
10 value="org.apache.kafka.common.serialization.StringDeserializer" />
11 <entry key="value.deserializer"
12 value="org.apache.kafka.common.serialization.StringDeserializer" />
13 </map>
14 </constructor-arg>
15 </bean>
16
17 <!-- 2.创建consumerFactory bean -->
18 <bean id="consumerFactory"
19 class="org.springframework.kafka.core.DefaultKafkaConsumerFactory" >
20 <constructor-arg>
21 <ref bean="consumerProperties" />
22 </constructor-arg>
23 </bean>
24
25 <!-- 3.定义消费实现类 -->
26 <bean id="kafkaConsumerService" class="xxx.service.impl.KafkaConsumerSerivceImpl" />
27
28 <!-- 4.消费者容器配置信息 -->
29 <bean id="containerProperties" class="org.springframework.kafka.listener.config.ContainerProperties">
30 <!-- topic -->
31 <constructor-arg name="topics">
32 <list>
33 <value>${kafka.consumer.topic.credit.for.lease}</value>
34 <value>${loan.application.feedback.topic}</value>
35 <value>${templar.agreement.feedback.topic}</value>
36 <value>${templar.aggrement.active.feedback.topic}</value>
37 <value>${templar.aggrement.agreementRepaid.topic}</value>
38 <value>${templar.aggrement.agreementWithhold.topic}</value>
39 <value>${templar.aggrement.agreementRepayRemind.topic}</value>
40 </list>
41 </constructor-arg>
42 <property name="messageListener" ref="kafkaConsumerService" />
43 </bean>
44 <!-- 5.消费者并发消息监听容器,执行doStart()方法 -->
45 <bean id="messageListenerContainer" class="org.springframework.kafka.listener.ConcurrentMessageListenerContainer" init-method="doStart" >
46 <constructor-arg ref="consumerFactory" />
47 <constructor-arg ref="containerProperties" />
48 <property name="concurrency" value="${concurrency}" />
49 </bean>
1.consumerProperties-》consumerFactory 载入配置构造消费者工厂
2.messageListener-》containerProperties 载入容器配置(topics)
3.consumerFactory+containerProperties-》messageListenerContainer 容器配置(topics)+消息监听器,构造一个并发消息监听容器,并执行初始化方法doStart
2.2消费kafka消息
方案1:直接实现MessageListener接口,复写onMessage方法,实现自定义消费业务逻辑。
1 public class KafkaConsumerSerivceImpl implements MessageListener<String, String> {
2 @Override
3 public void onMessage(ConsumerRecord<String, String> data) {
4 //根据不同主题,消费
5 if("主题1".equals(data.topic())){
6 //逻辑1
7 }else if("主题2".equals(data.topic())){
8 //逻辑2
9 }
10 }
11 }
方案2:使用@KafkaListener注解,并设置topic,支持SPEL表达式。这样方便拆分多个不同topic处理不同业务逻辑。(特别是有自己的事务的时候,尤其方便)
1 import org.springframework.kafka.annotation.KafkaListener;
2
3 public class KafkaConsumerSerivceImpl {
4 @KafkaListener(topics = "${templar.aggrement.agreementWithhold.topic}")
5 void templarAgreementNoticewithhold(ConsumerRecord<String, String> data){
6 //消费业务逻辑
7 }
8 }
三、总结
本章我们实现了一个简单的kafka生产、消费消息的实践。到这里我们已经会基本使用kafka了。是不是很简单...
下一章,我们从源码角度来深入分析spring-kafka。