Loading

Kafka学习笔记

Kafka学习笔记

一、Windows下配置kafka环境

1.下载

https://www.apache.org/dyn/closer.cgi?path=/kafka/2.8.0/kafka_2.12-2.8.0.tgz

如果在windows下kafka出现问题,将kafka目录中的kafka-log删除掉,重启即可

2.修改配置文件

zookeeper.properties

修改zookeeper数据文件位置
#####################################################################
dataDir=C:/Users/ANTIA1/Desktop/DATA/zookeeper

server.properties

#####################################################################
log.dirs=C:/Users/ANTIA1/Desktop/DATA/kafka-logs

3.启动

启动 zookeeper

D:\Dev\Environment\kafka_2.12-2.8.0> bin\windows\zookeeper-server-start.bat config\zookeeper.properties

启动 kafka

D:\Dev\Environment\kafka_2.12-2.8.0> bin\windows\kafka-server-start.bat config\server.properties

使用 kafka 命令工具

--replication-factor [] 副本的数量
--partitions [] 分区的数量
--topic [] 主题的名称

D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-topics.bat --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic test
Created topic test. 创建成功

查看主题是否创建成功

D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-topics.bat --list --bootstrap-server localhost:9092
test

生产消息

D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-console-producer.bat --broker-list localhost:9092 --topic test


>hello
>world
>kafka

消费消息

D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test --from-beginning


hello
world
kafka
123
hahah

二、SpringBoot整合Kafka

image-20210728234942793

1.引入依赖

pom.xml

<!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

2.配置Kafka

application.properties

#KafkaProperties
spring.kafka.boostrap-servers=localhost:9092
spring.kafka.consumer.group-id=community-consumer-group  对应kafka包中的 config/consumer.properties
spring.kafka.consumer.enable-auto-commit=true
spring.kafka.consumer.auto-commit-interval=3000

3.实例演示

package com.zhuantai.community;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

/**
 * @author ANTIA1
 * @date 2021/7/28 23:58
 */
@SpringBootTest
public class KafkaTests {

    @Autowired
    KafkaProducer producer;


    @Test
    public void testKafka() throws InterruptedException {
        //生产消息
        producer.sendMessage("test","你好");
        producer.sendMessage("test","在吗");

        Thread.sleep(1000*10);
    }
}

/**
 * 生产者Bean
 */
@Component
class KafkaProducer {
    @Autowired
    private KafkaTemplate kafkaTemplate;

    public void sendMessage(String topic,String content){
        kafkaTemplate.send(topic,content);
    }
}

/**
 * 消费者Bean
 */
@Component
class KafkaConsumer {

    @KafkaListener(topics = {"test"})//监听指定的topic
    public void handleMessage(ConsumerRecord record){
        System.out.println(record.value());//打印消息中的值
    }
}

运行结果

image-20210729000848167

三、发送系统通知

image-20210729001113157

1.编写实体类

方便封装数据

Event.java

package com.zhuantai.community.entity;


import java.util.HashMap;
import java.util.Map;

/**
 * @author ANTIA1
 * @date 2021/7/29 0:16
 */
public class Event {
    private String topic;
    private int userId;//事件触发者
    private int entityType;
    private int entityId;
    private int entityUserId;//实体的作者
    private Map<String,Object> data = new HashMap<>();

    public String getTopic() {
        return topic;
    }

    public Event setTopic(String topic) {
        this.topic = topic;
        return this;
    }

    public int getUserId() {
        return userId;
    }

    public Event setUserId(int userId) {
        this.userId = userId;
        return this;
    }

    public int getEntityType() {
        return entityType;
    }

    public Event setEntityType(int entityType) {
        this.entityType = entityType;
        return this;
    }

    public int getEntityId() {
        return entityId;
    }

    public Event setEntityId(int entityId) {
        this.entityId = entityId;
        return this;
    }

    public int getEntityUserId() {
        return entityUserId;
    }

    public Event setEntityUserId(int entityUserId) {
        this.entityUserId = entityUserId;
        return this;
    }

    public Map<String, Object> getData() {
        return data;
    }

    public Event setData(String key,Object value) {
        this.data.put(key,value);
        return this;
    }
}

2.消息生产者

EventProducer.java

package com.zhuantai.community.event;

import com.alibaba.fastjson.JSONObject;
import com.zhuantai.community.entity.Event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

/**
 * 消息生产者
 * @author ANTIA1
 * @date 2021/7/29 0:23
 */
@Component
public class EventProducer {
    @Autowired
    private KafkaTemplate kafkaTemplate;

    //处理事件
    public void fireEvent(Event event){
        //将事件发布到指定的主题
        kafkaTemplate.send(event.getTopic(), JSONObject.toJSONString(event));
    }
}

3.消息消费者

EventConsumer.java

package com.zhuantai.community.event;

import com.alibaba.fastjson.JSONObject;
import com.zhuantai.community.entity.Event;
import com.zhuantai.community.entity.Message;
import com.zhuantai.community.service.MessageService;
import com.zhuantai.community.uitls.CommunityConstant;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 消息消费者
 * @author ANTIA1
 * @date 2021/7/29 0:27
 */
@Component
public class EventConsumer implements CommunityConstant {

    private static final Logger LOGGER = LoggerFactory.getLogger(EventConsumer.class);

    @Autowired
    private MessageService messageService;

    @KafkaListener(topics = {TOPIC_COMMENT,TOPIC_LIKE,TOPIC_FOLLOW})
    public void handleCommentMessage(ConsumerRecord record){
        if (record == null || record.value() == null ){
            LOGGER.error("消息内容为空!");
            return;
        }

        Event event  = JSONObject.parseObject(record.value().toString(),Event.class);
        if (event == null ){
            LOGGER.error("消息格式错误!");
            return;
        }

        // 发送站内通知
        Message message = new Message();
        message.setFromId(SYSTEM_USER_ID);
        message.setToId(event.getEntityUserId());
        message.setConversationId(event.getTopic());
        message.setCreateTime(new Date());

        Map<String,Object> content = new HashMap<>();
        content.put("userId",event.getUserId());//事件是谁触发的
        content.put("entityType",event.getEntityType());//事件实体类型
        content.put("entityId",event.getEntityId());//事件实体ID

        if(!event.getData().isEmpty()){
            for(Map.Entry<String,Object> entry : event.getData().entrySet()){
                content.put(entry.getKey(),entry.getValue());
            }
        }
        message.setContent(JSONObject.toJSONString(content));
        messageService.addMessage(message);
    }
}

4.调用

package com.zhuantai.community.controller;

import com.zhuantai.community.annotation.LoginRequired;
import com.zhuantai.community.entity.Comment;
import com.zhuantai.community.entity.DiscussPost;
import com.zhuantai.community.entity.Event;
import com.zhuantai.community.event.EventProducer;
import com.zhuantai.community.service.CommentService;
import com.zhuantai.community.service.DiscussPostService;
import com.zhuantai.community.uitls.CommunityConstant;
import com.zhuantai.community.uitls.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.Date;

/**
 * @author ANTIA1
 * @date 2021/7/26 17:37
 */
@Controller
@RequestMapping("/comment")
public class CommentController implements CommunityConstant {

    @Autowired
    CommentService commentService;

    @Autowired
    HostHolder hostHolder;

    @Autowired
    EventProducer producer;

    @Autowired
    private DiscussPostService discussPostService;

    @RequestMapping(path = "/add/{discussPostId}", method = RequestMethod.POST)
    public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) {
        comment.setUserId(hostHolder.getUser().getId());
        comment.setStatus(0);
        comment.setCreateTime(new Date());
        commentService.addComment(comment);

        //触发评论事件
        Event event = new Event()
                .setTopic(TOPIC_COMMENT)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(comment.getEntityType())
                .setEntityId(comment.getEntityId())
                .setData("postId",discussPostId);
        if (comment.getEntityType() == ENTITY_TYPE_POST){//如果是给帖子做评论
            DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId());
            event.setEntityUserId(target.getUserId());
        }else if(comment.getEntityType() == ENTITY_TYPE_COMMENT){
            Comment target = commentService.findCommentById(comment.getId());
            event.setEntityUserId(target.getUserId());
        }
        //发布消息
        producer.fireEvent(event);

        return "redirect:/discuss/detail/" + discussPostId;
    }
}
posted @ 2021-08-02 19:16  ANTIA11  阅读(60)  评论(0编辑  收藏  举报