RabbitMQ整合Spring AMQP实战

常用组件介绍

  • RabbitAdmin

  • Spring AMQP声明 通过@Bean注解进行声明

  • RabbitTemplate

  • SimpleMessageListenerContainer 对消息消费进行详细配置和优化

  • MessageListenerAdapter 消息监听适配器,建立在监听器基础之上

  • MessageConverter

RabbitAdmin

  • RabbitAdmin类可以很好的操作RabbitMQ,在Spring中直接进行注入即可

  • 注意:autoSatrtup必须设置为true,否则spring容器不会加载RabbitAdmin类

  • RabbitAdmin底层实现就是从Spring容器中获取Exchange、Bingding、RoutingKey以及Queue的@Bean声明;

  • 底层使用RabbitTemplate的execute方法执行对应的声明、修改、删除等一系列RabbitMQ基础功能操作;

RabbitMQ简单使用

pom.xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>	

配置

@Configuration
public class RabbitMqConfig1 {/*** 设置连接* @return ConnectionFactory*/@Beanpublic ConnectionFactory connectionFactory(){CachingConnectionFactory connectionFactory = new CachingConnectionFactory();connectionFactory.setHost("localhost");connectionFactory.setPort(5672);connectionFactory.setUsername("guest");connectionFactory.setPassword("guest");connectionFactory.setVirtualHost("/");return connectionFactory;}/*** 创建RabbitAdmin* @return RabbitAdmin*/@Beanpublic RabbitAdmin rabbitAdmin() {RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());//默认就是truerabbitAdmin.setAutoStartup(true);return rabbitAdmin;}
}

测试

 @Autowiredprivate RabbitAdmin rabbitAdmin;/*** RabbitAdmin api应用*/@Testpublic void testAdmin() {rabbitAdmin.declareExchange(new DirectExchange("test.direct", false, false));rabbitAdmin.declareExchange(new TopicExchange("test.topic", false, false));rabbitAdmin.declareExchange(new FanoutExchange("test.fanout", false, false));rabbitAdmin.declareQueue(new Queue("test.direct.queue", false));rabbitAdmin.declareQueue(new Queue("test.topic.queue", false));rabbitAdmin.declareQueue(new Queue("test.fanout.queue", false));//绑定rabbitAdmin.declareBinding(new Binding("test.direct.queue",Binding.DestinationType.QUEUE,"test.direct", "direct", new HashMap<>()));//使用 BindingBuilder 创建绑定// https://docs.spring.io/spring-amqp/docs/2.1.16.BUILD-SNAPSHOT/reference/html/#builder-apirabbitAdmin.declareBinding(BindingBuilder.bind(new Queue("test.topic.queue", false))        //直接创建队列.to(new TopicExchange("test.topic", false, false))    //直接创建交换机 建立关联关系.with("user.#"));    //指定路由Key//FanoutExchange 类型exchange不走路由键rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue("test.fanout.queue", false)).to(new FanoutExchange("test.fanout", false, false)));//清空队列数据// rabbitAdmin.purgeQueue("test.topic.queue", false);}

SpringAMQP声明(Exchange、Queue、Binding)

在RabbitMQ基础AP里面声明一个Exchange、声明一个绑定、一个队列

//基础API声明一个exchange
channel.exchangeDeclare(String exchange,String type,boolean durable,boolean autoDelete,boolean internal,Map<String, Object> arguments)
//基础API 声明一个队列
channel.queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,Map<String, Object> arguments) 
//基础API 声明binding
channel.queueBind(String queue, String exchange, String routingKey)

使用SpringAMQP去声明,就需要使用SpringAMQP的如下模式,即声明@Bean方式

   //声明Topic 类型的exchange @Beanpublic TopicExchange topicExchange() {//exchange 持久化// Exchange springEchange = ExchangeBuilder.topicExchange("spring_amqp_test_echange").durable(true).build();return new TopicExchange("spring_amqp_test_echange", true, false);}//声明队列@Beanpublic Queue queue() {//   Queue spring_amqp_test_echange = QueueBuilder.durable("spring_amqp_test_echange").build();return new Queue("spring_amqp_test_queue");}//建立绑定@Beanpublic Binding binding(TopicExchange topicExchange, Queue queue) {return BindingBuilder.bind(queue).to(topicExchange).with("spring.*");}

消息模板 RabbitTemplate

  • RabbitTemplate,即消息模板。

  • 在与SpringAMQP整合的时候进行发送消息的关键类

  • 该类提供了丰富的发送消息的方法,包括可靠性投递消息方法、回调监听消息接口ConfirmCallback、返回值确认接口ReturnCallback等等。同样我们需要进入注入到Spring容器中,然后直接使用;

  • 在与Spring整合时需要实例化,但是在与SpringBoot整合时,在配置文件里添加配置即可;

RabbitTemplate简单使用

配置


@Configuration
public class RabbitMqConfig3 {/*** 设置连接** @return ConnectionFactory*/@Beanpublic ConnectionFactory connectionFactory() {CachingConnectionFactory connectionFactory = new CachingConnectionFactory();connectionFactory.setHost("localhost");connectionFactory.setPort(5672);connectionFactory.setUsername("guest");connectionFactory.setPassword("guest");connectionFactory.setVirtualHost("/");return connectionFactory;}/*** 创建RabbitAdmin** @return RabbitAdmin*/@Beanpublic RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);//默认就是truerabbitAdmin.setAutoStartup(true);return rabbitAdmin;}/*** 消息模板** @param connectionFactory connectionFactory* @return RabbitTemplate*/@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {return new RabbitTemplate(connectionFactory);}/*** 针对消费者配置* 1. 设置交换机类型* 2. 将队列绑定到交换机* FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念* HeadersExchange :通过添加属性key-value匹配* DirectExchange:按照routingkey分发到指定队列* TopicExchange:多关键字匹配*/@Beanpublic TopicExchange exchange001() {return new TopicExchange("topic001", true, false);}@Beanpublic Queue queue001() {return new Queue("queue001", true); //队列持久}@Beanpublic Binding binding001(TopicExchange exchange001, Queue queue001) {return BindingBuilder.bind(queue001).to(exchange001).with("spring.*");}
}

测试

   @Testpublic void testSendMessage() {//1 创建消息//AMQP消息的消息属性//MessageBuilder(也可以构建Message) 使用流利的API从byte[]主体或其他消息构建Spring AMQP消息。MessageProperties messageProperties = new MessageProperties();messageProperties.getHeaders().put("desc", "信息描述..");messageProperties.getHeaders().put("type", "自定义消息类型..");Message message = new Message("Hello RabbitMQ".getBytes(), messageProperties);rabbitTemplate.convertAndSend("topic001", "spring.amqp", message, new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {System.err.println("------添加额外的设置---------");message.getMessageProperties().getHeaders().put("desc", "额外修改的信息描述");message.getMessageProperties().getHeaders().put("attr", "额外新加的属性");return message;}});}

队列queue001
在这里插入图片描述

 @Test
public void testSendMessage2() throws Exception {//1 创建消息MessageProperties messageProperties = new MessageProperties();messageProperties.setContentType("text/plain");Message message = new Message("mq 消息1234".getBytes(), messageProperties);rabbitTemplate.send("topic001", "spring.abc", message);rabbitTemplate.convertAndSend("topic001", "spring.amqp", "hello object message send!");rabbitTemplate.convertAndSend("topic002", "rabbit.abc", "hello object message send!");}

队列queue001
在这里插入图片描述
队列queue002
在这里插入图片描述

简单消息监听容器:SimpleMessageListenerContainer

  • 这个类非常的强大,我们可以对他进行很多设置,对于消费者的配置项,这个类都可以满足
  • 监听队列(多个队列)、自动启动、自动声明功能
  • 设置事务特性、事务管理器、事务属性、事务容量(并发)、是否开启事务、回滚消息等
  • 设置消费者数量、最小最大数量、批量消费
  • 设置消息确认和自动确认模式、是否重回队列、异常捕获handler函数
  • 设置消费者标签生成策略、是否独占模式、消费者属性等
  • 设置具体的监听器、消息转换器等等

注意:SimpleMessageListenerContainer可以进行动态设置,比如在运行中的应用可以动态的修改其消费者数量的大小、接收消息的模式等。很多基于RabbitMQ的自制定化后端管控台在进行动态设置的时候,也是根据这一特性去实现的。所以可以看出SpringAMQP非常的强大;
思考一下:SimpleMessageListenerContainer为什么可以动态感知配置变更?
在这里插入图片描述
在这里插入图片描述

配置

 @Beanpublic SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);// container.setQueueNames(); 接收字符串的队列名//container.setQueues(queue001(), queue002(), queue003());//当前消费者数量container.setConcurrentConsumers(1);//最大消费者数量container.setMaxConcurrentConsumers(5);//是否使用重队列container.setDefaultRequeueRejected(false);//自动签收container.setAcknowledgeMode(AcknowledgeMode.AUTO);container.setExposeListenerChannel(true);//消费端的标签策略container.setConsumerTagStrategy(new ConsumerTagStrategy() {@Overridepublic String createConsumerTag(String queue) {return queue + "_" + UUID.randomUUID().toString();}});//设置消息监听//必须设置消息监听 否则 报  No message listener specified - see property 'messageListener'container.setMessageListener(new ChannelAwareMessageListener() {@Overridepublic void onMessage(Message message, Channel channel) throws Exception {String msg = new String(message.getBody());System.err.println("----------消费者: " + msg);//做消息处理....}});return container;}

消息监听适配器:MessageListenerAdapter

通过MessageListenerAdapter的代码我们可以看出如下核心属性:

  • defaultListenerMethod默认监听方法名称:用于设置监听方法名称
  • Delegate委托对象:实际真实的委托对象,用于处理消息、
  • queueOrTagToMethodName: 队列标识与方法名称组成的集合
  • 可以一一进行队列与方法名称的匹配;
  • 队列和方法名称绑定,即指定队列里的消息会被绑定的方法所接收处理;

配置

public class MessageDelegate1 {public void handleMessage(byte[] messageBody) {System.err.println("默认方法, 消息内容:" + new String(messageBody));}public void consumeMessage(byte[] messageBody) {System.err.println("字节数组方法, 消息内容:" + new String(messageBody));}public void consumeMessage(String messageBody) {System.err.println("字符串方法, 消息内容:" + messageBody);}public void method1(String messageBody) {System.err.println("method1 收到消息内容:" + new String(messageBody));}public void method2(String messageBody) {System.err.println("method2 收到消息内容:" + new String(messageBody));}public void consumeMessage(Map messageBody) {System.err.println("map方法, 消息内容:" + messageBody);}
}
  @Beanpublic SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);// container.setQueueNames(); 接收字符串的队列名//container.setQueues(queue001(), queue002(), queue003());//当前消费者数量container.setConcurrentConsumers(1);//最大消费者数量container.setMaxConcurrentConsumers(5);//是否使用重队列container.setDefaultRequeueRejected(false);//自动签收container.setAcknowledgeMode(AcknowledgeMode.AUTO);container.setExposeListenerChannel(true);//消费端的标签策略container.setConsumerTagStrategy(new ConsumerTagStrategy() {@Overridepublic String createConsumerTag(String queue) {return queue + "_" + UUID.randomUUID().toString();}});//1 适配器方式. 默认是有自己的方法名字的:handleMessage// 可以自己指定一个方法的名字: consumeMessage// 也可以添加一个转换器: 从字节数组转换为String//MessageDelegate1如何写 MessageListenerAdapter 源码里面也给出了一些建议MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate1());//默认的方法是 	public static final String ORIGINAL_DEFAULT_LISTENER_METHOD = "handleMessage";adapter.setDefaultListenerMethod("consumeMessage");//TextMessageConverter 自定义的消息转换器//new TextMessageConverter()-->consumeMessage(byte[] messageBody))->MessageProperties.setContentType("text/plian")//new Jackson2JsonMessageConverter()--->consumeMessage(Map messageBody))->MessageProperties.setContentType("application/json")// adapter.setMessageConverter(new Jackson2JsonMessageConverter());container.setMessageListener(adapter);return container;}

MessageConverter消息转换器

  • 我们在进行发送消息的时候,正常情况下消息体为二进制的数据方式进行传输,如果希望内部帮我们进行转换,或者指定自定义的转换器,就需要用到MessageConverter;

  • 自定义常用转换器:MessageConverter,一般来讲都需要实现这个接口

  • 重写下面两个方法:

    • toMessage:java对象转换为Message
    • fromMessage:Message对象转换为java对象
  • MessageConverter消息转换器:

  • Json转换器:Jackson2JsonMessageConverter:可以进行java对象的转换功能;

  • DefaultJackson2JavaTypeMapper映射器:可以进行java对象的映射关系;

  • 自定义二进制转换器:比如图片类型、PDF、PPT、流媒体等

使用转换器的目的是当传入不同的类型的数据(如json,类,PDF,图片等)时,在消息的接收方接收到时也总是以传入的类型接收结果对象;我们通过写入不同的转换器以达到此种效果。具体可百度。

JSON格式转换

默认监听方法的参数为Map

public class Order {private String id;private String name;private String content;public Order() {}public Order(String id, String name, String content) {this.id = id;this.name = name;this.content = content;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}}

配置

     // 1.1 支持json格式的转换器MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());//  public void consumeMessage(Map messageBody) {//        System.err.println("map方法, 消息内容:" + messageBody);//    }//对应map参数方法adapter.setDefaultListenerMethod("consumeMessage");Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();adapter.setMessageConverter(jackson2JsonMessageConverter);container.setMessageListener(adapter);

测试

  @Testpublic void testSendJsonMessage() throws Exception {Order order = new Order();order.setId("001");order.setName("消息订单");order.setContent("描述信息");ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(order);System.err.println("order 4 json: " + json);MessageProperties messageProperties = new MessageProperties();//这里注意一定要修改contentType为 application/jsonmessageProperties.setContentType("application/json");Message message = new Message(json.getBytes(), messageProperties);rabbitTemplate.send("topic001", "spring.order", message);}
JSON格式转换支持Java对象

默认监听方法的参数为Java对象

委托对象方法

public void consumeMessage(Order order) {System.err.println("order对象, 消息内容, id: " + order.getId() + ", name: " + order.getName() + ", content: "+ order.getContent());}

配置

     // 1.2 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持java对象转换MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());adapter.setDefaultListenerMethod("consumeMessage");Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper();//信任所有的包,否则会报 报不信任javaTypeMapper.setTrustedPackages("*");jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper);adapter.setMessageConverter(jackson2JsonMessageConverter);container.setMessageListener(adapter);

测试

 @Testpublic void testSendJavaMessage() throws Exception {Order order = new Order();order.setId("001");order.setName("订单消息");order.setContent("订单描述信息");ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(order);System.err.println("order 4 json: " + json);MessageProperties messageProperties = new MessageProperties();//这里注意一定要修改contentType为 application/jsonmessageProperties.setContentType("application/json");//__TypeId__ 这个是固定写法messageProperties.getHeaders().put("__TypeId__", "com.niugang.spring.entity.Order");Message message = new Message(json.getBytes(), messageProperties);rabbitTemplate.send("topic001", "spring.order", message);}

输出

order对象, 消息内容, id: 001, name: 订单消息, content: 订单描述信息
JSON格式转换支持Java对象(二)

委托对象方法

	public void consumeMessage(Order order) {System.err.println("order对象, 消息内容, id: " + order.getId() + ", name: " + order.getName() + ", content: "+ order.getContent());}public void consumeMessage(Packaged pack) {System.err.println("package对象, 消息内容, id: " + pack.getId() + ", name: " + pack.getName() + ", content: "+ pack.getDescription());}

配置

 //1.3 DefaultJackson2JavaTypeMapper & Jackson2JsonMessageConverter 支持java对象多映射转换MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());adapter.setDefaultListenerMethod("consumeMessage");Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper();Map<String, Class<?>> idClassMapping = new HashMap<String, Class<?>>();idClassMapping.put("order", com.niugang.spring.entity.Order.class);idClassMapping.put("packaged", com.niugang.spring.entity.Packaged.class);javaTypeMapper.setIdClassMapping(idClassMapping);jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper);adapter.setMessageConverter(jackson2JsonMessageConverter);container.setMessageListener(adapter);

测试

   @Testpublic void testSendMappingMessage() throws Exception {ObjectMapper mapper = new ObjectMapper();Order order = new Order();order.setId("001");order.setName("订单消息");order.setContent("订单描述信息");String json1 = mapper.writeValueAsString(order);System.err.println("order 4 json: " + json1);MessageProperties messageProperties1 = new MessageProperties();//这里注意一定要修改contentType为 application/jsonmessageProperties1.setContentType("application/json");messageProperties1.getHeaders().put("__TypeId__", "order");Message message1 = new Message(json1.getBytes(), messageProperties1);rabbitTemplate.send("topic001", "spring.order", message1);Packaged pack = new Packaged();pack.setId("002");pack.setName("包裹消息");pack.setDescription("包裹描述信息");String json2 = mapper.writeValueAsString(pack);System.err.println("pack 4 json: " + json2);MessageProperties messageProperties2 = new MessageProperties();//这里注意一定要修改contentType为 application/jsonmessageProperties2.setContentType("application/json");messageProperties2.getHeaders().put("__TypeId__", "packaged");Message message2 = new Message(json2.getBytes(), messageProperties2);rabbitTemplate.send("topic001", "spring.pack", message2);}
全局消息转化器与自定义转化器

自定义文本转化器

public class TextMessageConverter implements MessageConverter {@Overridepublic Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {return new Message(object.toString().getBytes(), messageProperties);}@Overridepublic Object fromMessage(Message message) throws MessageConversionException {String contentType = message.getMessageProperties().getContentType();if(null != contentType && contentType.contains("text")) {return new String(message.getBody());}return message.getBody();}}

自定义图片转化器

/*** 图片转化器*/
public class ImageMessageConverter implements MessageConverter {@Overridepublic Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {throw new MessageConversionException(" convert error ! ");}@Overridepublic Object fromMessage(Message message) throws MessageConversionException {System.err.println("-----------Image MessageConverter----------");Object _extName = message.getMessageProperties().getHeaders().get("extName");String extName = _extName == null ? "png" : _extName.toString();byte[] body = message.getBody();String fileName = UUID.randomUUID().toString();//目录必须存在String path = "d:/springbootlog/" + fileName + "." + extName;File f = new File(path);try {//拷贝到指定路径Files.copy(new ByteArrayInputStream(body), f.toPath());} catch (IOException e) {e.printStackTrace();}return f;}}

自定义pdf转化器

public class PDFMessageConverter implements MessageConverter {@Overridepublic Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {throw new MessageConversionException(" convert error ! ");}@Overridepublic Object fromMessage(Message message) throws MessageConversionException {System.err.println("-----------PDF MessageConverter----------");byte[] body = message.getBody();String fileName = UUID.randomUUID().toString();String path = "d:/springbootlog/" + fileName + ".pdf";File f = new File(path);try {Files.copy(new ByteArrayInputStream(body), f.toPath());} catch (IOException e) {e.printStackTrace();}return f;}}

委托对象

    public void consumeMessage(File file) {System.err.println("文件对象 方法, 消息内容:" + file.getName());}

配置

     //1.4 ext convertMessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());adapter.setDefaultListenerMethod("consumeMessage");//全局的转换器:ContentTypeDelegatingMessageConverter convert = new ContentTypeDelegatingMessageConverter();TextMessageConverter textConvert = new TextMessageConverter();convert.addDelegate("text", textConvert);convert.addDelegate("html/text", textConvert);convert.addDelegate("xml/text", textConvert);convert.addDelegate("text/plain", textConvert);Jackson2JsonMessageConverter jsonConvert = new Jackson2JsonMessageConverter();convert.addDelegate("json", jsonConvert);convert.addDelegate("application/json", jsonConvert);ImageMessageConverter imageConverter = new ImageMessageConverter();convert.addDelegate("image/png", imageConverter);convert.addDelegate("image", imageConverter);PDFMessageConverter pdfConverter = new PDFMessageConverter();convert.addDelegate("application/pdf", pdfConverter);adapter.setMessageConverter(convert);container.setMessageListener(adapter);

测试

@Testpublic void testSendExtConverterMessage() throws Exception {byte[] body = Files.readAllBytes(Paths.get("C:\\Users\\Administrator\\Desktop\\公众号", "spring.png"));MessageProperties messageProperties = new MessageProperties();messageProperties.setContentType("image/png");messageProperties.getHeaders().put("extName", "png");Message message = new Message(body, messageProperties);rabbitTemplate.send("", "image_queue", message);byte[] body1 = Files.readAllBytes(Paths.get("D:\\Documents\\技术书籍", "Java huashan-2019-06-20.pdf"));MessageProperties messageProperties1 = new MessageProperties();messageProperties.setContentType("application/pdf");Message message1 = new Message(body1, messageProperties);rabbitTemplate.send("", "pdf_queue", message1);}

SpringBoot整合配置详解(生产端)

  • publisher-confirms,实现一个监听器用于监听Broker端给我们返回的确认请求:RabbitTemplate.ConfirmCallback
  • publisher-returns,保证消息对Broker端是可达的,如果出现路由键不可达的情况,则使用监听器对不可达的消息进行后续的处理,保证消息的路由成功: RabbitTemplate.ReturnCallback

注意一点,在发送消息的时候对template进行配置mandatory=true保证监听有效;生产端还可以配置其他属性,比如发送重试,超时时间、次数、间隔等。

生产端代码示例

application.properties

spring.rabbitmq.addresses=localhost:5672
#spring.rabbitmq.host=localhost
#spring.rabbitmq.port=5762
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=15000# 消息确认模式
spring.rabbitmq.publisher-confirms=true
# 消息返回模式
spring.rabbitmq.publisher-returns=true
# 为true 消息返回模式才生效
spring.rabbitmq.template.mandatory=true

配置

/*** springboot  消息生产者** @author niugang*/
@Configuration
public class RabbitMqConfig {/*** 自动注入RabbitTemplate模板类*/@Autowiredprivate RabbitTemplate rabbitTemplate;/*** 回调函数: confirm确认*/final ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {System.err.println("correlationData: " + correlationData);System.err.println("ack: " + ack);if (!ack) {System.err.println("异常处理....");}}};/*** 回调函数: return返回*/final ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {@Overridepublic void returnedMessage(org.springframework.amqp.core.Message message, int replyCode, String replyText,String exchange, String routingKey) {System.err.println("return exchange: " + exchange + ", routingKey: "+ routingKey + ", replyCode: " + replyCode + ", replyText: " + replyText);}};/*队列监听在消费者端配置,没有将会自动创建@Beanpublic TopicExchange topicExchange() {return new TopicExchange("exchange-1");}@Beanpublic Queue queue() {return new Queue("queue-1");}@Beanpublic Binding binding(Queue queue, TopicExchange topicExchange) {return BindingBuilder.bind(queue).to(topicExchange).with("springboot.#");}*//*** 发送消息方法调用: 构建Message消息** @param message    消息体* @param properties 消息属性*/public void send(Object message, Map<String, Object> properties) {MessageProperties messageProperties = new MessageProperties();if (properties != null && properties.size() > 0) {Set<Map.Entry<String, Object>> entries = properties.entrySet();for (Map.Entry<String, Object> entry : entries) {String key = entry.getKey();Object value = entry.getValue();messageProperties.setHeader(key, value);}}//org.springframework.amqp.coreMessage msg = MessageBuilder.withBody(message.toString().getBytes()).andProperties(messageProperties).build();//id + 时间戳 全局唯一CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());rabbitTemplate.setConfirmCallback(confirmCallback);rabbitTemplate.setReturnCallback(returnCallback);//routingKey修改 为 spring.abc 消息将走 returnCallbackrabbitTemplate.convertAndSend("exchange-1", "springboot.abc", msg, correlationData);}}

测试

在rabbitmq控制台新建,Exchange名为exchange-1,新建队列queue-1,并建立两者之间的绑定,routingKey为springboot.#

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Testpublic void contextLoads() {}@Autowiredprivate RabbitMqConfig rabbitMqConfig ;private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");@Testpublic void testSender1() throws Exception {Map<String, Object> properties = new HashMap<>();properties.put("number", "12345");properties.put("send_time", simpleDateFormat.format(new Date()));rabbitMqConfig.send("Hello RabbitMQ For Spring Boot!"+System.currentTimeMillis(), properties);}}

注意:进行单元测试,ack一直是false;改为url请求,ack就正常了

SpringBoot整合配置详解(消费端)

消费端核心配置

#    NONE, MANUAL, AUTO;  手工消息消息确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#监听器调用程序线程的最小数量。
spring.rabbitmq.listener.simple.concurrency=5
#监听器调用程序线程的最大数量。
spring.rabbitmq.listener.simple.max-concurrency=10
# spring.rabbitmq.listener.type=simple 默认为 SimpleContainer  模式对应  spring.rabbitmq.listener.simple 前缀相关的

注意点

  • 首先配置手工确认模式,用于ACK的手工处理,这样我们可以保证消息的可靠性送达,或者在消费端消费失败的时候可以做到重回队列、根据业务记录日志等处理
  • 可以设置消费端的监听个数和最大个数,用于控制消费端的并发情况。

@RabbitListener注解的使用

  • 消费端监听@RabbitMQListener注解,这个对于在实际工作中非常的好用。
  • @RabbitListener是一个组合注解,里面可以注解配置
  • @QueueBinding、@Queue、@Exchange直接通过这个组合注解一次性搞定消费端交换机、队列、绑定、路由、并且配置监听功能等。

消费者端代码示例

类配置写在代码里非常不友好,所以强烈建议大家使用配置文件配置。

properties

#spring.rabbitmq.addresses=localhost:5672
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=15000
#    NONE, MANUAL, AUTO;  手工消息消息确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#监听器调用程序线程的最小数量。
spring.rabbitmq.listener.simple.concurrency=5
#监听器调用程序线程的最大数量。
spring.rabbitmq.listener.simple.max-concurrency=10
# spring.rabbitmq.listener.type=simple 默认为 SimpleContainer  模式对应  spring.rabbitmq.listener.simple 前缀相关的
spring.rabbitmq.listener.order.queue.name=queue-2
spring.rabbitmq.listener.order.queue.durable=true
spring.rabbitmq.listener.order.exchange.name=exchange-2
spring.rabbitmq.listener.order.exchange.durable=true
spring.rabbitmq.listener.order.exchange.type=topic
spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions=true
spring.rabbitmq.listener.order.key=springboot.*

配置

public class Order implements Serializable {private String id;private String name;public Order() {}public Order(String id, String name) {super();this.id = id;this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
/*** 消费者类** @author niugang*/
@Configuration
public class RabbitMQReceiver {/*** 从1.5.0版开始,您可以在类级别指定@RabbitListener注释。* 与新的@RabbitHandler批注一起,这使单个侦听器可以根据传入消息的有效负载类型调用不同的方法。** @RabbitListener(id="multi", queues = "someQueue")* @SendTo("my.reply.queue") public class MultiListenerBean {* @RabbitHandler public String thing2(Thing2 thing2) {* ...* }* @RabbitHandler public String cat(Cat cat) {* ...* }* @RabbitHandler public String hat(@Header("amqp_receivedRoutingKey") String rk, @Payload Hat hat) {* ...* }* @RabbitHandler(isDefault = true)* public String defaultMethod(Object object) {* ...* }* }* 在这种情况下,如果转换后的有效负载是Thing2,Cat或Hat,则会调用各个@RabbitHandler方法。* 您应该了解,系统必须能够根据有效负载类型识别唯一方法。* 检查该类型是否可分配给没有注释或带有@Payload注释的单个参数。* 请注意,如方法级别@RabbitListener(前面所述)中所述,应用了相同的方法签名。*///队列 exchange  绑定 没有 自动创建@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "queue-1",durable = "true"),exchange = @Exchange(value = "exchange-1",durable = "true",type = ExchangeTypes.TOPIC,ignoreDeclarationExceptions = "true"),key = "springboot.*" //routing key))@RabbitHandler//@RabbitListener 提供了很多灵活的签名 如Message Channel  @Payload  @Header 等 具体可查看源码// org.springframework.amqp.core.Message// org.springframework.messaging.Messagepublic void onMessage(Message message, Channel channel) throws Exception {System.err.println("--------------------------------------");System.err.println("消费端Payload: " + new String(message.getBody()));System.err.println("消费端MessageProperties.: " + message.getMessageProperties());//AmqpHeaders header属性封装//手工ACKchannel.basicAck(message.getMessageProperties().getDeliveryTag(), false);}/*** spring.rabbitmq.listener.order.queue.name=queue-2* spring.rabbitmq.listener.order.queue.durable=true* spring.rabbitmq.listener.order.exchange.name=exchange-1* spring.rabbitmq.listener.order.exchange.durable=true* spring.rabbitmq.listener.order.exchange.type=topic* spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions=true* spring.rabbitmq.listener.order.key=springboot.*** @param order   order* @param channel channel* @param headers headers* @throws Exception Exception*/@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${spring.rabbitmq.listener.order.queue.name}",durable = "${spring.rabbitmq.listener.order.queue.durable}"),exchange = @Exchange(value = "${spring.rabbitmq.listener.order.exchange.name}",durable = "${spring.rabbitmq.listener.order.exchange.durable}",type = "${spring.rabbitmq.listener.order.exchange.type}",ignoreDeclarationExceptions = "${spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions}"),key = "${spring.rabbitmq.listener.order.key}"))@RabbitHandler//@Headers 必须通过Map接收//@Header("amqp_receivedRoutingKey") String rk 直接获取header中某一个key//默认前缀为amqp_/*** {amqp_receivedDeliveryMode=PERSISTENT,* amqp_receivedExchange=exchange-2,* amqp_deliveryTag=1,* amqp_consumerQueue=queue-2,* amqp_redelivered=false,amqp_receivedRoutingKey=springboot.def,spring_listener_return_correlation=175a21c4-ffd5-4a3e-ac3a-2f63d60c18a5,spring_returned_message_correlation=0987654321,id=53443ced-0b23-3079-71c2-09997897a553,amqp_consumerTag=amq.ctag-V0hqyVObrHXJeC60MwPSVQ,contentType=application/x-java-serialized-object,timestamp=1591240122842}*/public void onOrderMessage(@Payload Order order,Channel channel,@Headers Map<String, Object> headers) throws Exception {System.err.println("--------------------------------------");System.err.println("消费端order: " + order.getId());System.err.println("消费端headers: " + headers);Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);//手工ACKchannel.basicAck(deliveryTag, false);}}

在这里插入图片描述

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. STM32 在线升级功能(IAP)总结

    在开发产品完成之后,用户使用过程中可能提出新要求(Fuck客户),或出现BUG(肯定的)。需要使用一种较为方便的方法给MCU或外挂flash更新程序。 目前接触过的接口有: 1.串口 2.USB(DFU) 3.网口 3种方式的原理基本一样。都是写一个bootloader程序,在MCU上电时判断某引脚电平…...

    2024/4/24 10:39:08
  2. 分布式锁的三种实现方式及对比

    分布式锁三种实现方式:基于数据库实现分布式锁;基于缓存(Redis等)实现分布式锁;基于Zookeeper实现分布式锁;一, 基于数据库实现分布式锁悲观锁利用select … where … for update 排他锁 注意: 其他附加功能与实现一基本一致,这里需要注意的是“where name=lock ”,na…...

    2024/4/27 8:12:56
  3. 复杂网络表示的原理,算法和应用

    一、 引言图数据在我们的世界中广泛存在,如社交网络,知识图谱,交通网络等。以知识图谱为例,它已经成为很多智能系统的支柱,如搜索引擎,推荐系统等。知识图谱中的一个核心问题是图结构(包括结点和边)的表示,好的知识表示可以帮助知识图谱更加完善以及知识图谱上层的应用…...

    2024/4/24 10:39:04
  4. Django 第10天

    每日测验 """ 今日考题 1.默写ajax基本语法,及提交json数据和文件都需要添加哪些额外参数 2.什么是序列化,截止目前为止你所接触过的序列化有哪些 3.批量插入数据需要注意什么,orm批量插入数据的语法? 4.当需要展示的数据量特别多的情况下,会采取什么优化措…...

    2024/4/24 10:39:04
  5. 《再学一周光线追踪》 学习 一 引子和运动模糊

    蒙特卡洛光线追踪技术系列 见 蒙特卡洛光线追踪技术在《一周学完光线跟踪》书本中,您构建了一个简单且蛮力的光线跟踪器。在本期中,我们将添加纹理、体(如雾)、矩形、实例、灯光,并支持使用BVH的许多对象。完成后,你会有一个“真正的”光线跟踪器。许多人(包括我)相信,…...

    2024/5/7 11:05:03
  6. vue2.X基础速成---核心技术(2)

    vue框架常用知识点 认识Vue文件结构( template, script,stye) 怎么使用vue? 1内网下载, 2另一种方式BootCDN。https://www.bootcdn.cn/ 选择.min.js压缩版本,也可以减少网络相应的时间 模板语法 包含插值、指令(指令缩写) 插值语法{{msg}},数据、js表达式; 指令(指…...

    2024/4/24 10:38:55
  7. CAS详解及ABA问题的解决

    序言 由于最近项目上遇到了高并发问题,而自己对高并发,多线程这里的知识点相对薄弱,尤其是基础,所以想系统的学习一下,以后可能会出一系列的JUC文章及总结 ,同时也为企业级的高并发项目做好准备。 本文是JUC文章的第二篇,如想看以往关于JUC文章,请点击从代码实践的角度…...

    2024/4/24 10:38:54
  8. 微服务的注册发现

    前言服务注册发现是分布式服务中定位服务使用服务的重要机制,也是服务集群中的重要机制。在我们之前了解的微服务架构中,服务的注册发现同样有着重要的作用。服务注册、服务发现注册发现机制主要是在分布式集群中给服务提供的服务定位定位和服务负载均衡机制,自身有两个有用…...

    2024/4/24 10:39:00
  9. Vue开发中的一点技♂巧

    路由参数解耦设置路由的 props 参数 在组件内用 props 接收 params 参数// 设置为 true const router = new VueRouter({routes: [{path: /user/:id,component: User,props: true}] })// 用函数返回 const router = new VueRouter({routes: [{path: /user/:id,component: User,…...

    2024/4/24 10:38:52
  10. python内存机制与垃圾回收、调优手段

    python目录一、python的内存机制二、python的垃圾回收1. 引用计数1.1 原理:1.2 优缺点:1.3 一个例子:1.4 两种情况:1.5 一个特殊的实例:2. 标记清除2.1 原理:2.2 优缺点:3. 分代回收3.1 原理:4. 三种情况触发垃圾回收:5. 小整数对象池与intern机制三、调优手段1. 手动垃…...

    2024/4/24 10:38:53
  11. 利用ApiPost接口管理工具校验/测试API返回结果是否符合预期

    本文主要讲解接口管理工具ApiPost的预执行脚本和后执行脚本里,怎么校验/测试接口返回结果是否符合预期?ApiPost简介:ApiPost是一个支持团队协作,并可直接生成文档的API调试、管理工具。它支持模拟POST、GET、PUT等常见请求,是后台接口开发者或前端、接口测试人员不可多得的…...

    2024/4/24 10:38:52
  12. TCP和SCTP【思维导图】

    ...

    2024/4/24 10:38:56
  13. 六大搜索技巧,提升学习工作效率

    我们在学习工作中用到搜索引擎(例如:百度)去搜索一些资料的时候会发现,搜索出来的结果有很多的干扰项,或者无用的不准确的,下面这些搜索技巧可以帮助你提高效率,一起来看看吧。(以百度搜索为例)搜索技巧一:精确搜索二:排除关键字三:指定网站内搜索四:指定文件格式…...

    2024/5/5 17:09:04
  14. JS中if, else的优化思路

    大体思路三元 || && ?? 如果是有规律的 key,可以用数组 无规律的 key ,可以用对象的键值对的形式储存判断实例 // 原意 if (offsetTop < 0) {this.titleFixed = true } else {this.titleFixed = false }// 三元 offsetTop < 0 ? this.titleFixed = true : thi…...

    2024/4/19 16:08:11
  15. 将项目上传到GitHub

    第一次将项目上传到GitHub需要哪些步骤~~ 首先,你要安装并打开Git工具(安装过程自行百度~~) 然后,切换到你要上传的那个项目的路径 ants@LAPTOP-P71U3IJN MINGW32 ~ $ cd g:ants@LAPTOP-P71U3IJN MINGW32 /g $ cd hotel_management/初始化一个Git仓库 设置签名 用于标识不同…...

    2024/4/17 23:46:40
  16. nui-app介绍

    据官宣,uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架,开发者只需编写一套代码,可编译到iOS、Android、H5、小程序等多个平台,不仅能正确运行且能给用户带来优秀体验。uni-app 继承自 Vue.js,提供了完整的 Vue.js 开发体验。uni-app 组件规范和扩展api与微信小程序…...

    2024/4/16 6:18:18
  17. 使用weex等前端框架开发app获取时间少8个小时

    这个问题在安卓8.0以下会出现let date = new Date(); let hour = date.getHours(); let minute = date.getMinutes(); let second = date.getSeconds();这个是之前的写法,在安卓8.0以上的手机上获取时间正常,低版本的安卓手机会少8个小时var timezone = 8; //目标时区时间,东…...

    2024/4/24 10:38:47
  18. flex布局左边自适应,右边宽度固定

    wxml: <view class="content"><view class="left-content">左边自适应</view><view class="right-content">右边固定</view> </view>wxss .content{ display:flex; algin-items:center; just-content:space…...

    2024/4/24 10:38:46
  19. lombok安装后Tomcat启动报错

    导入lombok后,启动Tomcat报错了,按照网上的方法重新下载也不行,反复测试后,发现是Tomcat版本太低了,换成了8.0之后正常启动了,eclipse4.4 maven 3.3.9 jdk 1.8 tomcat8.0...

    2024/4/24 10:38:45
  20. 请问有画生物活动图的R包或其他的工具吗?

    醒着的时候涂一种颜色,睡着了不涂色或涂其它颜色...

    2024/4/24 10:38:45

最新文章

  1. mac安装linux的centos strem9 虚拟机解压rar文件报错

    背景&#xff1a;解压rar文件需要再linux上安装unrar工具 yum install unrar直接安装的后解压报错,如图 解决办法&#xff1a; 下载&#xff1a;wget https://www.rarlab.com/rar/rarlinux-x64-6.0.2.tar.gz 安装&#xff1a; tar -zxvf rarlinux-x64-6.0.2.tar.gz cd rar …...

    2024/5/7 15:47:17
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 力扣HOT100 - 56. 合并区间

    解题思路&#xff1a; class Solution {public int[][] merge(int[][] intervals) {// 先按照区间起始位置排序Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);int[][] res new int[intervals.length][2];int idx -1;for (int[] interval : intervals) {//直接加入的…...

    2024/5/6 22:23:36
  4. DevOps三步法之反馈:流动是油门,反馈是刹车

    打个比方&#xff0c;流动是油门&#xff0c;反馈是刹车。流动是关于行使&#xff0c;反馈是关于安全。车辆要想持续平稳运行&#xff0c;需要油门与刹车良好配合&#xff0c;否则就有可能车毁人亡。核电站需要使核反应处于临界状态&#xff0c;超出临界状态就是核爆炸这也需要…...

    2024/5/3 14:13:48
  5. 设计模式:组合模式

    定义 组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端可以统一对待单个对象和组合对象。 应用场景 组合模式适用于以下场景: 表达对象的部分-整体层次结构:当你想要表示对象的部分-整…...

    2024/5/7 11:56:24
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/7 5:50:09
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/7 9:45:25
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/7 14:25:14
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/6 21:42:42
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57