Java面试——Spring Boot

Java面试——Spring Boot

一、谈谈你对 SpringBoot 的理解


简单说说我的理解:Java是一个静态语言,相比动态语言,它相对笨重,体现在我们搭建 SSM 框架写一个 Helloword 的时候相当复杂,需要写一大堆的配置。还有在导入 jar包依赖的时候版本号问题,令人头疼。但是,我们有 Spring呀,真的是 Java 开发人员的福音。SpringBoot 就是为解决这些问题而生的。让我们写一个 Helloword 跟动态语言一样简单。版本控制也通过 SpringBoot 与 Maven的插件进行整合管理,让我们将重点放在业务的开发之上。下面就说说其优点:
【1】创建独立的 Spring 应用,可以通过 java -jar xx.jar 直接运行;
【2】直接嵌入 Tomcat、Jetty或Undertow 等 Web 容器(不需要部署 war 文件),后期与云计算平台集成方便(docket);
【3】提供固化的 “starter” 的 pom 配置简化构建 maven 配置,避免大量的 Maven导入和各种版本冲突;
【4】当条件满足时自动装配 Spring 或第三方类库;
【5】提供运维特性,基于 ssh、http、telnet 对服务器进行监控、健康检查以及外部化配置;
【6】SpringBoot 不需要 XML 配置,也不是通过代码生成来实现,而是通过条件注解+类实现配置文件;
【7】基于环境的配置使用这些属性,您可以将您正在使用的环境传递到应用程序:-Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,Spring 将在(application{environment}.properties)中加载后续的应用程序属性文件。

二、Spring 和 SpringBoot 有什么不同


【1】Maven 依赖:Spring Boot 对依赖进行了进一步封装(starter),我们只需要根据场景依赖 starter 即可。在进行构建期间,所有其他依赖项将自动添加到项目中。

 1 <!--首先,让我们看一下使用Spring创建Web应用程序所需的最小依赖项-->
 2 <dependency>
 3     <groupId>org.springframework</groupId>
 4     <artifactId>spring-web</artifactId>
 5     <version>5.1.0.RELEASE</version>
 6 </dependency>
 7 <dependency>
 8     <groupId>org.springframework</groupId>
 9     <artifactId>spring-webmvc</artifactId>
10     <version>5.1.0.RELEASE</version>
11 </dependency>
12 
13 <!--与Spring不同,Spring Boot只需要一个依赖项来启动和运行Web应用程序-->
14 <dependency>
15     <groupId>org.springframework.boot</groupId>
16     <artifactId>spring-boot-starter-web</artifactId>
17     <version>2.0.6.RELEASE</version>
18 </dependency>

【2】Spring Boot 拥有默认的配置信息,Spring Boot 只需要在 application 配置文件中配置几个属性来完成如下操作:所有Spring 配置都是通过一个名为 auto-configuration 的过程添加 Boot web starter 来自动包含的。这意味着Spring Boot 将查看应用程序中存在的依赖项,属性和 Bean,并根据这些依赖项,对属性和 bean进行配置。当然,如果我们想要添加自己的自定义配置,那么Spring Boot 自动配置将会退回。

1 spring.mvc.view.prefix=/WEB-INF/jsp/
2 spring.mvc.view.suffix=.jsp

【3】 默认情况下,Spring Boot 使用嵌入式容器来运行应用程序。在这种情况下,Spring Boot 使用 public static void main 入口点来启动嵌入式 Web服务器。此外,它还负责将 Servlet,Filter 和 ServletContextInitializerbean 从应用程序上下文绑定到嵌入式 servlet容器。Spring Boot 的另一个特性是它会自动扫描同一个包中的所有类或 Main 类的子包中的组件。Spring Boot 提供了将其部署到外部容器的方式:

1 @SpringBootApplication
2 public class Application {
   
3     public static void main(String[] args) {
   
4         SpringApplication.run(Application.class, args);
5     }
6 }

【4】打包和部署:这两个框架都支持Maven 和 Gradle 等通用包管理技术。但是在部署方面,这些框架差异很大。例如,Spring Boot Maven 插件在 Maven中提供 Spring Boot支持。它还允许打包可执行jar 或 war包。在部署环境中 Spring Boot 对比 Spring的一些优点包括:
■ 提供嵌入式容器支持;
■ 使用命令 java -jar独立运行 jar;
■ 在外部容器中部署时,可以选择排除依赖关系以避免潜在的 jar 冲突;
■ 部署时灵活指定配置文件的选项;
■ 用于集成测试的随机端口生成;

简而言之,我们可以说 Spring Boot 只是 Spring本身的扩展,使开发,测试和部署更加方便。

三、SpringBoot 与 Spring Cloud 的区别


【1】Spring Cloud 基于Spring Boot,为微服务体系开发中的架构问题,提供了一整套的解决方案——服务注册与发现,服务消费,服务保护与熔断,网关,分布式调用追踪,分布式配置管理等。
【2】Spring Cloud 是一个基于 SpringBoot 实现的云应用开发工具;SpringBoot 专注于快速、方便集成的单个个体,Spring Cloud 是关注全局的服务治理框架;SpringBoot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud 很大的一部分是基于 SpringBoot 来实现。

四、SpringBoot 中的 application.properties 或者 application.yml 配置文件是什么


application.ymlapplication.properties(默认配置文件) 文件这两种文件都是 SpringBoot的配置文件,注释都可以用#号来注释,只不过因为application.yml 看起来更直观,更清晰。但是要注意一点:properties 文件的优先级高于 yml文件,即如果两个文件中都配置了端口号,只有 properties中的端口号有效,而 yml文件中端口配置无效。
【1】application.properties 文件,在 properties文件中是以 ”.”进行分割的;

server.port=8085
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
spring.datasource.url=jdbc:mysql://aliyuncs.com:3306/home?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=***
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

【2】application.properties 文件,都是 K-V格式,并且通过 ” : ” 引号进行赋值;需要注意冒号后面有个空格;

server:
  port: 8081
 
spring:
    datasource:
        name: test
        url: jdbc:mysql://localhost:3306/springbootdatabase
        username: root
        password: 123456
        # 使用druid数据源
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        filters: stat
        maxActive: 20
        initialSize: 1
        maxWait: 60000
        minIdle: 1
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: select 'x'
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxOpenPreparedStatements: 20 

五、SpringBoot 的核心配置文件有哪几个?它们的区别是什么?


Spring Boot 中有以下两种配置文件:bootstrap (.yml 或者 .properties) 和 application (.yml 或者 .properties):bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。这两个上下文共用一个环境。它默认也不能被本地相同配置覆盖。主要给运维人员使用,可以对开发的一些配置进行覆盖。bootstrap 配置文件有以下几个应用场景:使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息。一些固定的不能被覆盖的属性和一些加密/解密的场景。

六、SpringBoot 的配置文件有哪几种格式?它们有什么区别?


.properties.yml,它们的区别主要是书写格式不同。

【1】.properties:通过.进行分割。

app.user.name = javastack

【2】.yml:赋值的时候,冒号后面有个空格。不支持 @PropertySource 注解导入配置。可以通过如下注解:@ConfigurationProperties(prefix=“xxx”) String 类型的一定需要 setter 来接收属性值;maps、collections和 arrays不需要。

app:
  user:
    name: javastack

七、SpringBoot 的核心注解是哪个?它主要由哪几个注解组成的?


启动类上面的注解是 @SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
【1】@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
【2】@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。
【3】@ComponentScan:Spring组件扫描。
源码博客连接】:链接

八、SpringBoot 自动配置及原理


【1】SpringBoot 启动的时候加载主配置类,@SpringBootApplication下开启了主配置功能 @EnableAutoConfiguration
【2】**@EnableAutoConfiguration 作用:**①、利用 EnableAutoConfigurationImportSelector 给容器导入一些组件。
②、可以查看 selectImports() 方法的内容:List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置。SpringFactoriesLoader.loadFactoryNames() 扫描所有 jar包类路径下 META‐INF/spring.factories 把扫描到的这些文件的内容包装成 properties对象从 properties中获取到 EnableAutoConfiguration.class 类(类名)对应的值,然后把他们添加在容器中。
【3】将类路径下 META-INF/spring.factories 里面配置的所有 EnableAutoConfiguration 的值加入到了容器中;

# EnableAutoConfiguration 对应 @EnableAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\

每一个这样的 xxxAutoConfiguration 类都是容器中的一个组件,都加入到容器中。用他们来做自动配置;
【4】每一个自动配置类进行自动配置,以 HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

@Configuration //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties(HttpEncodingProperties.class) //启动指定类的
//ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把
//HttpEncodingProperties加入到ioc容器中
@ConditionalOnWebApplication //Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果
//满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnClass(CharacterEncodingFilter.class) //判断当前项目有没有这个类
//CharacterEncodingFilter;SpringMVC 中进行乱码解决的过滤器;
//判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) 
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
public class HttpEncodingAutoConfiguration {
   
    //他已经和SpringBoot的配置文件映射了
    private final HttpEncodingProperties properties;
    //只有一个有参构造器的情况下,参数的值就会从容器中拿
    public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
   
        this.properties = properties;
    }

    @Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取
    @ConditionalOnMissingBean(CharacterEncodingFilter.class) //判断容器没有这个组件?
    public CharacterEncodingFilter characterEncodingFilter() {
   
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
        return filter;
    }

根据当前不同的条件判断,决定这个配置类是否生效?一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的 properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
【5】所有在配置文件中能配置的属性都是在 xxxxProperties 类中封装;配置文件能配置什么就可以参照某个功能对应的属性类

@ConfigurationProperties(prefix = "spring.http.encoding") //从配置文件中获取指定的值和bean的属性进行绑定
public class HttpEncodingProperties {
   
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF‐8");

精髓:【1】SpringBoot 启动会加载大量的自动配置类;
【2】看我们需要的功能有没有SpringBoot 默认写好的自动配置类;
【3】我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
【4】给容器中自动配置类添加组件的时候,会从 properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
xxxxAutoConfigurartion:自动配置类,给容器中添加组件。xxxxProperties:封装配置文件中相关属性;
更多配置信息连接】:链接

九、如何理解 SpringBoot 中的 Starters


Starters 可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。Starters 包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。

【1】starters 命名:Spring Boot 官方的启动器都是以 spring-boot-starter-* 命名的,代表了一个特定的应用类型。第三方的启动器不能以 spring-boot开头命名,它们都被 Spring Boot官方保留。一般第三方应该这样命名,像 mybatis 的 mybatis-spring-boot-starter。
【2】starters 分类:① Spring Boot 应用类启动器;② Spring Boot 生产启动器;③ Spring Boot 技术类启动器;④ 其他第三方启动器;

十、SpringBoot 有哪几种读取配置的方式


在 application.yml 或者 application.properties 文件中添加:

info.address=CN
info.company=SpringBoot
info.degree=high 

【1】@Value 注解读取方式:

@Component
public class InfoConfig1 {
   

    @Value("${info.address}")
    private String address;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XtdFCYs0-1612619470163)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

【2】@ConfigurationProperties 注解读取方式:

@Component
@ConfigurationProperties(prefix = "info")
public class InfoConfig2 {
   

    private String address;

    public String getAddress() {
   
        return address;
    }

    public void setAddress(String address) {
   
        this.address = address;
    }
}

【3】 @PropertySource+@Value注解:读取指定文件

@Component
@PropertySource(value = {
    "config/db-config.properties" })
public class DBConfig1 {
   

    @Value("${db.username}")
    private String username;
}

注意:@PropertySource不支持 yml文件读取。

【4】 @PropertySource+@ConfigurationProperties注解读取方式:

@Component
@ConfigurationProperties(prefix = "db")
@PropertySource(value = {
    "config/db-config.properties" })
public class DBConfig2 {
   

    private String username;

    public String getUsername() {
   
        return username;
    }

    public void setUsername(String username) {
   
        this.username = username;
    }
}

【5】 Environment 读取方式:

@Component
public class ReadByEnv {
   

    @Autowired
    private Environment environment;

    public String getServerPort() {
   
        return environment.getProperty("server.port");
    }

}

十一、Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?


Spring Boot 支持 Java Util Logging、Log4j2、Lockback 作为日志框架,如果你使用 starters启动器,Spring Boot 将使用Logback 作为默认日志框架。无论使用哪种日志框架,Spring Boot 都支持配置将日志输出到控制台或者文件中。spring-boot-starter 启动器包含 spring-boot-starter-logging 启动器并集成了slf4j 日志抽象及 Logback日志框架。

日志源码博客连接】:链接

十二、SpringBoot 实现热部署有哪几种方式


在 Spring Boot 实现代码热部署是一件很简单的事情,代码的修改可以自动部署并重新热启动项目。
【1】引用 devtools 依赖:当修改 java类时就会热更新。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
	<optional>true</optional>
</dependency>

【2】然后依次点击 File-Settings-Build、Execution、Deployment-Complier,在右边界面找到图: 并打勾;下一步按住这几个键 Ctrl+Shift+Alt+/,选中 Registry ,在弹出的提示框中找到 compiler.automake.allow.when.app.running 如下图并打钩,就可以顺利使用了。
img

【3】devtools 会在 windows资源管理器占用 java进程,在开发工具里面杀不掉,只能手动 kill掉,不然重启会选成端口重复绑定报错。

注意事项:1、生产环境 devtools将被禁用,如 java -jar方式或者自定义的类加载器等都会识别为生产环境。
2、打包应用默认不会包含 devtools,除非你禁用 SpringBoot Maven 插件的 excludeDevtools 属性。
3、Thymeleaf 无需配置 spring.thymeleaf.cache:false,devtools 默认会自动设置,参考完整属性。

十三、如何理解 Spring Boot 配置加载顺序


Spring Boot 会涉及到各种各样的配置,如开发、测试、生产就至少 3 套配置信息了。Spring Boot 可以轻松的帮助我们使用相同的代码就能使开发、测试、生产环境使用不同的配置。在 Spring Boot 里面,可以使用以下几种方式来加载配置:
【1】properties文件;
【2】YML文件;
【3】系统环境变量;
【4】命令行参数等等;

配置属性加载的顺序如下】:数字小的优先级越高,即数字小的会覆盖数字大的参数值,我们来实践下,验证以上配置参数的加载顺序。

 1、开发者工具 `Devtools` 全局配置参数; 
 2、单元测试上的 `@TestPropertySource` 注解指定的参数; 
 3、单元测试上的 `@SpringBootTest` 注解指定的参数; 
 4、命令行指定的参数,如 `java -jar springboot.jar --name="Java技术栈"`; 
 5、命令行中的 `SPRING_APPLICATION_JSONJSON` 指定参数, 如 `java Dspring.application.json='{"name":"Java技术栈"}' -jar springboot.jar` 
 6、`ServletConfig` 初始化参数; 
 7、`ServletContext` 初始化参数; 
 8、JNDI参数(如 `java:comp/env/spring.application.json`); 
 9、Java系统参数(来源:`System.getProperties()`); 
10、操作系统环境变量参数; 
11、`RandomValuePropertySource` 随机数,仅匹配:`ramdom.*`; 
12、JAR包外面的配置文件参数(`application-{
    profile}.properties(YAML)`) 
13、JAR包里面的配置文件参数(`application-{
    profile}.properties(YAML)`) 
14、JAR包外面的配置文件参数(`application.properties(YAML)`) 
15、JAR包里面的配置文件参数(`application.properties(YAML)`) 
16、`@Configuration`配置文件上 `@PropertySource` 注解加载的参数; 
17、默认参数(通过 `SpringApplication.setDefaultProperties` 指定);

十四、Spring Boot 如何定义多套不同环境配置


首先我们要了解一个名词:Profile。简单来说,Profile 就是 Spring Boot 可以对不同环境或者指令来读取不同的配置文件。假如有开发、测试、生产三个不同的环境,需要定义三个不同环境下的配置。

【1】基于 properties文件类型:你可以另外建立3个环境下的配置文件:然后在 applcation.properties 文件中指定当前的环境 spring.profiles.active=test,这时候读取的就是 application-test.properties文件。

applcation.properties
application-dev.properties
application-test.properties
application-prod.properties

【2】基于 yml文件类型:只需要一个 applcation.yml 文件就能搞定,推荐此方式。此时读取的就是 dev的配置。

spring:
  profiles:
    active: dev

---
#开发环境配置
spring:
  profiles: dev

server:
  port: 1000


---
#测试环境配置
spring:
  profiles: stg

server:
  port: 1001


---
#生产环境配置
spring:
  profiles: prd

server:
  port: 1002

【3】在 cmd 命令中指定:

java -jar xxx.jar --spring.profiles.actvie=dev 

【4】在IDEA 编辑器中指定:在运行按钮(绿色三角形按钮)旁边选择 Edit Configurations...,在弹出的对话框中 Active profiles 输入 dev 或其他即可。这种方法只有在本地调试的时候才生效。
优秀博客连接】:链接

十五、SpringBoot 启动类的原理


源码连接】:链接

十六、SpringBoot 静态资源配置及原理


源码连接】:链接

十七、SpringBoot 国际化配置及原理


源码连接】:链接

十八、SpringBoot 模板引擎配置及原理


源码连接】:链接

十九、SpringBoot 错误页面配置及原理


源码连接】:链接

二十、SpringBoot 拦截器配置及原理


源码连接】:链接

二十一、SpringBoot MVC配置及原理


源码连接】:链接

二十二、SpringBoot 嵌入式容器配置及原理


源码连接】:链接

二十三、如何在 Spring Boot 启动的时候运行一些特定的代码


如果想在 Spring Boot 启动的时候运行一些特定的代码,你可以实现接口 ApplicationRunner 或者 CommandLineRunner,这两个接口实现方式一样,它们都只提供了一个run方法。CommandLineRunner:启动获取命令行参数:

public interface CommandLineRunner{
   
    void run(String... args) throws Exception;
}

ApplicationRunner:启动获取应用启动的时候参数:

public interface ApplicationRunner{
   
    void run(ApplicationArguments args) throws Exception;
}

启动顺序】:如果启动的时候有多个 ApplicationRunner 和CommandLineRunner,想控制它们的启动顺序,可以实现org.springframework.core.Ordered 接口或者使用 org.springframework.core.annotation.Order 注解。

二十四、自己实现一个 start


CommandLineRunner:启动获取命令行参数:

public interface CommandLineRunner{
   
    void run(String... args) throws Exception;
}

ApplicationRunner:启动获取应用启动的时候参数:

public interface ApplicationRunner{
   
    void run(ApplicationArguments args) throws Exception;
}

启动顺序】:如果启动的时候有多个 ApplicationRunner 和CommandLineRunner,想控制它们的启动顺序,可以实现org.springframework.core.Ordered 接口或者使用 org.springframework.core.annotation.Order 注解。

二十四、自己实现一个 start


博客链接】:链接

本文来源程序猿进阶,由javajgs_com转载发布,观点不代表Java架构师必看的立场,转载请标明来源出处:https://javajgs.com/archives/8292

发表评论