RocetMQ发送顺序消息的所有方法以及代码示例

2023-05-16

RocetMQ发送顺序消息的所有方法以及代码示例

  • 一、使用RocketMQTemplate发送顺序消息
    • (1)SendResult syncSendOrderly(String destination, Message<?> message, String hashKey);同步发送
    • (2)SendResult syncSendOrderly(String destination, Message<?> message, String hashKey, long timeout);同步发送
    • (3)SendResult syncSendOrderly(String destination, Object payload, String hashKey);同步发送
    • (4)SendResult syncSendOrderly(String destination, Object payload, String hashKey, long timeout);同步发送
    • (5)\<T extends Message\> SendResult syncSendOrderly(String destination, Collection<T> messages, String hashKey);同步发送
    • (6)\<T extends Message\> SendResult syncSendOrderly(String destination, Collection<T> messages, String hashKey, long timeout);同步发送
    • (7)void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback);异步发送
    • (8)void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback, long timeout);异步发送
    • (9)void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback);异步发送
    • (10)void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, long timeout);异步发送
    • (11)void sendOneWayOrderly(String destination, Message<?> message, String hashKey);one-way模式,异步发送
    • (12)void sendOneWayOrderly(String destination, Object payload, String hashKey);one-way模式,异步发送
  • 二、使用DefaultMQProducer发送顺序消息
  • 2.1 DefaultMQProducer的创建
    • (1)DefaultMQProducer(String namespace, String producerGroup, RPCHook rpcHook);
    • (2)DefaultMQProducer(String producerGroup, RPCHook rpcHook);
    • (3)DefaultMQProducer(String namespace, String producerGroup);
    • (4)DefaultMQProducer(String producerGroup);
    • (5)DefaultMQProducer(RPCHook rpcHook);
    • (6)DefaultMQProducer();
    • (7)DefaultMQProducer(String namespace, String producerGroup, RPCHook rpcHook, boolean enableMsgTrace, String customizedTraceTopic);
    • (8)DefaultMQProducer(String producerGroup, boolean enableMsgTrace, String customizedTraceTopic);
    • (9)DefaultMQProducer(String producerGroup, boolean enableMsgTrace);
  • 2.2 发送顺序消息
    • (1)SendResult send(Message msg, MessageQueue mq) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送
    • (2)SendResult send(Message msg, MessageQueue mq, long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送
    • (3)void send(Message msg, MessageQueue mq, SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException;异步发送
    • (4)void send(Message msg, MessageQueue mq, SendCallback sendCallback, long timeout) throws MQClientException, RemotingException, InterruptedException;异步发送
    • (5)void sendOneway(Message msg, MessageQueue mq) throws MQClientException, RemotingException, InterruptedException;one-way模式,异步发送
    • (6)SendResult send(Message msg, MessageQueueSelector selector, Object arg) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送
    • (7)SendResult send(Message msg, MessageQueueSelector selector, Object arg, long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送
    • (8)void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException;异步发送
    • (9)void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback,long timeout) throws MQClientException, RemotingException, InterruptedException;异步发送
  • 总结与展望

一、使用RocketMQTemplate发送顺序消息

关于什么是顺序消息,可以参考这篇文章:RocketMQ的顺序消息(顺序消费),这里主要讲如何使用RocketMQ发送顺序消息。

(1)SendResult syncSendOrderly(String destination, Message<?> message, String hashKey);同步发送

import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        Message<String> sendMessage = MessageBuilder.withPayload("这里些消息体")
                .setHeader("消息属性的键","消息属性的值")
                .setHeader("KEYS", "消息的key")
                .build();
        SendResult sendResult = rocketMQTemplate.syncSendOrderly("topicA:tagA", sendMessage, "hashKey");
        System.out.println(sendResult);
    }
}

相对于发送普通消息,发送顺序消息的关键是设置hashKey这个参数。接下来浅显的讲一下实现顺序消息的原理。如下是RocketMQ发送顺序消息的部分源码:

import java.util.List;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;

public class SelectMessageQueueByHash implements MessageQueueSelector {
    public SelectMessageQueueByHash() {
    }

    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        int value = arg.hashCode() % mqs.size();
        if (value < 0) {
            value = Math.abs(value);
        }

        return (MessageQueue)mqs.get(value);
    }
}

通过源码可以看到,RocketMQ会获取每个Java对象都有的hashCode来对queue的数量取模,如果取模后得到的值小于0则取绝对值,最后根据取模后的值去集合中获取一个queue。然后消息就发送到这个queue中。

每个topic都有1-16个queue,queue的数量是在创建topic时设定的,每个消息会负载均衡地发送到这些queue中的其中一个。顺序消息的原理就是使需要保证顺序的消息都发送到同一个queue,从而保证顺序。这里对底层原理不做过多的说明。

hashKey相同的消息被保证发送到topic下相同的queue从而实现顺序消息。实际工作中,hashKey往往被设为订单ID,交易ID等从而保证相同订单ID的消息的顺序。

(2)SendResult syncSendOrderly(String destination, Message<?> message, String hashKey, long timeout);同步发送

import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        Message<String> sendMessage = MessageBuilder.withPayload("这里设置消息体")
                .setHeader("消息属性的键","消息属性的值")
                .setHeader("KEYS", "消息的key")
                .build();
        SendResult sendResult = rocketMQTemplate.syncSendOrderly("topicA:tagA", sendMessage, "hashKey", 3000L);
        System.out.println(sendResult);
    }
}

相对于方法(1)增加了timeout来设置超时时间。

(3)SendResult syncSendOrderly(String destination, Object payload, String hashKey);同步发送

import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        SendResult sendResult = rocketMQTemplate.syncSendOrderly("topicA:tagA", "这里设置消息体", "hashKey");
        System.out.println(sendResult);
    }
}

相对于方法(1),第二个参数变成了Object类型,我们可以直接传入字符串或者实体类,RocketMQ会在底层帮我们转化成Message对象。此方法的缺点是不能设置消息的属性和key。

(4)SendResult syncSendOrderly(String destination, Object payload, String hashKey, long timeout);同步发送

import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        SendResult sendResult = rocketMQTemplate.syncSendOrderly("topicA:tagA", "这里设置消息体", "hashKey", 3000L);
        System.out.println(sendResult);
    }
}

相对于方法(3)增加了timeout来设置超时时间。

(5)<T extends Message> SendResult syncSendOrderly(String destination, Collection messages, String hashKey);同步发送

import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

import java.util.ArrayList;
import java.util.Collection;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        Collection<Message<String>> messages = new ArrayList<>();
        for (int i=0; i<3; i++) {
            Message<String> sendMessage = MessageBuilder.withPayload("这里设置消息体" + i)
                    .setHeader("消息属性的键","消息属性的值")
                    .setHeader("KEYS", "消息的key")
                    .build();
            messages.add(sendMessage);
        }
        SendResult sendResult = rocketMQTemplate.syncSendOrderly("topicA:tagA", messages, "hashKey");
        System.out.println(sendResult);
    }
}

批量发送顺序消息。

(6)<T extends Message> SendResult syncSendOrderly(String destination, Collection messages, String hashKey, long timeout);同步发送

import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

import java.util.ArrayList;
import java.util.Collection;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        Collection<Message<String>> messages = new ArrayList<>();
        for (int i=0; i<3; i++) {
            Message<String> sendMessage = MessageBuilder.withPayload("这里设置消息体" + i)
                    .setHeader("消息属性的键","消息属性的值")
                    .setHeader("KEYS", "消息的key")
                    .build();
            messages.add(sendMessage);
        }
        SendResult sendResult = rocketMQTemplate.syncSendOrderly("topicA:tagA", messages, "hashKey", 3000L);
        System.out.println(sendResult);
    }
}

相对于方法(5)增加了timeout来设置超时时间。

(7)void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback);异步发送

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        Message<String> sendMessage = MessageBuilder.withPayload("这里设置消息体")
                .setHeader("消息属性的键","消息属性的值")
                .setHeader("KEYS", "消息的key")
                .build();
        rocketMQTemplate.asyncSendOrderly("topicA:tagA", sendMessage, "hashKey", new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        });
    }
}

相对于同步发送顺序消息,异步发送只是多了一个SendCallback参数。注意:异步发送顺序消息并不能严格保证消息的顺序

异步发送模式在消息发送后立刻返回,当消息完全完成发送后,会调用回调函数sendCallback来告知发送者本次发送是成功或者失败。异步模式通常用于响应时间敏感业务场景,即承受不了同步发送消息时等待返回的耗时代价。

(8)void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback, long timeout);异步发送

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        Message<String> sendMessage = MessageBuilder.withPayload("这里设置消息体")
                .setHeader("消息属性的键","消息属性的值")
                .setHeader("KEYS", "消息的key")
                .build();
        rocketMQTemplate.asyncSendOrderly("topicA:tagA", sendMessage, "hashKey", new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        }, 3000L);
    }
}

相对于方法(7)增加了timeout来设置超时时间。

(9)void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback);异步发送

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        rocketMQTemplate.asyncSendOrderly("topicA:tagA", "这里设置消息体", "hashKey", new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        });
    }
}

相对于方法(7),第二个参数变成了Object类型,我们可以直接传入字符串或者实体类,RocketMQ会在底层帮我们转化成Message对象。此方法的缺点是不能设置消息的属性和key。

(10)void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, long timeout);异步发送

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        rocketMQTemplate.asyncSendOrderly("topicA:tagA", "这里设置消息体", "hashKey", new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        }, 3000L);
    }
}

相对于方法(9)增加了timeout来设置超时时间。

(11)void sendOneWayOrderly(String destination, Message<?> message, String hashKey);one-way模式,异步发送

import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        Message<String> sendMessage = MessageBuilder.withPayload("这里些消息体")
                .setHeader("消息属性的键","消息属性的值")
                .setHeader("KEYS", "消息的key")
                .build();
        rocketMQTemplate.sendOneWayOrderly("topicA:tagA", sendMessage, "hashKey");
    }
}

使用one-way模式发送顺序消息。本质上是讲SendCallback设为null的异步发送消息。注意:异步发送顺序消息并不能严格保证消息的顺序

采用one-way发送模式发送消息的时候,发送端发送完消息后会立即返回,不会等待来自broker的ack来告知本次消息发送是否完全完成发送。这种模式吞吐量很大,但是存在消息丢失的风险,所以其适用于不重要的消息发送,比如日志收集。one-way模式本质上是没有sendCallback的异步发送方式。

(12)void sendOneWayOrderly(String destination, Object payload, String hashKey);one-way模式,异步发送

import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;

public class OrderlyMessageProducer {
    @Autowired
    RocketMQTemplate rocketMQTemplate;
    public void sendMessages() {
        rocketMQTemplate.sendOneWayOrderly("topicA:tagA", "这里设置消息体", "hashKey");
    }
}

相对于方法(11)第二个参数变成了Object类型,我们可以直接传入字符串或者实体类,RocketMQ会在底层帮我们转化成Message对象。此方法的缺点是不能设置消息的属性和key。

综上所述,使用RocketMQTemplate发送顺序消息相对与发送普通消息只是多了一个hashKey参数,详细的如何使用RocketMQTemplate发送普通消息可以参考我的另一篇文章:RocketMQ发送普通消息的所有方法以及代码示例。值得注意的是,异步发送顺序消息并不能严格保证消息的顺序。

二、使用DefaultMQProducer发送顺序消息

DefaultMQProducer有多个构造函数,我们可以根据不同的场景使用不同的构造函数创建对象。

2.1 DefaultMQProducer的创建

(1)DefaultMQProducer(String namespace, String producerGroup, RPCHook rpcHook);

DefaultMQProducer producer = new DefaultMQProducer("命名空间", "生产者组", new AclClientRPCHook(new SessionCredentials("用户名","密码")));

此构造函数的第一个参数是命名空间,命名空间需要在服务端提前创建。第二个参数是生产者组,一个生产者组可以包含多个生产者,生产者组不需要提前创建,在创建DefaultMQProducer对象的时候赋值一个生产者组就可以。第三个参数是RPCHook对象用于权限认证,相当于你登陆一个网站需要输入用户名和密码。

命名空间是RocketMQ中的一个资源管理概念。用户不同的业务场景一般都可以通过命名空间做隔离,并且针对不同的业务场景设置专门的配置,例如消息保留时间。不同命名空间之间的 Topic 相互隔离,订阅相互隔离,角色权限相互隔离。

(2)DefaultMQProducer(String producerGroup, RPCHook rpcHook);

DefaultMQProducer producer = new DefaultMQProducer("生产者组", new AclClientRPCHook(new SessionCredentials("用户名","密码")));

此构造函数底层还是调用了构造方法(1),只不过将namespace设为了null,在没有命名空间的时候可以使用此构造函数。

(3)DefaultMQProducer(String namespace, String producerGroup);

DefaultMQProducer producer = new DefaultMQProducer("命名空间", "生产者组");

此构造函数底层还是调用了构造方法(1),只不过将RPCHook 设为了null,在不需要acl认证的时候可以使用此构造函数。

(4)DefaultMQProducer(String producerGroup);

DefaultMQProducer producer = new DefaultMQProducer("生产者组");

此构造函数底层还是调用了构造方法(1),只不过将namespace和RPCHook设为了null,在没有命名空间和不需要acl认证的时候可以使用此构造函数。

(5)DefaultMQProducer(RPCHook rpcHook);

DefaultMQProducer producer = new DefaultMQProducer(new AclClientRPCHook(new SessionCredentials("用户名","密码")));

此构造函数底层还是调用了构造方法(1),只不过将namespace设为了null,由于prodcuerGroup不能为null,所以RocketMQ会使用默认的生产者组:DEFAULT_PRODUCER

(6)DefaultMQProducer();

DefaultMQProducer producer = new DefaultMQProducer();

此构造函数底层还是调用了构造方法(1),只不过将namespace和RPCHook设为了null,由于prodcuerGroup不能为null,所以RocketMQ会使用默认的生产者组:DEFAULT_PRODUCER

(7)DefaultMQProducer(String namespace, String producerGroup, RPCHook rpcHook, boolean enableMsgTrace, String customizedTraceTopic);

DefaultMQProducer producer = new DefaultMQProducer("命名空间", "生产者组", new AclClientRPCHook(new SessionCredentials("用户名","密码")), true, "traceTopic");

此构造函数的第一个参数是命名空间,命名空间需要在服务端提前创建。第二个参数是生产者组,一个生产者组可以包含多个生产者,生产者组不需要提前创建,在创建DefaultMQProducer对象的时候赋值一个生产者组就可以。第三个参数是RPCHook对象用于权限认证,相当于你登陆一个网站需要输入用户名和密码。第四个参数是布尔类型,表示是否开启消息追踪。第五个参数是消息跟踪的topic的名称,这个topic专门用来做消息追踪的,一般不会用这个topic生产和消费业务数据。开启追踪后,追踪topic内会记录生产者的一些信息,比如生产者IP、消息的MessageID等。例如下面的代码就是开启追踪并设置trace-topic为追踪topic,然后将消息发送到topicA中,于是topicA里面是业务数据,trace-topic里面是用于消息追踪的追踪数据。也就是发送一次消息会发送一份业务数据和一份追踪数据到业务topic和追踪topic

package com.sgm.esb.gateway.service;

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.nio.charset.StandardCharsets;


public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");

        producer.start();
        Message sendMessage = new Message("topicA", "tagA", "这里设置消息体".getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");

        producer.send(sendMessage);

        producer.shutdown();
    }
}

如下是追踪topic中的消息内容:
跟踪topic的消息内容

(8)DefaultMQProducer(String producerGroup, boolean enableMsgTrace, String customizedTraceTopic);

DefaultMQProducer producer = new DefaultMQProducer("生产者组", true, "traceTopic");

此构造函数底层还是调用了构造方法(7),只不过将namespace和RPCHook设为了null,使用于没有命名空间和不需要acl认证的时候。

(9)DefaultMQProducer(String producerGroup, boolean enableMsgTrace);

DefaultMQProducer producer = new DefaultMQProducer("生产者组", true);

此构造函数底层还是调用了构造方法(7),只不过将namespace、RPCHook和customizedTraceTopic设为了null。

2.2 发送顺序消息

(1)SendResult send(Message msg, MessageQueue mq) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.nio.charset.StandardCharsets;
import java.util.List;


public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        // fetchPublishMessageQueues()中传入的topic必须和Message设置的topic一致,否则发送消息的时候会报错
        List<MessageQueue> messageQueues = producer.fetchPublishMessageQueues("topicA");
        // 根据需求获取一个MessageQueue
        MessageQueue queue = messageQueues.get(0);
        producer.send(sendMessage, queue);
        producer.shutdown();
    }
}

SendResult send(Message msg, MessageQueue mq)第二个参数是MessageQueue类型,表示一个消息队列,设置了这个参数之后消息都会发到这个队列中去,由于队列这种数据结构具有先进先出的特性,所以可以保证消息的顺序性。我们先使用fetchPublishMessageQueues(String topic)方法获取topicA下的MessageQueue,然后根据实际的需要选取一个queue作为参数传入send()方法中。这样做虽然可以保证顺序,但是如果消息全部都往一个队列中发送和消费,会导致效率非常低下。

(2)SendResult send(Message msg, MessageQueue mq, long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.nio.charset.StandardCharsets;
import java.util.List;


public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        // fetchPublishMessageQueues()中传入的topic必须和Message设置的topic一致,否则发送消息的时候会报错
        List<MessageQueue> messageQueues = producer.fetchPublishMessageQueues("topicA");
        // 根据需求获取一个MessageQueue
        MessageQueue queue = messageQueues.get(0);
        producer.send(sendMessage, queue, 3000L);
        producer.shutdown();
    }
}

相对于方法(1)增加了timeout来设置超时时间。

(3)void send(Message msg, MessageQueue mq, SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException;异步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        // fetchPublishMessageQueues()中传入的topic必须和Message设置的topic一致,否则发送消息的时候会报错
        List<MessageQueue> messageQueues = producer.fetchPublishMessageQueues("topicA");
        // 根据需求获取一个MessageQueue
        MessageQueue queue = messageQueues.get(0);
        producer.send(sendMessage, queue, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        });
        producer.shutdown();
    }
}

增加了SendCallback参数表明这个发送方式是异步发送。

(4)void send(Message msg, MessageQueue mq, SendCallback sendCallback, long timeout) throws MQClientException, RemotingException, InterruptedException;异步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        // fetchPublishMessageQueues()中传入的topic必须和Message设置的topic一致,否则发送消息的时候会报错
        List<MessageQueue> messageQueues = producer.fetchPublishMessageQueues("topicA");
        // 根据需求获取一个MessageQueue
        MessageQueue queue = messageQueues.get(0);
        producer.send(sendMessage, queue, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        }, 3000L);
        producer.shutdown();
    }
}

相对于方法(3)增加了timeout来设置超时时间。

(5)void sendOneway(Message msg, MessageQueue mq) throws MQClientException, RemotingException, InterruptedException;one-way模式,异步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        // fetchPublishMessageQueues()中传入的topic必须和Message设置的topic一致,否则会报错
        List<MessageQueue> messageQueues = producer.fetchPublishMessageQueues("topicA");
        // 根据需求获取一个MessageQueue
        MessageQueue queue = messageQueues.get(0);
        producer.sendOneway(sendMessage, queue);
        producer.shutdown();
    }
}

使用one-way模式异步发送消息到某一个队列。

(6)SendResult send(Message msg, MessageQueueSelector selector, Object arg) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.nio.charset.StandardCharsets;
import java.util.List;


public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        producer.send(sendMessage, new MessageQueueSelector() {
            @Override
            // select方法的arg参数就是send(Message msg, MessageQueueSelector selector, Object arg)的第三个参数
            public MessageQueue select(List<MessageQueue> list, Message message, Object arg) {
            	// 自定义选取MessageQueue的方法。这里是根据Object的hashCode来选取
                int value =  arg.hashCode() % list.size();
                if (value < 0) {
                    value = Math.abs(value);
                }
                return list.get(value);
            }
        }, "hashKey");
        producer.shutdown();
    }
}

SendResult send(Message msg, MessageQueueSelector selector, Object arg)的第二个参数MessageQueueSelector是一个接口,里面只有MessageQueue select(List<MessageQueue> list, Message message, Object arg)这一个方法,第一个参数是MessageQueue的列表,第二个参数是send()方法中的msg,第三参数是send()方法中的arg,我们要实现这个接口从而自定义MessageQueue的选择方式。

(7)SendResult send(Message msg, MessageQueueSelector selector, Object arg, long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;同步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        producer.send(sendMessage, new MessageQueueSelector() {
            @Override
            // select方法的arg参数就是send(Message msg, MessageQueueSelector selector, Object arg)的第三个参数
            public MessageQueue select(List<MessageQueue> list, Message message, Object arg) {
            	// 自定义选取MessageQueue的方法。这里是根据Object的hashCode来选取
                int value =  arg.hashCode() % list.size();
                if (value < 0) {
                    value = Math.abs(value);
                }
                return list.get(value);
            }
        }, "hashKey", 3000L);
        producer.shutdown();
    }
}

相对于方法(6)增加了timeout来设置超时时间。

(8)void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException;异步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        producer.send(sendMessage, new MessageQueueSelector() {
            @Override
            public MessageQueue select(List<MessageQueue> list, Message message, Object arg) {
                int value = arg.hashCode() % list.size();
                if (value < 0) {
                    value = Math.abs(value);
                }
                return list.get(value);
            }
        }, "hashKey", new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        });
        producer.shutdown();
    }
}

增加了SendCallback参数表明这个发送方式是异步发送。

(9)void send(Message msg, MessageQueueSelector selector, Object arg, SendCallback sendCallback,long timeout) throws MQClientException, RemotingException, InterruptedException;异步发送

import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class DefaultMQProducerTest {

    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("生产者组",
                new AclClientRPCHook(new SessionCredentials("用户名","密码")),
                true, "trace-topic");
        producer.setNamesrvAddr("nameServer集群IP");
        producer.start();
        Message sendMessage = new Message("topicA", "tagA", ("这里设置消息体").getBytes(StandardCharsets.UTF_8));
        sendMessage.putUserProperty("消息的属性的键", "消息的属性的值");
        sendMessage.setKeys("消息的key");
        producer.send(sendMessage, new MessageQueueSelector() {
            @Override
            public MessageQueue select(List<MessageQueue> list, Message message, Object arg) {
                int value = arg.hashCode() % list.size();
                if (value < 0) {
                    value = Math.abs(value);
                }
                return list.get(value);
            }
        }, "hashKey", new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("Send success");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("Send fail");
            }
        }, 3000L);
        producer.shutdown();
    }
}

相对于方法(8)增加了timeout来设置超时时间。

总结与展望

使用RocketMQTemplate发送顺序消息相对于发送普通消息只是要设置一下hashKey,hashKey一般设为交易ID、订单ID等。使用DefaultMQProducer发送顺序消息相对于使用RocketMQTemplate我们需要自己实现MessageQueueSelector接口来自定义MessageQueue的选取方式。这是我的第二篇文章,我的第一篇文章《RocketMQ发送普通消息的所有方法以及代码示例》有需要的读者也可以阅读,之后我会继续写关于RocketMQ的文章。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RocetMQ发送顺序消息的所有方法以及代码示例 的相关文章

  • 迷宫题解

    P1605 迷宫 题目背景 给定一个N M方格的迷宫 xff0c 迷宫里有T处障碍 xff0c 障碍处不可通过 给定起点坐标和终点坐标 xff0c 问 每个方格最多经过1次 xff0c 有多少种从起点坐标到终点坐标的方案 在迷宫中移动有上下
  • Corn Maze S

    题目 xff1a This past fall Farmer John took the cows to visit a corn maze But this wasn t just any corn maze it featured se
  • csp-m4

    反思 此次模测做的不太理想 xff0c t1因为一个循环条件写错导致只拿到了3个点的分数 xff0c t2是读题不仔细没有搞清输出的数据同时对于数据范围估计也产生了错误 xff0c 导致爆0 xff0c t4看到树就犯怵的习惯还有待克服 x
  • anaconda重装后缺失大量文件夹及各种文件并且安装完毕后在菜单栏找不到快捷方式

    项目场景 xff1a anaconda是python程序设计中不可缺少的一个工具 问题描述 anaconda的最新版本重装后 xff0c 只有conda meta Lib Library pkgs等几个文件夹 xff08 没有截图 xff0
  • 如何解决在Linux CLI终端界面中汉字方块乱码

    解决Linux 纯命令界面下中文是方块乱码的问题 最近在学习Linux安全并给磁盘LUKS加密时 xff0c 发现在telinit 1模式下 xff0c 原本正常的中文字符均变成了方块乱码 xff08 如下图 xff09 xff0c 这使得
  • 基于大数据平台的毕业设计

    前言 2022年最新大数据毕设文章 xff1a 基于大数据平台的毕业设计01 xff1a 基于Docker的HDP集群搭建 最近有很多人问我 xff0c 大数据专业有什么好的毕设项目 xff0c 我就简单的回复了一下 也有直接问我要源码的
  • DM9000在TQ2440移植中的地址内容

    2 2 修改宏定义 三个地址相关宏定义是参考别的单板配置复制过来的 xff0c 肯定不能用 xff0c 查看S3C2440芯片手册和原理图 xff0c 确定这三个地址 首先是基地址CONFIG DM9000 BASE xff0c 在原理图中
  • node学习笔记

    阶段一 1 初始Node js javascript 运行环境 1 2 Node js中的javacript 运行环境 1 3 Node js环境安装 百度 1 4 node js 执行javaScript 代码 2 fs文件系统模块 2
  • SQL实验三 select语句查询操作

    SQL select查询实验 一 实验目的 了解查询的概念和方法掌握SQL Server集成管理器查询子窗口中执行select操作的方法掌握select语句在单表查询中的应用掌握select语句在多表查询中的应用掌握select语句在复杂查
  • [编程题]字母交换

    题目描述 xff1a 字符串S由小写字母构成 xff0c 长度为n 定义一种操作 xff0c 每次都可以挑选字符串中任意的两个相邻字母进行交换 询问在至多交换m次之后 xff0c 字符串中最多有多少个连续的位置上的字母相同 xff1f 输入
  • 阿里云域名备案问题 注销主体步骤

    阿里云域名备案问题 注销主体步骤 注意 xff1a 当主体下只有一个域名时 xff0c 若在阿里云备案平台按 注销网站 xff0c 主体会成为空壳主体 xff0c 阿里云备案平台不会再显示主体了 xff0c 接下来就按不了 注销主体 操作
  • jenkins安装和配置(一):ubuntu 20.04 jenkins安装

    参考 Installing Jenkins 参考 How to Install and Configure Jenkins on Ubuntu 20 04 LTS 一 安装前提 Java 8 or Java 11 are required
  • 泛型 知识点 总结

    为什么要有泛型 泛型实质上就是使程序员定义安全的类型 在没有出现泛型之前 java也提供了对Objct的引用 34 任意化 34 操作 这种 34 任意化 34 操作就是对Object引用进行向下转型及向上转型操作 但是某些强制类型转换的错
  • 手把手教你centos8/rhel8使用国内源安装virtualbox If your system is using EFI Secure Boot you may need to

    这两天装virtualbox的时候又遇到问题了 xff0c 它显示这个错误 xff1a If your system is using EFI Secure Boot you may need to sign the kernel modu
  • gitlab配置

    在Ubuntu下安装gitlab ce 首先全程使用root进行配置 更新apt源 apt update 安装依赖项 Postfix Configuration 选择 No configuration 就好 apt span class t
  • vs2019更新后的设置问题for(

    最近不小心把vs2019更新了一下 xff0c 虽然增加了很多新功能 xff0c 但是对于我来说最大的意义在于它的字体颜色好像更丰富了 xff0c 其他的也不太能用得到 但是更新之后 xff0c 写for循环的时候发现for i 61 0
  • 插入最少的字符,构造回文串

    题目 xff1a 题目链接 给一个字符串 xff0c 在任意的位置插入一些字符 xff0c 使得这个字符串成为回文串 xff0c 最少需要插入多少个字符 ps xff1a 有一个和这个题很像的题 xff0c 都是插入最少的字符构造回文串 x
  • Linux常用命令大全

    Linux常用命令大全 一 进程管理 xff08 1 xff09 Linux中Kill进程的方法 二 系统信息三 关机 系统的关机 重启以及登出 四 文件和目录五 文件搜索六 挂载一个文件系统七 磁盘空间八 系统负载 top九 用户和群组十
  • 字符的最少变换次数,并查集

    题意 xff1a 给两个字符串a xff0c b a合和b中的字符都是前20个字母 xff08 a t xff09 xff0c a需要进行一些变换 xff0c 使得a等于b 对于每一次变换 xff1a 选取a中相同的字符 xff0c 然后把
  • 并查集 判断无向图是否有环

    无向图中 xff0c 给定一些边 xff0c 然后判断这些边组成的图是否有环 注意这个方法必须保证没有输入重边 对于一条边用 a b 表示 xff0c 然后把a xff0c b加入到并查集中 如果又加入了一条边 b c xff0c 那么如果

随机推荐

  • 彻底地删除垃圾软件

    当不小心下载了垃圾软件 xff0c 想删除掉 xff0c 但是又删不掉 xff0c 或者是删不干净的一些办法 首先 xff0c 我们应该把软件关掉 xff0c 让它停止运行 然后找到软件所在的文件夹 xff0c 把一些能够删除的文件都删除掉
  • Aizu_GRL_1_c floyd算法,判断负环的题

    这题应该是很简单的 xff0c 但是我wa了好久 看了别人的博客 xff0c 还是想不明白哪有问题 xff0c 我发现别人的ac代码要判断一下 xff0c mp i k 和mp k jj 是不是等于inf xff0c 我觉得判不判断没啥区别
  • codeforces 1165D(求因子的问题)

    题意 xff1a 给出除了1和它本身之外的所有因子 xff0c 找出最小的这个数 xff0c 如果有冲突的数就输出 1 思路 xff1a 我是当时没做出来看了大佬的博客才知道 https www cnblogs com fengxunlin
  • cmd 复制文件语法不正确

    复制文件到另一个文件夹 xff1a 语法格式 xff1a copy 原文件的路径和名称 目标文件夹的路径 说语法不正确的时候可能是路径中有空格 比如C Program Files x86 CodeBlocks share CodeBlock
  • 关于斜率的计算

    codeforces 842A 从L到R中选取一个数作为分子 xff0c 从x到y中选取一个数作为分母 xff0c 给一个数k 问有没有可能这个分数等于k 这题也是有够坑的 xff0c 用二分精确的判断要超时 xff0c 但是只是看在不在范
  • c语言线性表实现电话簿(学生信息)

    c语言线性表实现电话簿 span class token macro property span class token directive keyword include span span class token string lt s
  • vsc code-runner插件运行python文件,解释器更改为ananconda

    code runner刚下载下来的默认解释器是系统自带的 xff0c 并不是anaconda的 选择文件 首选项 找到code runner executor map 找到python的命令 xff0c 改为自己的解释器位置即可
  • NT_STATUS_ACCESS_DENIED listing \*

    在centos8上配了个SAMBA与windows共享文件 访问共享目录出现 NT STATUS ACCESS DENIED listing xff0c smb gt span class token operator span span
  • RocketMQ发送普通消息的所有方法以及代码示例

    RocketMQ发送普通消息的所有方法以及代码示例 一 使用RocketMQTemplate发送消息 xff08 整合Springboot xff09 xff08 1 xff09 void send Message lt gt messag
  • C语言总结day01

    day01 1 C语言标识符 C语言标识符需满足以下条件 只能由英文字母 26个英文字母 xff0c 包括大小写即共52个 数字 0 9 和下划线组成长度为1 32必须以英文字母或下划线开头 2 C语言风格 C语言严格区分英文字母的大小写C
  • C语言总结day02

    day02 1 运算符 算术运算符 单目运算符 xff1a 43 正 xff1b 负 xff1b 双目运算符 xff1a 这三个同级 gt 43 这两个同级 注意 xff1a 前边三个的优先级大于后边的两个 xff1b 双目运算符两边运算数
  • C语言总结day03

    day03 1 数据的输入输出 数据的输出 xff1a 从计算机向输出设备 如显示器 打印机等 输出数据称为输出 数据的输入 xff1a 从输入设备 如键盘 磁盘 光盘 扫描仪等 向计算机输入数据称为输入 C语言函数库中有一批 34 标准输
  • C语言总结day04

    day04 1 int a n 是错误的 C语言中不允许对数组的大小作动态定义 2 字符数组的初始化 char a 61 I am Student char a 10 利用for语句对每个进行初始化 3 字符数组的输入和输出输入 char
  • C语言总结day06

    day06 1 定义和使用结构体变量 C语言允许用户建立由不同类型数据组成的组合型的数据结构 xff0c 它称为结构体 声明格式 struct 结构体名 成员列表 定义结构体类型变量 struct 结构体名 结构体变量 在声明类型的同时定义
  • C语言总结day07

    day07 一些概念理解 1 为什么使用指针 每一个编程语言都使用指针C 43 43 将指针暴露给了 用户 xff08 程序员 xff09 xff0c 而java和C 等语言则将指针隐蔽起来了 2 指针和引用的区别 本质 xff1a 引用是
  • C语言总结day05

    day05 1 函数间可以相互调用 xff0c 但是不能调用main函数 xff0c main函数是被操作系统调用的 2 数组作为函数参数 数组元素可以作函数参数 值传递 注意 xff1a 数组元素可以用作函数实参 xff0c 不能用作形参
  • SSM-Spring入门

    Spring学习 1 Spring简介 Spring是什么 Spring是分层的Java SE EE应用full stack轻量级开源框架 xff0c 是以loC Inverse Of Contorl 反转控制 和AOP Aspect Or
  • SSM-Spring学习(二)

    Spring IoC和DI注解开发 Spring配置数据源 数据源 xff08 连接池 xff09 介绍 xff1a 数据库连接池概念 百度百科 xff1a 数据库连接池负责分配 管理和释放数据库连接 xff0c 它允许应用程序重复使用一个
  • SSM-Spring(三)-AOP

    简介 什么是 AOP AOP 为 span class token class name Aspect span span class token class name Oriented span span class token clas
  • RocetMQ发送顺序消息的所有方法以及代码示例

    RocetMQ发送顺序消息的所有方法以及代码示例 一 使用RocketMQTemplate发送顺序消息 xff08 1 xff09 SendResult syncSendOrderly String destination Message