热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

RabbitMQ消息中间件(第四章)第二部分

本章导航RabbitMQ整合SpringAMQP实战RabbitMQ整合SpringBoot实战RabbitMQ整合SpringCloud实战RabbitMQ整合SpringAMQ

本章导航

  • RabbitMQ整合Spring AMQP实战

  • RabbitMQ整合Spring Boot实战

  • RabbitMQ整合Spring Cloud实战


RabbitMQ整合Spring AMQP实战

  • RabbitAdmin

  • SpringAMQP声明

  • SimpleMessageListenerContainer简单消息监听容器

  • MessageListenerAdapter消息监听适配器

  • MessageConverter 消息转换器,序列化和反序列化等操作

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

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

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

  • 例如:添加一个交换机、删除一个绑定、清空一个队列里的消息等等


MessageListenerAdapter

MessageListenerAdapter即消息监听适配器



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

  • defaultListenerMethod默认监听方法名称:用于设置监听方法名称

  • Delegate委托对象:实际真实的委托对象,用于处理消息

  • queueOrTagToMethodName队列标识与方法名称组成的集合

  • 可以一一进行队列与方法名称的匹配

  • 队列和方法名称绑定,即指定队列里的消息会被绑定的方法所接受处理

 代码实现

package com.cx.temp.common.rabbitmq.spring;
import com.cx.temp.common.rabbitmq.spring.adapter.MessageDelegate;
import com.cx.temp.common.rabbitmq.spring.convert.TextMessageConverter;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.
*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.ConsumerTagStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.util.UUID;
/**
*
*/
@Configuration
@ComponentScan({
"com.cx.temp.*"})
public class RabbitMQConfig {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory
= new CachingConnectionFactory();
connectionFactory.setAddresses(
"127.0.0.1:5672");
connectionFactory.setUsername(
"root");
connectionFactory.setPassword(
"123456");
connectionFactory.setVirtualHost(
"/test001");
return connectionFactory;
}
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin rabbitAdmin
= new RabbitAdmin(connectionFactory);
rabbitAdmin.setAutoStartup(
true);
return rabbitAdmin;
}
/**
* 针对消费者配置
* 1.设置交换机类型
* 2.将队列绑定到交换机
* FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
* HeadersExchange: 通过添加属性key-value匹配
* DirectExchange: 按照routingkey分发到指定队列
* TopicExchange: 多关键字匹配
* @return
*/
@Bean
public TopicExchange exchange001(){
return new TopicExchange("topic001", true, false);
}
@Bean
public Queue queue001() {
return new Queue("queue001", true); //队列持久
}
@Bean
public Binding binding001(){
return BindingBuilder.bind(queue001()).to(exchange001()).with("spring.*");
}
@Bean
public TopicExchange exchange002(){
return new TopicExchange("topic002", true, false);
}
@Bean
public Queue queue002() {
return new Queue("queue002", true); //队列持久
}
@Bean
public Queue queue003() {
return new Queue("queue003", true); //队列持久
}
@Bean
public Binding binding002(){
return BindingBuilder.bind(queue002()).to(exchange002()).with("rabbit.*");
}
@Bean
public Binding binding003(){
return BindingBuilder.bind(queue003()).to(exchange002()).with("spring.*");
}
@Bean
public Queue queue_image() {
return new Queue("image_queue", true); //队列持久
}
@Bean
public Queue queue_pdf() {
return new Queue("pdf_queue", true); //队列持久
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate
= new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
@Bean
public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container
= new SimpleMessageListenerContainer(connectionFactory);
container.setQueues(queue001(), queue002(), queue003(), queue_image(), queue_pdf());
container.setConcurrentConsumers(
1);
container.setMaxConcurrentConsumers(
5);
container.setDefaultRequeueRejected(
false); //不进行重回队列
container.setAcknowledgeMode(AcknowledgeMode.AUTO); //自动签收机制
container.setConsumerTagStrategy(new ConsumerTagStrategy() {
@Override
public String createConsumerTag(String queue) {
return queue + "_" + UUID.randomUUID().toString();
}
});
// container.setMessageListener(new ChannelAwareMessageListener() {
// @Override
// public void onMessage(Message message, Channel channel) throws Exception {
// String msg = new String(message.getBody());
// System.err.println("-----------消费者:" + msg);
// }
// });
//第一种
// MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
// container.setMessageListener(adapter);
//第二种
// MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
// adapter.setDefaultListenerMethod("consumeMessage"); //也可以通过这个方法设置默认查找适配器对象的方法,默认的方法名是handleMessage
//第三种
MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
adapter.setDefaultListenerMethod(
"consumeMessage");
adapter.setMessageConverter(
new TextMessageConverter());
container.setMessageListener(adapter);
return container;
}
}

 

字节转换器

package com.cx.temp.common.rabbitmq.spring.convert;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.amqp.support.converter.MessageConverter;
public class TextMessageConverter implements MessageConverter {
@Override
public Message toMessage(Object o, MessageProperties messageProperties) throws MessageConversionException {
return new Message(o.toString().getBytes(), messageProperties);
}
@Override
public 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();
}
}

 

自定义输出设置

package com.cx.temp.common.rabbitmq.spring.adapter;
/**
*/
public class MessageDelegate {
//方法名是固定的,通过查看MessageListenerAdapter的源码,里面有句【public static final String ORIGINAL_DEFAULT_LISTENER_METHOD = "handleMessage";】
//表示他是通过反射查找handleMessage这个方法名进行处理的
//第一种 旧版的RabbitMQ默认是字节数据
// public void handleMessage(byte[] messageBody) {
// System.out.println("默认方法,消息内容:" + new String(messageBody));
// }
//第一种 现演示的版本默认走字符串
// public void handleMessage(String messageBody) {
// System.out.println("默认方法,消息内容:" + messageBody);
// }
//第二种
public void consumeMessage(byte[] messageBody) {
System.
out.println("字节数组方法,消息内容:" + new String(messageBody));
}
//
// public void consumeMessage(String messageBody) {
// System.out.println("字符串方法,消息内容:" + messageBody);
// }
//
// public void method1(String messageBody) {
//
// }

}

 

测试类

package com.cx.temp.rabbitmq;
import com.cx.temp.admin.AdminApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.
*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.HashMap;
@RunWith(SpringJUnit4ClassRunner.
class)
@SpringBootTest(classes
= AdminApplication.class)
public class RabbitMQTest {
@Autowired
private RabbitAdmin rabbitAdmin;
@Test
public void testAdmin() throws Exception {
//第一种声明与绑定方式
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<>()));
//第二种 支持链式声明与绑定
rabbitAdmin.declareBinding(BindingBuilder
.bind(
new Queue("test.topic.queue", false))
.to(
new TopicExchange("test.topic", false, false))
.with(
"user.#"));
rabbitAdmin.declareBinding(BindingBuilder
.bind(
new Queue("test.fanout.queue", false))
.to(
new FanoutExchange("test.fanout", false, false)));
//清空队列数据
rabbitAdmin.purgeQueue("test.topic.queue", false);
}
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testSendMessage() throws Exception {
//1 创建消息
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() {
//消息发送之后在对这个message进行设置
@Override
public Message postProcessMessage(Message message) throws AmqpException {
System.err.println(
"----------添加额外的设置-----------");
message.getMessageProperties().getHeaders().put(
"desc", "额外修改的信息描述");
message.getMessageProperties().getHeaders().put(
"attr", "额外新加的属性");
return message;
}
});
}
@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.amqp", "hello object message send!");
}
@Test
public void testSendMessage4Text() 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);
}
}

 

执行测试类

testSendMessage4Text方法

 



  • queueOrTagToMethodName队列标识与方法名称组成的集合

package com.cx.temp.common.rabbitmq.spring;
import com.cx.temp.common.rabbitmq.spring.adapter.MessageDelegate;
import com.cx.temp.common.rabbitmq.spring.convert.TextMessageConverter;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.
*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.ConsumerTagStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
*
*/
@Configuration
@ComponentScan({
"com.cx.temp.*"})
public class RabbitMQConfig {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory
= new CachingConnectionFactory();
connectionFactory.setAddresses(
"127.0.0.1:5672");
connectionFactory.setUsername(
"root");
connectionFactory.setPassword(
"123456");
connectionFactory.setVirtualHost(
"/test001");
return connectionFactory;
}
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin rabbitAdmin
= new RabbitAdmin(connectionFactory);
rabbitAdmin.setAutoStartup(
true);
return rabbitAdmin;
}
/**
* 针对消费者配置
* 1.设置交换机类型
* 2.将队列绑定到交换机
* FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
* HeadersExchange: 通过添加属性key-value匹配
* DirectExchange: 按照routingkey分发到指定队列
* TopicExchange: 多关键字匹配
* @return
*/
@Bean
public TopicExchange exchange001(){
return new TopicExchange("topic001", true, false);
}
@Bean
public Queue queue001() {
return new Queue("queue001", true); //队列持久
}
@Bean
public Binding binding001(){
return BindingBuilder.bind(queue001()).to(exchange001()).with("spring.*");
}
@Bean
public TopicExchange exchange002(){
return new TopicExchange("topic002", true, false);
}
@Bean
public Queue queue002() {
return new Queue("queue002", true); //队列持久
}
@Bean
public Queue queue003() {
return new Queue("queue003", true); //队列持久
}
@Bean
public Binding binding002(){
return BindingBuilder.bind(queue002()).to(exchange002()).with("rabbit.*");
}
@Bean
public Binding binding003(){
return BindingBuilder.bind(queue003()).to(exchange001()).with("mq.*");
}
@Bean
public Queue queue_image() {
return new Queue("image_queue", true); //队列持久
}
@Bean
public Queue queue_pdf() {
return new Queue("pdf_queue", true); //队列持久
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate
= new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
@Bean
public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container
= new SimpleMessageListenerContainer(connectionFactory);
container.setQueues(queue001(), queue002(), queue003(), queue_image(), queue_pdf());
container.setConcurrentConsumers(
1);
container.setMaxConcurrentConsumers(
5);
container.setDefaultRequeueRejected(
false); //不进行重回队列
container.setAcknowledgeMode(AcknowledgeMode.AUTO); //自动签收机制
container.setConsumerTagStrategy(new ConsumerTagStrategy() {
@Override
public String createConsumerTag(String queue) {
return queue + "_" + UUID.randomUUID().toString();
}
});
// container.setMessageListener(new ChannelAwareMessageListener() {
// @Override
// public void onMessage(Message message, Channel channel) throws Exception {
// String msg = new String(message.getBody());
// System.err.println("-----------消费者:" + msg);
// }
// });
//第一种
// MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
// container.setMessageListener(adapter);
//第二种
// MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
// adapter.setDefaultListenerMethod("consumeMessage"); //也可以通过这个方法设置默认查找适配器对象的方法,默认的方法名是handleMessage
//第三种
/** 1.适配器方式,默认是有自己的方法名称的:handleMessage
//可以自己指定一个方法的名字:consumeMessage
//也可以添加一个转换器:从字节数组转换String
MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate());
adapter.setDefaultListenerMethod("consumeMessage");
adapter.setMessageConverter(new TextMessageConverter());
container.setMessageListener(adapter);
*/
/**
* 2.适配器方式:我们的队列名称和方法名称也可以也进行一一匹配
*/
Map
queueOrTagToMethodName = new HashMap<>();
queueOrTagToMethodName.put(
"queue001", "method1");
queueOrTagToMethodName.put(
"queue002", "method2");
MessageListenerAdapter adapter
= new MessageListenerAdapter(new MessageDelegate());
adapter.setQueueOrTagToMethodName(queueOrTagToMethodName);
adapter.setMessageConverter(
new TextMessageConverter());
container.setMessageListener(adapter);
return container;
}
}

 

package com.cx.temp.common.rabbitmq.spring.convert;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.amqp.support.converter.MessageConverter;
public class TextMessageConverter implements MessageConverter {
@Override
public Message toMessage(Object o, MessageProperties messageProperties) throws MessageConversionException {
return new Message(o.toString().getBytes(), messageProperties);
}
@Override
public 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();
}
}

 

package com.cx.temp.common.rabbitmq.spring.adapter;
/**
*/
public class MessageDelegate {
//方法名是固定的,通过查看MessageListenerAdapter的源码,里面有句【public static final String ORIGINAL_DEFAULT_LISTENER_METHOD = "handleMessage";】
//表示他是通过反射查找handleMessage这个方法名进行处理的
//第一种 旧版的RabbitMQ默认是字节数据
// public void handleMessage(byte[] messageBody) {
// System.out.println("默认方法,消息内容:" + new String(messageBody));
// }
//第一种 现演示的版本默认走字符串
// public void handleMessage(String messageBody) {
// System.out.println("默认方法,消息内容:" + messageBody);
// }
//第二种 旧版
// public void consumeMessage(byte[] messageBody) {
// System.out.println("字节数组方法,消息内容:" + new String(messageBody));
// }
//第二种 新版
public void consumeMessage(String messageBody) {
System.
out.println("字符串方法,消息内容:" + messageBody);
}
public void method1(String messageBody) {
System.
out.println("method1收到消息内容:" + messageBody);
}
public void method2(String messageBody) {
System.
out.println("method2收到消息内容:" + messageBody);
}
}

package com.cx.temp.rabbitmq;
import com.cx.temp.admin.AdminApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.
*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.HashMap;
@RunWith(SpringJUnit4ClassRunner.
class)
@SpringBootTest(classes
= AdminApplication.class)
public class RabbitMQTest {
@Autowired
private RabbitAdmin rabbitAdmin;
@Test
public void testAdmin() throws Exception {
//第一种声明与绑定方式
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<>()));
//第二种 支持链式声明与绑定
rabbitAdmin.declareBinding(BindingBuilder
.bind(
new Queue("test.topic.queue", false))
.to(
new TopicExchange("test.topic", false, false))
.with(
"user.#"));
rabbitAdmin.declareBinding(BindingBuilder
.bind(
new Queue("test.fanout.queue", false))
.to(
new FanoutExchange("test.fanout", false, false)));
//清空队列数据
rabbitAdmin.purgeQueue("test.topic.queue", false);
}
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testSendMessage() throws Exception {
//1 创建消息
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() {
//消息发送之后在对这个message进行设置
@Override
public Message postProcessMessage(Message message) throws AmqpException {
System.err.println(
"----------添加额外的设置-----------");
message.getMessageProperties().getHeaders().put(
"desc", "额外修改的信息描述");
message.getMessageProperties().getHeaders().put(
"attr", "额外新加的属性");
return message;
}
});
}
@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.amqp", "hello object message send!");
}
@Test
public void testSendMessage4Text() 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.send(
"topic002", "rabbit.abc",message);
}
}

 

启动Appliciton后执行

testSendMessage4Text控制台输出

 



推荐阅读
  • 本文推荐了六款高效的Java Web应用开发工具,并详细介绍了它们的实用功能。其中,分布式敏捷开发系统架构“zheng”项目,基于Spring、Spring MVC和MyBatis技术栈,提供了完整的分布式敏捷开发解决方案,支持快速构建高性能的企业级应用。此外,该工具还集成了多种中间件和服务,进一步提升了开发效率和系统的可维护性。 ... [详细]
  • 修复一个 Bug 竟耗时两天?真的有那么复杂吗?
    修复一个 Bug 竟然耗费了两天时间?这背后究竟隐藏着怎样的复杂性?本文将深入探讨这个看似简单的 Bug 为何会如此棘手,从代码层面剖析问题根源,并分享解决过程中遇到的技术挑战和心得。 ... [详细]
  • 本文提供了 RabbitMQ 3.7 的快速上手指南,详细介绍了环境搭建、生产者和消费者的配置与使用。通过官方教程的指引,读者可以轻松完成初步测试和实践,快速掌握 RabbitMQ 的核心功能和基本操作。 ... [详细]
  • 阿里巴巴Java后端开发面试:TCP、Netty、HashMap、并发锁与红黑树深度解析 ... [详细]
  • SpringBoot非官方教程|终章:文章汇总springboot非官方教程,可能最接近于官方的一个教程,大多数案例都来自于官方文档,为了更好的理解,加入了个人的改造。码云下载:htt ... [详细]
  • 工程项目管理系统源码简洁+好用+全面工程项目管理系统
    ​​工程项目管理系统是指从事工程项目管理的企业(以下简称工程项目管理企业)受业主委托,按照合同约定,代表业主对工程项目的组织 ... [详细]
  • 本文深入探讨了在使用 Spring Cloud Feign 时遇到的 `java.lang.IllegalStateException` 异常,具体表现为方法体参数过多的问题。通过详细分析异常原因和代码结构,提出了有效的解决方案,帮助开发者更好地理解和处理这一常见问题。 ... [详细]
  • 本文深入探讨了Spring Cloud Eureka在企业级应用中的高级使用场景及优化策略。首先,介绍了Eureka的安全配置,确保服务注册与发现过程的安全性。接着,分析了Eureka的健康检查机制,提高系统的稳定性和可靠性。随后,详细讨论了Eureka的各项参数调优技巧,以提升性能和响应速度。最后,阐述了如何实现Eureka的高可用性部署,保障服务的连续性和可用性。通过这些内容,开发者可以更好地理解和运用Eureka,提升微服务架构的整体效能。 ... [详细]
  • 在探讨SpringCloud环境中实现跨标签页或新窗口的单点登录机制时,重点分析了localStorage与sessionStorage的应用。通过使用localStorage存储token,可以确保其在浏览器关闭后仍有效,但需手动设置过期时间以增强安全性。相比之下,sessionStorage仅在当前会话期间有效,适用于临时数据存储。文中详细讨论了两种存储方式的技术细节及其在实际开发中的应用策略。 ... [详细]
  • 本文深入探讨了 Spring Cloud 微服务架构中 Gateway 组件的应用,详细介绍了其在实现高效请求路由与过滤方面的关键作用。文章首先从基本配置入手,逐步讲解了如何通过静态路由和动态路由实现灵活的服务访问控制。此外,还特别介绍了如何配置 Gateway 以自动从 Nacos 服务注册中心拉取服务列表,进一步提升系统的可维护性和扩展性。 ... [详细]
  • 本文深入探讨了Java枚举类型的使用与实践,详细解析了枚举的基本用法及其在实际开发中的应用。首先介绍了枚举作为常量的替代方案,自JDK 1.5起,通过枚举可以更加简洁、安全地定义常量,避免了传统方式中可能出现的错误。此外,文章还探讨了枚举在实现单例模式、状态机等场景中的优势,并提供了多个实际案例,帮助开发者更好地理解和运用这一强大的语言特性。 ... [详细]
  • 深入解析Spring Boot源码的序章
    本系列文章旨在深入解析Spring Boot的源代码,分享笔者在学习过程中的心得与体会。内容涵盖核心源码分析,可能会对初学者造成一定理解难度,建议读者结合笔者提供的详细注释进行阅读,以获得更好的学习体验。 ... [详细]
  • 优化Spring Cloud Zuul与Nginx域名转发问题的解决方案_java
    本文深入探讨了Spring Cloud Zuul与Nginx在域名转发过程中可能遇到的问题,并提供了一系列优化解决方案。通过实例分析和代码示例,详细阐述了如何有效解决这些常见问题,提升系统的稳定性和性能。希望对开发者在实际项目中遇到类似问题时有所启发和帮助。 ... [详细]
  • Spring Boot与Redis的高效集成方案
    本文探讨了Spring Boot与Redis的高效集成方法,详细介绍了如何在Spring Boot项目中配置和使用Redis,以提升应用性能和数据处理能力。同时,文章还涉及了Go语言社区的相关资源,为Golang开发者提供了宝贵的技术交流平台。 ... [详细]
  • Spring 中获取 Request 的多种方式及其线程安全性的深入解析
    本文深入探讨了在Spring MVC框架下获取HTTP请求对象的多种方法,详细分析了每种方法的实现原理及其线程安全性,为开发者提供了全面的技术参考。 ... [详细]
author-avatar
手机用户2502861905
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有