/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.client.java.example;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.rocketmq.client.apis.ClientConfiguration;
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.SessionCredentialsProvider;
import org.apache.rocketmq.client.apis.StaticSessionCredentialsProvider;
import org.apache.rocketmq.client.apis.message.Message;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.SendReceipt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProducerNormalMessageExample {
private static final Logger LOGGER = LoggerFactory.getLogger(ProducerNormalMessageExample.class);
private ProducerNormalMessageExample() {
}
public static void main(String[] args) throws ClientException, IOException {
final ClientServiceProvider provider = ClientServiceProvider.loadService();
// Credential provider is optional for client configuration.
String accessKey = "yourAccessKey";
String secretKey = "yourSecretKey";
SessionCredentialsProvider sessionCredentialsProvider =
new StaticSessionCredentialsProvider(accessKey, secretKey);
String endpoints = "foobar.com:8080";
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
.setCredentialProvider(sessionCredentialsProvider)
.build();
String topic = "yourNormalTopic";
final Producer producer = provider.newProducerBuilder()
.setClientConfiguration(clientConfiguration)
// Set the topic name(s), which is optional. It makes producer could prefetch the topic route before
// message publishing.
.setTopics(topic)
// May throw {@link ClientException} if the producer is not initialized.
.build();
// Define your message body.
byte[] body = "This is a normal message for Apache RocketMQ".getBytes(StandardCharsets.UTF_8);
String tag = "yourMessageTagA";
final Message message = provider.newMessageBuilder()
// Set topic for the current message.
.setTopic(topic)
// Message secondary classifier of message besides topic.
.setTag(tag)
// Key(s) of the message, another way to mark message besides message id.
.setKeys("yourMessageKey-1c151062f96e")
.setBody(body)
.build();
try {
final SendReceipt sendReceipt = producer.send(message);
LOGGER.info("Send message successfully, messageId={}", sendReceipt.getMessageId());
} catch (Throwable t) {
LOGGER.error("Failed to send message", t);
}
// Close the producer when you don't need it anymore.
producer.close();
}
}
在Spring Boot中安全封装RocketMQ生产者
要在Spring Boot中安全地封装RocketMQ生产者,建议采用以下方式:
1. 创建配置类
import org.apache.rocketmq.client.apis.ClientConfiguration;
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.SessionCredentialsProvider;
import org.apache.rocketmq.client.apis.StaticSessionCredentialsProvider;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RocketMQConfig {
@Value("${rocketmq.endpoints}")
private String endpoints;
@Value("${rocketmq.access-key}")
private String accessKey;
@Value("${rocketmq.secret-key}")
private String secretKey;
@Value("${rocketmq.producer.topics}")
private String topics;
@Bean(destroyMethod = "close")
public Producer rocketMQProducer() throws Exception {
ClientServiceProvider provider = ClientServiceProvider.loadService();
SessionCredentialsProvider credentialsProvider =
new StaticSessionCredentialsProvider(accessKey, secretKey);
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
.setCredentialProvider(credentialsProvider)
.build();
return provider.newProducerBuilder()
.setClientConfiguration(clientConfiguration)
.setTopics(topics)
.build();
}
}
2. 创建服务类封装生产者操作
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.message.Message;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.SendReceipt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RocketMQService {
private static final Logger LOGGER = LoggerFactory.getLogger(RocketMQService.class);
private final Producer producer;
@Autowired
public RocketMQService(Producer producer) {
this.producer = producer;
}
public String sendNormalMessage(String topic, String tag, String keys, String body) {
try {
Message message = ClientServiceProvider.loadService()
.newMessageBuilder()
.setTopic(topic)
.setTag(tag)
.setKeys(keys)
.setBody(body.getBytes(StandardCharsets.UTF_8))
.build();
SendReceipt sendReceipt = producer.send(message);
return sendReceipt.getMessageId().toString();
} catch (ClientException e) {
LOGGER.error("Failed to send message", e);
throw new RuntimeException("Failed to send RocketMQ message", e);
}
}
// 可以添加更多发送消息的方法重载
public String sendNormalMessage(String topic, String body) {
return sendNormalMessage(topic, null, null, body);
}
}
3. 添加应用配置
在application.yml或application.properties中添加配置:
rocketmq:
endpoints: foobar.com:8080
access-key: yourAccessKey
secret-key: yourSecretKey
producer:
topics: yourNormalTopic
4. 使用异常处理
创建全局异常处理器:
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleRuntimeException(RuntimeException e) {
if (e.getCause() instanceof ClientException) {
return ResponseEntity.status(500).body("RocketMQ operation failed: " + e.getMessage());
}
return ResponseEntity.status(500).body("Internal server error: " + e.getMessage());
}
}
5. 在Controller中使用
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MessageController {
private final RocketMQService rocketMQService;
public MessageController(RocketMQService rocketMQService) {
this.rocketMQService = rocketMQService;
}
@PostMapping("/messages")
public String sendMessage(@RequestBody MessageRequest request) {
return rocketMQService.sendNormalMessage(
request.getTopic(),
request.getTag(),
request.getKeys(),
request.getBody()
);
}
}
class MessageRequest {
private String topic;
private String tag;
private String keys;
private String body;
// getters and setters
}
安全注意事项
-
敏感信息保护:
- 不要将accessKey和secretKey硬编码在代码中
- 使用Spring Cloud Config或Vault等工具管理敏感信息
- 在生产环境中考虑使用KMS加密
-
资源管理:
- 确保Producer正确关闭(通过
@Bean(destroyMethod = "close")实现) - 考虑连接池管理(虽然RocketMQ客户端内部可能有连接池)
- 确保Producer正确关闭(通过
-
错误处理:
- 捕获并适当处理ClientException
- 提供有意义的错误信息给客户端
- 考虑重试机制
-
性能考虑:
- 考虑异步发送消息
- 批量发送消息以提高吞吐量
164

被折叠的 条评论
为什么被折叠?



