1 一个简单的示例

Spring Boot项目中使用spring-rabbit时,需要经过以下几个步骤:

  1. 引入依赖。
  2. 配置基本连接信息。
  3. 创建消息发布者,并发送消息。
  4. 创建消息消费者,监听消息并处理。

我们以一个简单的例子开始,展示这个基本过程。

1.1 引入依赖

如果是Maven项目,需要在pom.xml文件中引入基本依赖如下:

  1. <dependency>
  2. <groupId>org.springframework.amqp</groupId>
  3. <artifactId>spring-rabbit</artifactId>
  4. <version>2.3.10</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-autoconfigure</artifactId>
  9. <version>2.5.5</version>
  10. </dependency>

其中:

  • spring-rabbit用于与RabbitMQ服务器交互的工具包
  • spring-boot-autoconfigure用于自动配置RabbitMQ客户端服务器连接等基本信息。

1.2 配置连接信息

由于spring-boot-autoconfigure的自动配置功能,我们仅需要在application.yml文件中配置连接信息即可。以下是一个例子:

  1. spring:
  2. rabbitmq:
  3. host: localhost
  4. port: 5672
  5. username: guest
  6. password: guest
  7. virtual-host: /

其中:

  • host:服务器地址。
  • port:服务器端口。
  • username:用户名。
  • password:密码。
  • virtual-host:交换机/队列所属虚拟主机。

1.3 消息发布者&消费者

我们直接在Spring Boot主程序中简单编写一个发布&接收消息的示例:

  1. @SpringBootApplication
  2. public class Application {
  3. public static void main(String[] args) {
  4. SpringApplication.run(Application.class, args);
  5. }
  6. @Bean
  7. public Queue myQueue() {
  8. return new Queue("myQueue");
  9. }
  10. @RabbitListener(queues = "myQueue")
  11. public void listen(String in) {
  12. System.out.println(in);
  13. }
  14. @Bean
  15. public ApplicationRunner runner(AmqpTemplate template) {
  16. return args -> template.convertAndSend("myQueue", "Hello World!");
  17. }
  18. }

我们在这段代码中做了如下工作:

  1. 声明队列myQueue
  2. 创建消息消费者,监听队列myQueue
  3. 使用AmqpTemplate对象,向消息队列myQueue发送消息:Hello World!

1.4 启动项目

如果我们在本地启动了RabbitMQ服务器,并且端口、用户名和密码都没有问题。

那么启动项目,可以从控制台得到如下输出:

  1. Hello World!

1.5 提出问题

不知道大家会不会有这些疑问:

  1. 为什么在application.yml文件中写入这些字符就可以连接到RabbitMQ服务器
  2. AmqpTemplate对象为什么不用声明就可以直接使用?

其实,这一切的功劳都归因于我们引入了spring-boot-autoconfigure。它为我们做了以下基本工作:

  1. application.yml文件中读取基本配置信息。
  2. 使用基本配置信息为我们创建出AmqpTemplate等对象,存放到Spring容器中。

接下来,由我来给大家揭开spring-boot-autoconfigurespring-rabbit自动配置的面纱。

2 RabbitProperties

2.1 看看源码

spring-boot-autoconfigure依赖的org.springframework.boot.autoconfigure.amqp包下,有个RabbitProperties类。

它的作用是:从application.yml文件中读取到spring-rabbit相关配置信息。

IDEA中,我们可以简单使用以下方法进入到这个类。

方法一,从application.yml文件进入:

  • application.yml文件中,按住Ctrl键,鼠标左键点击某个配置信息。

方法二,搜索:

  • 快速连续按两下Shift键,跳出搜索框进行搜索。

RabbitProperties源码简要如下:

  1. package org.springframework.boot.autoconfigure.amqp;
  2. @ConfigurationProperties(prefix = "spring.rabbitmq")
  3. public class RabbitProperties {
  4. private static final int DEFAULT_PORT = 5672;
  5. private static final int DEFAULT_PORT_SECURE = 5671;
  6. private String host = "localhost";
  7. private Integer port;
  8. private String username = "guest";
  9. private String password = "guest";
  10. private final Ssl ssl = new Ssl();
  11. private String virtualHost;
  12. private String addresses;
  13. private AddressShuffleMode addressShuffleMode = AddressShuffleMode.NONE;
  14. @DurationUnit(ChronoUnit.SECONDS)
  15. private Duration requestedHeartbeat;
  16. private int requestedChannelMax = 2047;
  17. private boolean publisherReturns;
  18. private ConfirmType publisherConfirmType;
  19. private Duration connectionTimeout;
  20. private Duration channelRpcTimeout = Duration.ofMinutes(10);
  21. private final Cache cache = new Cache();
  22. private final Listener listener = new Listener();
  23. private final Template template = new Template();
  24. private List<Address> parsedAddresses;
  25. }

2.2 功能讲解

通过简单阅读RabbitProperties,我们可以发现两点重要信息:

  • 该类添加了@ConfigurationProperties(prefix = "spring.rabbitmq")注解。
  • 该类的部分成员变量名与application.yml中配置信息名一致,例如hostportusernamepasswordvirtual-host

在此我们需要先简单了解@ConfigurationProperties注解的功能:

  1. @ConfigurationProperties可以用来获取外部配置信息,默认是application.ymlSpring Boot配置文件。
  2. 将该注解添加到类上,会通过setter(默认)或constructor方法的方式,将外部配置信息赋值给对应成员变量。
  3. prefix可以指定配置文件中的前缀,用来将外部配置信息与成员变量进行匹配。

回到RabbitProperties源码,我们应该很容易理解RabbitProperties的功能:

  1. application.yml文件中读取前缀为spring.rabbitmq的配置信息。
  2. setter方法将配置信息赋值给对应的成员变量。

通过上述过程,完成了将配置信息从文件读取到缓存(RabbitProperties对象)的过程,以便于后续使用。

2.3 动手实战

我们也可以编写一个类似的MyRabbitProperties,用来从application.yml文件中读取RabbitMQ配置信息。

2.3.1 MyRabbitProperties

代码如下:

  1. @ConfigurationProperties(prefix = "spring.rabbitmq")
  2. public class MyRabbitProperties {
  3. private String host;
  4. private Integer port;
  5. private String username;
  6. private String password;
  7. private String virtualHost;
  8. public void setHost(String host) {
  9. this.host = host;
  10. }
  11. public void setPort(Integer port) {
  12. this.port = port;
  13. }
  14. public void setUsername(String username) {
  15. this.username = username;
  16. }
  17. public void setPassword(String password) {
  18. this.password = password;
  19. }
  20. public void setVirtualHost(String virtualHost) {
  21. this.virtualHost = virtualHost;
  22. }
  23. @Override
  24. public String toString() {
  25. return "MyRabbitProperties{" +
  26. "host='" + host + '\'' +
  27. ", port=" + port +
  28. ", username='" + username + '\'' +
  29. ", password='" + password + '\'' +
  30. ", virtualHost='" + virtualHost + '\'' +
  31. '}';
  32. }
  33. }

简要说明:

  • 添加@ConfigurationProperties(prefix = "spring.rabbitmq"),用来从application.yml文件中读取前缀为spring.rabbitmq的配置信息。
  • 添加setter方法,用来为成员变量注入配置信息。
  • 添加toString()方法,便于后续打印信息。

2.3.2 application.yml

我们在application.yml文件中写入如下配置信息:

  1. spring:
  2. rabbitmq:
  3. host: localhost
  4. port: 5672
  5. username: guest
  6. password: guest
  7. virtual-host: /

2.3.3 启动类

我们简单编写如下启动类:

  1. @EnableConfigurationProperties(MyRabbitProperties.class)
  2. @SpringBootApplication
  3. public class Application {
  4. public static void main(String[] args) {
  5. SpringApplication.run(Application.class, args);
  6. }
  7. @Bean
  8. public ApplicationRunner runner(MyRabbitProperties properties) {
  9. return args -> {
  10. System.out.println(properties);
  11. };
  12. }
  13. }

简要说明:

  • 添加SpringBootApplication注解,表明这是一个Spring Boot启动类。
  • 添加@EnableConfigurationProperties(MyRabbitProperties.class)注解,可以将@ConfigurationProperties标注的类声明为Bean。这样Spring容器才能为MyRabbitProperties注入配置信息。
  • 添加main()函数,用来启动Spring Boot项目。
  • 声明ApplicationRunnerBean,项目启动后会执行其中的代码。

需要注意的是:联合@EnableConfigurationProperties只是@ConfigurationProperties注解使用方式的一种。我们也可以直接在MyRabbitProperties类上标注@Configuration@Component等注解,直接声明为Bean

2.3.4 启动项目

启动项目后,可以从控制台中得到如下输出,说明我们成功将配置信息注入到MyRabbitProperteis对象中:

  1. MyRabbitProperties{host='localhost', port=5672, username='guest', password='guest', virtualHost='/'}

3 RabbitAutoConfiguration

通过RabbitProperteis我们已经从application.yml文件中获取到了连接RabbitMQ服务器的配置信息,接下来我们继续揭秘:

  • spring-boot-autoconfigure为我们预先创建了哪些Bean
  • 它是如何创建这些Bean的?

预先小结:这些功能都在RabbitAutoConfiguration中。

3.1 看看源码

spring-boot-autoconfigure依赖的org.springframework.boot.autoconfigure.amqp包下,有个RabbitAutoConfiguration类。

它的作用是,当类路径中存在RabbitMQSpring AMQP客户端类库时,可能会为我们自动创建如下Bean

  • org.springframework.amqp.rabbit.connection.CachingConnectionFactory:创建客户端与RabbitMQ服务器连接的工厂。
  • org.springframework.amqp.core.AmqpAdmin:封装了声明交换机/消息队列/绑定等模板方法。
  • org.springframework.amqp.rabbit.core.RabbitTemplate:封装了与RabbitMQ服务器交互的模板方法,例如:发送消息和接收消息等。
  • org.springframework.amqp.rabbit.core.RabbitMessagingTemplate:功能与RabbitTemplate相同,但底层使用org.springframework.messaging.Message作为消息抽象,较少使用。

IDEA中,我们可以简单使用以下方法进入到这个类:

  • 快速连续按两下Shift键,跳出搜索框进行搜索。

其源码结构如下:

  1. package org.springframework.boot.autoconfigure.amqp;
  2. @Configuration(proxyBeanMethods = false)
  3. @ConditionalOnClass({ RabbitTemplate.class, Channel.class })
  4. @EnableConfigurationProperties(RabbitProperties.class)
  5. @Import(RabbitAnnotationDrivenConfiguration.class)
  6. public class RabbitAutoConfiguration {
  7. // 创建连接工厂Bean
  8. protected static class RabbitConnectionFactoryCreator {}
  9. // 创建RabbitTemplate和AmqpAdmin
  10. protected static class RabbitTemplateConfiguration {}
  11. // 创建RabbitMessagingTemplate
  12. protected static class MessagingTemplateConfiguration {}
  13. }

3.2 功能讲解

通过简单阅读源码,我们可以将其分成四个部分进行介绍:

  1. RabbitAutoConfiguration标注注解:自动配置主类。
  2. RabbitConnectionFactoryCreator内部类:创建连接工厂,默认为CachingConnectionFactory
  3. RabbitTemplateConfiguration内部类:创建RabbitTemplateAmqpAdmin
  4. MessagingTemplateConfiguration内部类:创建RabbitMessagingTemplate

接下来,我们分别来介绍它们的功能。

3.2.1 配置主类

RabbitAutoConfiguration配置主类标注如以下四个注解:

  • @Configuration(proxyBeanMethods = false)
  • @ConditionalOnClass({ RabbitTemplate.class, Channel.class })
  • @EnableConfigurationProperties(RabbitProperties.class)
  • @Import(RabbitAnnotationDrivenConfiguration.class)

1、@Configuration(proxyBeanMethods = false)

@ConfigurationRabbitAutoConfiguration标注成配置类,可以在其内部声明Bean

proxyBeanMethods = false表示Spring容器不会动态代理内部用@Bean标注的方法,可以提高性能。

2、@ConditionalOnClass({ RabbitTemplate.class, Channel.class })

@ConditionalOnClass注解表示只有当类路径中存在以下类时,才会将RabbitAutoConfiguration注册成Bean

  • org.springframework.amqp.rabbit.core.RabbitTemplate
  • com.rabbitmq.client.Channel

也就是说,只有在类路径中存在RabbitMQSpring AMQP客户端类库,Spring容器才会为我们对RabbitMQ进行自动配置。

4、@EnableConfigurationProperties(RabbitProperties.class)

@EnableConfigurationProperties@ConfigurationProperties注解联用,可以将RabbitProperties注册成Bean,从而将配置信息从application.yml读取到内存中。

5、@Import(RabbitAnnotationDrivenConfiguration.class)

@Import注解可以引入另外的配置类——RabbitAnnotationDrivenConfiguration:用于配置Spring AMQP注解驱动断点

简单来说,它为我们注册了如下Bean

  • org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory:创建SimpleMessageListenerContainer的工厂。
  • DirectRabbitListenerContainerFactory:创建DirectMessageListenerContainer的工厂。

这两个XxxListenerContainer主要用来监听RabbitMQ服务器发送的消息。

因此,RabbitAnnotationDrivenConfiguration配置类主要与监听消息有关。由于篇幅限制,这里就不进行深入讲解了。其源码结构如下:

  1. package org.springframework.boot.autoconfigure.amqp;
  2. @Configuration(proxyBeanMethods = false)
  3. @ConditionalOnClass(EnableRabbit.class)
  4. class RabbitAnnotationDrivenConfiguration {
  5. @Bean
  6. @ConditionalOnMissingBean
  7. SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFactoryConfigurer() {}
  8. @Bean(name = "rabbitListenerContainerFactory")
  9. @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
  10. @ConditionalOnProperty(prefix = "spring.rabbitmq.listener", name = "type", havingValue = "simple",
  11. matchIfMissing = true)
  12. SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(}
  13. @Bean
  14. @ConditionalOnMissingBean
  15. DirectRabbitListenerContainerFactoryConfigurer directRabbitListenerContainerFactoryConfigurer() {}
  16. @Bean(name = "rabbitListenerContainerFactory")
  17. @ConditionalOnMissingBean(name = "rabbitListenerContainerFactory")
  18. @ConditionalOnProperty(prefix = "spring.rabbitmq.listener", name = "type", havingValue = "direct")
  19. DirectRabbitListenerContainerFactory directRabbitListenerContainerFactory(}
  20. @Configuration(proxyBeanMethods = false)
  21. @EnableRabbit
  22. @ConditionalOnMissingBean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
  23. static class EnableRabbitConfiguration {}
  24. }

3.2.2 RabbitConnectionFactoryCreator内部类

RabbitConnectionFactoryCreator内部类的作用是:注册CachingConnectionFactory作为连接工厂Bean

其头部标注了以下两个注解:

  • @Configuration(proxyBeanMethods = false):声明为配置类。
  • @ConditionalOnMissingBean(ConnectionFactory.class):只有org.springframework.amqp.rabbit.connection.ConnectionFactory类存在时才会生效,即只有类路径中添加了spring-rabbit依赖时才会生效。

其内部默认将CachingConnectionFactory注册为连接工厂Bean,步骤如下:

  1. 实例化CachingConnectionFactory对象。
  2. 将配置文件中的配置信息注入到CachingConnectionFactory对象中。

其源码简要如下:

  1. @Configuration(proxyBeanMethods = false)
  2. @ConditionalOnMissingBean(ConnectionFactory.class)
  3. protected static class RabbitConnectionFactoryCreator {
  4. // 注册CachingConnectionFactory作为连接工厂Bean
  5. @Bean
  6. public CachingConnectionFactory rabbitConnectionFactory(RabbitProperties properties,
  7. ResourceLoader resourceLoader, ObjectProvider<CredentialsProvider> credentialsProvider,
  8. ObjectProvider<CredentialsRefreshService> credentialsRefreshService,
  9. ObjectProvider<ConnectionNameStrategy> connectionNameStrategy,
  10. ObjectProvider<ConnectionFactoryCustomizer> connectionFactoryCustomizers) throws Exception {
  11. // 1、实例化CachingConnectionFactory对象
  12. com.rabbitmq.client.ConnectionFactory connectionFactory = getRabbitConnectionFactoryBean(properties,
  13. resourceLoader, credentialsProvider, credentialsRefreshService).getObject();
  14. connectionFactoryCustomizers.orderedStream()
  15. .forEach((customizer) -> customizer.customize(connectionFactory));
  16. CachingConnectionFactory factory = new CachingConnectionFactory(connectionFactory);
  17. // 2、将配置文件中的配置信息注入到CachingConnectionFactory对象中
  18. PropertyMapper map = PropertyMapper.get();
  19. map.from(properties::determineAddresses).to(factory::setAddresses);
  20. // 省略其他map.from().to()方法
  21. return factory;
  22. }
  23. // 实例化RabbitConnectionFactoryBean对象
  24. private RabbitConnectionFactoryBean getRabbitConnectionFactoryBean(RabbitProperties properties,
  25. ResourceLoader resourceLoader, ObjectProvider<CredentialsProvider> credentialsProvider,
  26. ObjectProvider<CredentialsRefreshService> credentialsRefreshService) {
  27. // 省略
  28. return factory;
  29. }
  30. }

3.2.3 RabbitTemplateConfiguration内部类

RabbitTemplateConfiguration内部类的作用是:注册RabbitTemplateAmqpAdmin作为交互模板Bean

其头部标注了以下两个注解:

  • @Configuration(proxyBeanMethods = false):声明为配置类。
  • @Import(RabbitConnectionFactoryCreator.class):引入RabbitConnectionFactoryCreator配置类。

其内部默认注册RabbitTemplateAmqpAdmin作为交互模板Bean,本质上就是实例化对象。源码简要如下:

  1. @Configuration(proxyBeanMethods = false)
  2. @Import(RabbitConnectionFactoryCreator.class)
  3. protected static class RabbitTemplateConfiguration {
  4. @Bean
  5. @ConditionalOnMissingBean
  6. public RabbitTemplateConfigurer rabbitTemplateConfigurer(RabbitProperties properties,
  7. ObjectProvider<MessageConverter> messageConverter,
  8. ObjectProvider<RabbitRetryTemplateCustomizer> retryTemplateCustomizers) {
  9. RabbitTemplateConfigurer configurer = new RabbitTemplateConfigurer();
  10. configurer.setMessageConverter(messageConverter.getIfUnique());
  11. configurer
  12. .setRetryTemplateCustomizers(retryTemplateCustomizers.orderedStream().collect(Collectors.toList()));
  13. configurer.setRabbitProperties(properties);
  14. return configurer;
  15. }
  16. // 注册RabbitTemplate
  17. @Bean
  18. @ConditionalOnSingleCandidate(ConnectionFactory.class)
  19. @ConditionalOnMissingBean(RabbitOperations.class)
  20. public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
  21. RabbitTemplate template = new RabbitTemplate();
  22. configurer.configure(template, connectionFactory);
  23. return template;
  24. }
  25. // 注册AmqpAdmin
  26. @Bean
  27. @ConditionalOnSingleCandidate(ConnectionFactory.class)
  28. @ConditionalOnProperty(prefix = "spring.rabbitmq", name = "dynamic", matchIfMissing = true)
  29. @ConditionalOnMissingBean
  30. public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {
  31. return new RabbitAdmin(connectionFactory);
  32. }
  33. }

3.2.4 MessagingTemplateConfiguration内部类

MessagingTemplateConfiguration内部类的作用是:注册RabbitMessagingTemplate作为交互模板Bean

RabbitMessagingTemplateRabbitTemplate的功能没有本质差别,它们的差别在于继承结构不同:

  • RabbitMessagingTemplate:继承自org.springframework.messaging.core.AbstractMessageSendingTemplate抽象类。
  • RabbitTemplate:继承自org.springframework.amqp.rabbit.connection.RabbitAccessor抽象类。

项目中通常使用的是RabbitTemplate

MessagingTemplateConfiguration内部类的源码如下:

  1. @Configuration(proxyBeanMethods = false)
  2. @ConditionalOnClass(RabbitMessagingTemplate.class)
  3. @ConditionalOnMissingBean(RabbitMessagingTemplate.class)
  4. @Import(RabbitTemplateConfiguration.class)
  5. protected static class MessagingTemplateConfiguration {
  6. @Bean
  7. @ConditionalOnSingleCandidate(RabbitTemplate.class)
  8. public RabbitMessagingTemplate rabbitMessagingTemplate(RabbitTemplate rabbitTemplate) {
  9. return new RabbitMessagingTemplate(rabbitTemplate);
  10. }
  11. }

4 总结

通过以上的简单介绍,想必大家对Spring Boot项目spring-rabbit的自动配置有了大概的了解。

Spring Boot对其他工具,如:spring-webspring-securityspring-datasourcespring-transactionspring-kafka以及spring.jackson等都采用类似的自动配置方式,大家可以采用本文类似的步骤阅读相关源码。

本篇文章就到这里了,希望大家身体健康,工作顺利!

[spring-rabbit]自动配置原理的更多相关文章

  1. Spring Boot自动配置原理、实战

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  2. Spring Boot自动配置原理(转)

    第3章 Spring Boot自动配置原理 3.1 SpringBoot的核心组件模块 首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量: 我们cd到spring-boot- ...

  3. Spring Boot自动配置原理与实践(二)

    前言 在之前的博文(Spring Boot自动配置原理与实践(一))中,已经介绍了Spring boot的自动配置的相关原理与概念,本篇主要是对自动配置的实践,即自定义Starter,对原理与概念加深 ...

  4. Springboot 系列(三)Spring Boot 自动配置原理

    注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring ...

  5. spring boot 自动配置原理

    1).spring boot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration,先看一下启动类的main方法 public ConfigurableApplic ...

  6. Spring Boot 自动配置原理(精髓)

    一.自动配置原理(掌握) SpringBoot启动项目会加载主配置类@SpringBootApplication,开启@EnableAutoConfiguration自动配置功能 @EnableAut ...

  7. Spring Boot自动配置原理与实践(一)

    前言 Spring Boot众所周知是为了简化Spring的配置,省去XML的复杂化配置(虽然Spring官方推荐也使用Java配置)采用Java+Annotation方式配置.如下几个问题是我刚开始 ...

  8. 【串线篇】spring boot自动配置原理

    配置文件到底能写什么?怎么写?自动配置原理: 配置文件能配置的属性参照 一.自动配置原理: 1.1.SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfigur ...

  9. Spring Boot自动配置原理

    使用Spring Boot之后,一个整合了SpringMVC的WEB工程开发,变的无比简单,那些繁杂的配置都消失不见了,这 是如何做到的? 一切魔力的开始,都是从我们的main函数来的,所以我们再次来 ...

  10. Spring Boot 自动配置原理是什么?

    注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,首先它得是一个配置文件,其次根据类路径下是否有这个 ...

随机推荐

  1. Ansible部署及配置介绍

    原文转自:https://www.cnblogs.com/itzgr/p/10233932.html作者:木二 目录 一 Ansible的安装部署 1.1 PIP方式 1.2 YUM方式 二 Ansi ...

  2. 第一次实战:XX漫画的XSS盲打

    第一次实战:XX漫画的XSS盲打 XSS盲打 盲打是一种惯称的说法,就是不知道有没有XSS漏洞存在的情况下,不顾一切的输入XSS代码在留言啊投诉窗口啊之类的地方,尽可能多的尝试XSS的语句,就叫盲打. ...

  3. 基于源码编译的lnmp架构实现论坛的搭建及memcache的应用

    系统环境: RHEL6 x86-64 selinux and iptables disabled LNMP代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构 Linux是一类 ...

  4. 磁盘“Seagate”没有被推出,因为一个或多个程序可能正在使用它。

    推出移动硬盘失败,解决方案: 执行 lsof /Volumes/Seagate/ 可以看到哪些进程在占用磁盘 $ lsof /Volumes/Seagate/ COMMAND PID USER FD ...

  5. vue + WangEnduit

    components 注册组件 <template lang="html"> <div class="editor"> <div ...

  6. JS 之 每日一题 之 算法 ( 划分字母区间 )

    题目详解: 字符串 S 由小写字母组成.我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段.返回一个表示每个字符串片段的长度的列表. 例子: 示例 1: 输入:S = &quo ...

  7. Vs code自动生成Doxygen格式注释

    前言 ​ 程序中注释的规范和统一性的重要性不言而喻,本文就推荐一种在用vscode编写代码时自动化生成标准化注释格式的方法,关于Doxygen规范及其使用可查看博文 代码注释规范之Doxygen. ​ ...

  8. Flask - 访问返回字典的接口报错:The view function did not return a valid response. The return type must be a string, tuple, Response instance, or WSGI callable, but it was a dict.

    背景 有一个 Flask 项目,然后有一个路由返回的是 dict 通过浏览器访问,结果报错 关键报错信息 TypeError: 'dict' object is not callable The vi ...

  9. 测试开发【提测平台】分享9-DBUntils优化数据连接&实现应用搜索和分页功能

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 从本期开始知识点讲以思维导图的形式给出,内容点会按照讲解-应用-展示的形式体现,这样会更清晰些. DBUntils连接池 在项目中链接数据 ...

  10. vue页面跳转以及传参和取参

    vue中this.$router.push()路由传值和获取的两种常见方法 1.路由传值   this.$router.push() (1) 想要导航到不同的URL,使用router.push()方法 ...