《SpringBoot系列五》:SpringBoot应用分类?默认类型如何推导出(deduceFromClasspath())?

简介: 《SpringBoot系列五》:SpringBoot应用分类?默认类型如何推导出(deduceFromClasspath())?

SpringBoot应用分类

SpringBoot2.0中的setWebApplicationTye(WebApplicationType)方法允许程序显式地设置Web应用的枚举类型。大体上分为两类:Web应用和非Web引用;

  • Web应用

    • Servlet Web (SERVLET)

      • 表示SpringBoot应用是一个servlet的web程序,对应SpringMVC;并且需要启动对应的web容器支持如tomcat等
      • 另外:需要在maven中添加spring-boot-starter-web依赖
    • Reactive Web(REACTIVE)

      • 表示SpringBoot应用是一种非阻塞的web框架,对应spring-webflux,需要启动支持reactive的web容器;
      • 需要在maven中添加spring-boot-starter-webflux依赖
  • 非Web应用(NONE)

    • 表示SpringBoot应用啥都没有,按照正常的代码走即可;不需要额外启动web容器如tomcat等

1、如何指定应用类型?

示例如下:

@SpringBootApplication
public class SpringBootApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(SpringBootTestApplication.class)
            // 设置SpringBoot应用的类型    
            .web(WebApplicationType.NONE)
                .run(args);
    }
}

2、默认SpringBoot应用类型

如果我不指定SpringBoot的应用类型呢?默认应该是什么?

一般情况下,我们的SpringBoot应用启动类是这样的:

/**
 * 省略n个注解
 */
@SpringBootApplication
public class StartApplication {

    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);
    }
}

我们顺着SpringApplication.run(StartApplication.class, args);往里跟源码,
在这里插入图片描述

经过四层进入到SpringApplicatioin的构造函数中,其中通过WebApplicationType.deduceFromClasspath()判断SpringBoot应用的类型默认应该为是什么;

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 根据classPath中类的内容判断SpringBoot应用的类型
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

WebApplicationType类的静态方法deduceFromClasspath()源码如下:

static WebApplicationType deduceFromClasspath() {
    if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
        && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
        return WebApplicationType.REACTIVE;
    }
    for (String className : SERVLET_INDICATOR_CLASSES) {
        if (!ClassUtils.isPresent(className, null)) {
            return WebApplicationType.NONE;
        }
    }
    return WebApplicationType.SERVLET;
}
/**
 * 常量部分
 */
private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
                                                           "org.springframework.web.context.ConfigurableWebApplicationContext" };

private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

代码中频繁使用到ClassUtils.isPresent()方法,通过其判断相应的类是否存在。

  • 通过Class.forName()方法尝试加载某个类,如果能够加载成功,则证明这个类存在;

    public static boolean isPresent(String className, @Nullable ClassLoader classLoader) {
        try {
            forName(className, classLoader);
            return true;
        }
        .....
        catch (Throwable ex) {
    
            return false;
        }
    }
  • 反之发生异常则代表类不存在;

所以,对于deduceFromClasspath()方法而言,本质上是通过webflux相关的类(DispatcherHandler)、Servlet相关的类(DispatcherServlet)是否存在来判断SpringBoot应用的类型;具体规则如下:

  1. 如果只能找到WebFlux相关的类,则SpringBoot应用类型为REACTIVE
  2. 如果找不到Servlet相关的上下文类,则SpringBoot应用类型为NONE
  3. 如果上述条件都不满足,则SpringBoot应用类型为SERVLET

也就是说:我们可以理解为SpringBoot的应用程序默认类型是SERVLET

相关文章
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
144 1
|
1月前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
18天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
95 62
|
10天前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
32 8
|
16天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
41 3
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第7天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建 Spring Boot 项目并配置 Spring Security。接着,实现后端 API 以提供菜单数据。在前端部分,使用 Ant Design Pro Vue 脚手架创建项目,并配置动态路由和菜单。最后,启动前后端服务,实现高效、美观且功能强大的应用框架。
41 2
|
1月前
|
搜索推荐 Java UED
SpringBoot 自定义启动画面:打造个性化应用启动体验
【10月更文挑战第7天】在软件开发中,细节往往能够体现一个团队的专业性和对用户体验的关注。SpringBoot作为快速构建Spring应用的框架,其简洁的启动流程和强大的功能深受开发者喜爱。然而,默认的启动画面可能略显单调,无法充分展示应用的特色或品牌。本文将详细介绍如何为SpringBoot应用自定义启动画面,让应用在启动时就能给人留下深刻印象。
52 1
|
19天前
|
关系型数据库 MySQL Java
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
22 0
|
1月前
|
Java Spring 容器
Springboot3.2.1搞定了类Service和bean注解同名同类型问题修复
这篇文章讨论了在Spring Boot 3.2.1版本中,同名同类型的bean和@Service注解类之间冲突的问题得到了解决,之前版本中同名bean会相互覆盖,但不会在启动时报错,而在配置文件中设置`spring.main.allow-bean-definition-overriding=true`可以解决这个问题。
85 0
Springboot3.2.1搞定了类Service和bean注解同名同类型问题修复