本文目录导读:

在Java分布式系统中,“发布-订阅”模式通常通过消息中间件实现,以下是几种主流方案及其实现方式:
基于Apache Kafka
生产者(发布者)
import org.apache.kafka.clients.producer.*;
public class KafkaProducerExample {
public static void main(String[] args) {
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<>(props);
for (int i = 0; i < 100; i++) {
producer.send(new ProducerRecord<>("my-topic",
Integer.toString(i), "message-" + i));
}
producer.close();
}
}
消费者(订阅者)
import org.apache.kafka.clients.consumer.*;
public class KafkaConsumerExample {
public static void main(String[] args) {
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test-group");
props.put("key.deserializer",
"org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer",
"org.apache.kafka.common.serialization.StringDeserializer");
Consumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("my-topic"));
while (true) {
ConsumerRecords<String, String> records =
consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
System.out.printf("offset = %d, key = %s, value = %s%n",
record.offset(), record.key(), record.value());
}
}
}
}
基于RabbitMQ
生产者(发布者)
import com.rabbitmq.client.*;
public class RabbitMQPublisher {
private final static String EXCHANGE_NAME = "my_exchange";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String message = "Hello World!";
channel.basicPublish(EXCHANGE_NAME, "", null,
message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + message + "'");
}
}
}
消费者(订阅者)
import com.rabbitmq.client.*;
public class RabbitMQSubscriber {
private final static String EXCHANGE_NAME = "my_exchange";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE_NAME, "");
System.out.println(" [*] Waiting for messages...");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
};
channel.basicConsume(queueName, true, deliverCallback,
consumerTag -> { });
}
}
基于Redis发布订阅
配置Redis
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
发布者
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class RedisMessagePublisher {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void publish(String channel, String message) {
redisTemplate.convertAndSend(channel, message);
}
}
订阅者
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
@Component
public class RedisMessageSubscriber implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
System.out.println("Received: " + message.toString());
// 处理消息逻辑
}
}
配置监听器
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
@Configuration
public class RedisConfig {
@Bean
RedisMessageListenerContainer container(
RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container =
new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter,
new ChannelTopic("my-channel"));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(
RedisMessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber, "onMessage");
}
}
基于JMS (ActiveMQ)
生产者
import javax.jms.*;
public class JMSProducer {
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new
org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("my-topic");
MessageProducer producer = session.createProducer(topic);
TextMessage message = session.createTextMessage("Hello World");
producer.send(message);
session.close();
connection.close();
}
}
消费者
import javax.jms.*;
public class JMSConsumer implements MessageListener {
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new
org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("my-topic");
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(message -> {
if (message instanceof TextMessage) {
try {
System.out.println("Received: " +
((TextMessage) message).getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
// 保持连接运行
Thread.sleep(100000);
session.close();
connection.close();
}
}
选择建议
| 场景 | 推荐方案 |
|---|---|
| 大数据流处理 | Apache Kafka |
| 微服务消息通信 | RabbitMQ |
| 简单轻量级消息 | Redis |
| 企业级消息系统 | JMS/ActiveMQ |
核心概念对比:
- Kafka:主题分区、消费者组、持久化消息、高吞吐
- RabbitMQ:交换器、队列、路由键、多协议支持
- Redis:频道、轻量级、内存存储、简单模式
- JMS:标准API、Topic/Queue、可靠性高
选择时要考虑吞吐量、持久化需求、消息顺序、事务支持等因素,对于大多数微服务架构,RabbitMQ或Kafka是常见选择。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播