在 Spring Boot中 封装 RocketMQ 生产者消息发送代码

/*
 * 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.ymlapplication.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
}

安全注意事项

  1. 敏感信息保护

    • 不要将accessKey和secretKey硬编码在代码中
    • 使用Spring Cloud Config或Vault等工具管理敏感信息
    • 在生产环境中考虑使用KMS加密
  2. 资源管理

    • 确保Producer正确关闭(通过@Bean(destroyMethod = "close")实现)
    • 考虑连接池管理(虽然RocketMQ客户端内部可能有连接池)
  3. 错误处理

    • 捕获并适当处理ClientException
    • 提供有意义的错误信息给客户端
    • 考虑重试机制
  4. 性能考虑

    • 考虑异步发送消息
    • 批量发送消息以提高吞吐量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学亮编程手记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值