百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

SpringBoot中3种条件装配技术

ztj100 2025-08-02 22:48 3 浏览 0 评论

Spring Boot提供了多种条件装配技术,允许开发者根据不同条件动态配置应用程序,大大提高了应用的灵活性,本文将介绍Spring Boot中四种常用的条件装配技术。

一、@Conditional注解及派生注解

1. 基本原理

@Conditional注解是Spring 4引入的核心条件装配机制,它允许开发者根据特定条件来决定是否创建某个Bean或启用某个配置。

@Conditional的基本工作原理是:当Spring容器处理带有@Conditional注解的Bean定义时,会先评估指定的条件是否满足,只有当条件满足时,才会创建Bean或应用配置。

2. @Conditional基本用法

使用@Conditional注解时,需要指定一个实现了Condition接口的条件类:

public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

自定义条件类示例:

public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment env = context.getEnvironment();
        String os = env.getProperty("os.name");
        return os != null && os.toLowerCase().contains("linux");
    }
}

public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment env = context.getEnvironment();
        String os = env.getProperty("os.name");
        return os != null && os.toLowerCase().contains("windows");
    }
}

然后,使用这些条件类来决定Bean的创建:

@Configuration
public class OperatingSystemConfig {

    @Bean
    @Conditional(LinuxCondition.class)
    public CommandService linuxCommandService() {
        return new LinuxCommandService();
    }

    @Bean
    @Conditional(WindowsCondition.class)
    public CommandService windowsCommandService() {
        return new WindowsCommandService();
    }
}

上面的配置会根据运行环境的操作系统类型,创建不同的CommandService实现。

3. 常用派生注解

Spring Boot提供了一系列基于@Conditional的派生注解,简化了常见条件判断的配置:

@ConditionalOnClass/@ConditionalOnMissingClass

根据类路径中是否存在特定类来决定配置:

@Configuration
public class JpaConfig {

    @Bean
    @ConditionalOnClass(name = "javax.persistence.EntityManager")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        // 只有当类路径中存在JPA相关类时,才创建此Bean
        return new LocalContainerEntityManagerFactoryBean();
    }

    @Bean
    @ConditionalOnMissingClass("javax.persistence.EntityManager")
    public JdbcTemplate jdbcTemplate() {
        // 当类路径中不存在JPA相关类时,采用JdbcTemplate
        return new JdbcTemplate();
    }
}

@ConditionalOnBean/@ConditionalOnMissingBean

根据容器中是否存在特定Bean来决定配置:

@Configuration
public class DataSourceConfig {

    @Bean
    @ConditionalOnMissingBean
    public DataSource defaultDataSource() {
        // 当容器中没有DataSource类型的Bean时,创建默认数据源
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .build();
    }

    @Bean
    @ConditionalOnBean(name = "customDataSourceProperties")
    public DataSource customDataSource(CustomDataSourceProperties properties) {
        // 当存在名为customDataSourceProperties的Bean时,创建自定义数据源
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(properties.getUrl());
        dataSource.setUsername(properties.getUsername());
        dataSource.setPassword(properties.getPassword());
        return dataSource;
    }
}

@ConditionalOnProperty

根据配置属性的值来决定配置:

@Configuration
public class CacheConfig {

    @Bean
    @ConditionalOnProperty(name = "cache.type", havingValue = "redis")
    public CacheManager redisCacheManager() {
        // 当cache.type属性值为redis时,配置Redis缓存管理器
        return new RedisCacheManager();
    }

    @Bean
    @ConditionalOnProperty(name = "cache.type", havingValue = "ehcache")
    public CacheManager ehCacheManager() {
        // 当cache.type属性值为ehcache时,配置EhCache缓存管理器
        return new EhCacheCacheManager();
    }

    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "false", matchIfMissing = true)
    public CacheManager noOpCacheManager() {
        // 当cache.enabled为false或未设置时,使用空操作缓存管理器
        return new NoOpCacheManager();
    }
}

@ConditionalOnExpression

根据SpEL表达式的结果来决定配置:

@Configuration
public class SecurityConfig {

    @Bean
    @ConditionalOnExpression("${security.enabled:true} and ${security.type:basic} == 'oauth2'")
    public SecurityFilterChain oauth2SecurityFilterChain(HttpSecurity http) throws Exception {
        // 当security.enabled为true且security.type为oauth2时生效
        return http
                .oauth2Login()
                .and()
                .build();
    }

    @Bean
    @ConditionalOnExpression("${security.enabled:true} and ${security.type:basic} == 'basic'")
    public SecurityFilterChain basicSecurityFilterChain(HttpSecurity http) throws Exception {
        // 当security.enabled为true且security.type为basic时生效
        return http
                .httpBasic()
                .and()
                .build();
    }
}

@ConditionalOnWebApplication/@ConditionalOnNotWebApplication

根据应用是否为Web应用来决定配置:

@Configuration
public class ServerConfig {

    @Bean
    @ConditionalOnWebApplication
    public ServletWebServerFactory servletWebServerFactory() {
        // 只有在Web应用中才创建此Bean
        return new TomcatServletWebServerFactory();
    }

    @Bean
    @ConditionalOnNotWebApplication
    public ApplicationRunner consoleRunner() {
        // 只有在非Web应用中才创建此Bean
        return args -> System.out.println("Running as a console application");
    }
}

4. 实战示例:构建适应不同缓存环境的应用

下面通过一个实际例子,展示如何使用@Conditional系列注解构建一个能够适应不同缓存环境的应用:

@Configuration
public class FlexibleCacheConfiguration {

    @Bean
    @ConditionalOnClass(name = "org.springframework.data.redis.core.RedisTemplate")
    @ConditionalOnProperty(name = "cache.type", havingValue = "redis")
    @ConditionalOnMissingBean(CacheManager.class)
    public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheManager.RedisCacheManagerBuilder builder = 
            RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory);
        
        return builder.build();
    }

    @Bean
    @ConditionalOnClass(name = "org.ehcache.jsr107.EhcacheCachingProvider")
    @ConditionalOnProperty(name = "cache.type", havingValue = "ehcache")
    @ConditionalOnMissingBean(CacheManager.class)
    public CacheManager ehCacheCacheManager() {
        return new JCacheCacheManager(getJCacheCacheManager());
    }

    @Bean
    @ConditionalOnProperty(
        name = "cache.type", 
        havingValue = "simple", 
        matchIfMissing = true
    )
    @ConditionalOnMissingBean(CacheManager.class)
    public CacheManager simpleCacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(
            new ConcurrentMapCache("users"),
            new ConcurrentMapCache("transactions"),
            new ConcurrentMapCache("products")
        ));
        return cacheManager;
    }

    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "false")
    @ConditionalOnMissingBean(CacheManager.class)
    public CacheManager noOpCacheManager() {
        return new NoOpCacheManager();
    }
    
    private javax.cache.CacheManager getJCacheCacheManager() {
        // 创建JCache CacheManager的逻辑...
        return null; // 实际代码需要返回真实的CacheManager
    }
}

在上面的配置中:

  • 如果类路径中有Redis相关类,且配置了cache.type=redis,则使用Redis缓存
  • 如果类路径中有EhCache相关类,且配置了cache.type=ehcache,则使用EhCache
  • 如果配置了cache.type=simple或未指定类型,则使用简单的内存缓存
  • 如果配置了cache.enabled=false,则使用不执行任何缓存操作的NoOpCacheManager

5. 优缺点分析

优点:

  • 灵活强大,能适应几乎所有条件判断场景
  • 与Spring生态系统无缝集成
  • 派生注解简化了常见场景的配置
  • 条件判断逻辑与业务逻辑分离,保持代码清晰

缺点:

  • 复杂条件可能导致配置难以理解和调试
  • 条件装配的顺序可能影响最终的Bean定义

二、Profile条件配置

1. 基本原理

Profile是Spring提供的另一种条件装配机制,主要用于按环境(如开发、测试、生产)管理Bean的创建。与@Conditional相比,Profile更专注于环境区分,配置更简单。

2. @Profile注解用法

使用@Profile注解标记Bean或配置类,指定它们在哪些Profile激活时才会被创建:

@Configuration
public class DataSourceConfig {

    @Bean
    @Profile("development")
    public DataSource developmentDataSource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .build();
    }

    @Bean
    @Profile("production")
    public DataSource productionDataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/proddb");
        dataSource.setUsername("produser");
        dataSource.setPassword("prodpass");
        return dataSource;
    }
}

也可以在配置类级别应用@Profile注解,控制整个配置类的激活:

@Configuration
@Profile("development")
public class DevelopmentConfig {
    // 开发环境特有的Bean定义...
}

@Configuration
@Profile("production")
public class ProductionConfig {
    // 生产环境特有的Bean定义...
}

3. 激活Profile的方式

有多种方式可以激活指定的Profile:

通过配置文件

在application.properties或application.yml中:

# application.properties
spring.profiles.active=development

# application.yml
spring:
  profiles:
    active: development

通过命令行参数

java -jar myapp.jar --spring.profiles.active=production

通过环境变量

export SPRING_PROFILES_ACTIVE=production
java -jar myapp.jar

通过代码激活

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MyApplication.class);
        app.setAdditionalProfiles("production");
        app.run(args);
    }
}

4. Profile组合与否定

Spring Boot 2.4及以上版本提供了更灵活的Profile表达式:

使用Profile组

# application.properties
spring.profiles.group.production=proddb,prodmq
spring.profiles.group.development=devdb,devmq

上面的配置定义了两个Profile组:当激活"production"时,会同时激活"proddb"和"prodmq";当激活"development"时,会同时激活"devdb"和"devmq"。

使用否定表达式

@Bean
@Profile("!development")
public MonitoringService productionMonitoringService() {
    return new DetailedMonitoringService();
}

上面的配置表示,除了"development"之外的所有Profile都会创建这个Bean。

5. 实战示例:基于Profile的消息队列配置

下面通过一个实际例子,展示如何使用Profile来配置不同环境的消息队列连接:

@Configuration
public class MessagingConfig {

    @Bean
    @Profile("local")
    public ConnectionFactory localConnectionFactory() {
        // 本地开发使用内嵌的ActiveMQ
        return new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
    }

    @Bean
    @Profile("dev")
    public ConnectionFactory devConnectionFactory() {
        // 开发环境使用开发服务器上的RabbitMQ
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost("dev-rabbitmq.example.com");
        connectionFactory.setUsername("dev_user");
        connectionFactory.setPassword("dev_pass");
        return connectionFactory;
    }

    @Bean
    @Profile("prod")
    public ConnectionFactory prodConnectionFactory() {
        // 生产环境使用生产级RabbitMQ集群
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses("prod-rabbitmq-1.example.com,prod-rabbitmq-2.example.com");
        connectionFactory.setUsername("prod_user");
        connectionFactory.setPassword("prod_pass");
        // 生产环境增加额外配置
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setPublisherReturns(true);
        return connectionFactory;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        // 通用的RabbitTemplate配置,使用当前Profile对应的ConnectionFactory
        return new RabbitTemplate(connectionFactory);
    }
}

结合特定环境的配置文件:

# application-local.yml
spring:
  rabbitmq:
    listener:
      simple:
        concurrency: 1
        max-concurrency: 5

# application-dev.yml
spring:
  rabbitmq:
    listener:
      simple:
        concurrency: 5
        max-concurrency: 10

# application-prod.yml
spring:
  rabbitmq:
    listener:
      simple:
        concurrency: 10
        max-concurrency: 50
        retry:
          enabled: true
          initial-interval: 5000
          max-attempts: 3

6. 优缺点分析

优点:

  • 使用简单直观,专门为环境区分设计
  • 与Spring Boot配置系统完美集成
  • 支持组合和否定表达式,增强表达能力
  • 可以通过多种方式切换Profile,适应不同部署场景

缺点:

  • 表达能力有限,不如@Conditional注解灵活
  • 主要基于预定义的命名环境,处理动态条件能力较弱

三、自动配置条件

1. 基本原理

自动配置是Spring Boot的核心特性之一,它允许框架根据类路径、已有Bean和配置属性等条件,自动配置应用程序。自动配置条件是实现这一功能的基础,它通过组合使用多种条件注解,实现复杂的条件判断逻辑。

2. 常用自动配置条件组合

在Spring Boot的自动配置类中,经常可以看到多种条件注解的组合使用:

@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(prefix = "spring.datasource", name = "enabled", matchIfMissing = true)
public class DataSourceAutoConfiguration {
    // 数据源自动配置...
}

上面的配置表示:

  • 只有当类路径中存在DataSource类
  • 且容器中没有DataSource类型的Bean
  • 且spring.datasource.enabled属性不存在或为true时
  • 才会启用这个自动配置类

3. 自定义自动配置类

开发者可以创建自己的自动配置类,使用条件注解控制其激活条件:

@Configuration
@ConditionalOnClass(RedisTemplate.class)
@ConditionalOnMissingBean(CacheManager.class)
@ConditionalOnProperty(prefix = "mycache", name = "type", havingValue = "redis")
@EnableConfigurationProperties(MyCacheProperties.class)
public class RedisCacheAutoConfiguration {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory,
                                   MyCacheProperties properties) {
        RedisCacheManager.RedisCacheManagerBuilder builder = 
            RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory);
        
        if (properties.getExpireTime() > 0) {
            builder.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofSeconds(properties.getExpireTime())));
        }
        
        return builder.build();
    }
}

配置属性类:

@ConfigurationProperties(prefix = "mycache")
public class MyCacheProperties {
    
    private String type;
    private int expireTime = 3600;
    
    // getters and setters
}

4. 启用自动配置

要启用自定义的自动配置类,需要创建META-INF/spring.factories文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.config.RedisCacheAutoConfiguration

或者在Spring Boot 2.7及以上版本,可以使用
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件:

com.example.config.RedisCacheAutoConfiguration

5. 自动配置顺序控制

在复杂系统中,可能需要控制自动配置类的加载顺序,这可以通过@AutoConfigureBefore、@AutoConfigureAfter和@AutoConfigureOrder注解实现:

@Configuration
@ConditionalOnClass(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class JdbcTemplateAutoConfiguration {
    // JDBC模板自动配置,确保在数据源配置之后
}

@Configuration
@ConditionalOnClass(SecurityFilterChain.class)
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
public class SecurityAutoConfiguration {
    // 安全配置应该在Web MVC配置之前
}

@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
public class EarlyInitAutoConfiguration {
    // 需要最先初始化的配置
}

6. 实战示例:自定义监控系统自动配置

下面通过一个实际例子,展示如何使用自动配置条件创建一个可插拔的应用监控组件:

// 配置属性类
@ConfigurationProperties(prefix = "app.monitoring")
public class MonitoringProperties {
    
    private boolean enabled = true;
    private String type = "jmx";
    private int sampleRate = 10;
    private boolean logMetrics = false;
    
    // getters and setters
}

// JMX监控自动配置
@Configuration
@ConditionalOnProperty(prefix = "app.monitoring", name = "enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnProperty(prefix = "app.monitoring", name = "type", havingValue = "jmx", matchIfMissing = true)
@ConditionalOnClass(name = "javax.management.MBeanServer")
@EnableConfigurationProperties(MonitoringProperties.class)
public class JmxMonitoringAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public MetricsCollector metricsCollector(MonitoringProperties properties) {
        JmxMetricsCollector collector = new JmxMetricsCollector();
        collector.setSampleRate(properties.getSampleRate());
        return collector;
    }
    
    @Bean
    @ConditionalOnMissingBean
    public MetricsExporter metricsExporter(MonitoringProperties properties) {
        JmxMetricsExporter exporter = new JmxMetricsExporter();
        exporter.setLogMetrics(properties.isLogMetrics());
        return exporter;
    }
}

// Prometheus监控自动配置
@Configuration
@ConditionalOnProperty(prefix = "app.monitoring", name = "enabled", havingValue = "true")
@ConditionalOnProperty(prefix = "app.monitoring", name = "type", havingValue = "prometheus")
@ConditionalOnClass(name = "io.prometheus.client.CollectorRegistry")
@EnableConfigurationProperties(MonitoringProperties.class)
public class PrometheusMonitoringAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public MetricsCollector metricsCollector(MonitoringProperties properties) {
        PrometheusMetricsCollector collector = new PrometheusMetricsCollector();
        collector.setSampleRate(properties.getSampleRate());
        return collector;
    }
    
    @Bean
    @ConditionalOnMissingBean
    public MetricsExporter metricsExporter(MonitoringProperties properties) {
        PrometheusMetricsExporter exporter = new PrometheusMetricsExporter();
        exporter.setLogMetrics(properties.isLogMetrics());
        return exporter;
    }
    
    @Bean
    public CollectorRegistry collectorRegistry() {
        return new CollectorRegistry(true);
    }
    
    @Bean
    public HttpHandler prometheusEndpoint(CollectorRegistry registry) {
        return new PrometheusHttpHandler(registry);
    }
}

// 日志监控自动配置
@Configuration
@ConditionalOnProperty(prefix = "app.monitoring", name = "enabled", havingValue = "true")
@ConditionalOnProperty(prefix = "app.monitoring", name = "type", havingValue = "log")
@EnableConfigurationProperties(MonitoringProperties.class)
public class LogMonitoringAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public MetricsCollector metricsCollector(MonitoringProperties properties) {
        LogMetricsCollector collector = new LogMetricsCollector();
        collector.setSampleRate(properties.getSampleRate());
        return collector;
    }
    
    @Bean
    @ConditionalOnMissingBean
    public MetricsExporter metricsExporter() {
        return new LogMetricsExporter();
    }
}

META-INF/spring.factories文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.monitoring.JmxMonitoringAutoConfiguration,\
com.example.monitoring.PrometheusMonitoringAutoConfiguration,\
com.example.monitoring.LogMonitoringAutoConfiguration

使用示例:

# 使用JMX监控(默认)
app:
  monitoring:
    enabled: true
    type: jmx
    sample-rate: 5
    log-metrics: true

# 或使用Prometheus监控
app:
  monitoring:
    enabled: true
    type: prometheus
    sample-rate: 10

# 或使用日志监控
app:
  monitoring:
    enabled: true
    type: log
    sample-rate: 30

# 或完全禁用监控
app:
  monitoring:
    enabled: false

7. 优缺点分析

优点:

  • 实现真正的"约定优于配置"原则
  • 可以创建可插拔的组件,极大提高代码复用性
  • 与Spring Boot生态系统无缝集成

缺点:

  • 学习曲线陡峭,需要了解多种条件注解的组合使用
  • 自动配置类过多可能导致应用启动时间增加
  • 调试困难,排查问题需要深入了解Spring Boot启动机制

八、总结

条件装配技术

核心特点

主要应用场景

复杂度

@Conditional及派生注解

最灵活,支持自定义条件

需要复杂条件判断的场景

Profile条件配置

专注于环境区分

多环境部署,环境特定配置

自动配置条件

组合多种条件,实现自动配置

可插拔组件,框架开发

通过合理利用Spring Boot提供的条件装配技术,开发者可以构建出灵活、可配置的应用程序,满足不同环境和业务场景的需求。

相关推荐

这个 JavaScript Api 已被废弃!请慎用!

在开发过程中,我们可能会不自觉地使用一些已经被标记为废弃的JavaScriptAPI。这些...

JavaScript中10个“过时”的API,你的代码里还在用吗?

JavaScript作为一门不断发展的语言,其API也在持续进化。新的、更安全、更高效的API不断涌现,而一些旧的API则因为各种原因(如安全问题、性能瓶颈、设计缺陷或有了更好的替代品)被标记为“废...

几大开源免费的 JavaScript 富文本编辑器测评

MarkDown编辑器用的时间长了,发现发现富文本编辑器用起来是真的舒服。...

比较好的网页里面的 html 编辑器 推荐

如果您正在寻找嵌入到网页中的HTML编辑器,以便用户可以直接在网页上编辑HTML内容,以下是几个备受推荐的:CKEditor:CKEditor是一个功能强大的、开源的富文本编辑器,可以嵌入到...

Luckysheet 实现excel多人在线协同编辑

前言前些天看到Luckysheet支持协同编辑Excel,正符合我们协同项目的一部分,故而想进一步完善协同文章,但是遇到了一下困难,特此做声明哈,若侵权,请联系我删除文章!若侵犯版权、个人隐私,请联系...

从 Element UI 源码的构建流程来看前端 UI 库设计

作者:前端森林转发链接:https://mp.weixin.qq.com/s/ziDMLDJcvx07aM6xoEyWHQ引言...

手把手教你如何用 Decorator 装饰你的 Typescript?「实践」

作者:Nealyang转发连接:https://mp.weixin.qq.com/s/PFgc8xD7gT40-9qXNTpk7A...

推荐五个优秀的富文本编辑器

富文本编辑器是一种可嵌入浏览器网页中,所见即所得的文本编辑器。对于许多从事前端开发的小伙伴来说并不算陌生,它的应用场景非常广泛,平时发个评论、写篇博客文章等都能见到它的身影。...

基于vue + element的后台管理系统解决方案

作者:林鑫转发链接:https://github.com/lin-xin前言该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(WebManagementSystem)开发。基于v...

开源富文本编辑器Quill 2.0重磅发布

开源富文本编辑器Quill正式发布2.0版本。官方TypeScript声明...

Python之Web开发框架学习 Django-表单处理

在Django中创建表单实际上类似于创建模型。同样,我们只需要从Django类继承,则类属性将是表单字段。让我们在myapp文件夹中添加一个forms.py文件以包含我们的应用程序表单。我们将创建一个...

Django测试入门:打造坚实代码基础的钥匙

这一篇说一下django框架的自动化测试,...

Django ORM vs SQLAlchemy:到底谁更香?从入门到上头的选择指南

阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。...

超详细的Django 框架介绍,它来了!

时光荏苒,一晃小编的Tornado框架系列也结束了。这个框架虽然没有之前的FastAPI高流量,但是,它也是小编的心血呀。总共16篇博文,从入门到进阶,包含了框架的方方面面。虽然小编有些方面介绍得不是...

20《Nginx 入门教程》使用 Nginx 部署 Python 项目

今天的目标是完成一个PythonWeb项目的线上部署,我们使用最新的Django项目搭建一个简易的Web工程,然后基于Nginx服务部署该PythonWeb项目。1.前期准备...

取消回复欢迎 发表评论: