💂 个人主页: Java程序鱼

💬 如果文章对你有帮助,欢迎关注、点赞、收藏(一键三连)和订阅专栏

👤 微信号:hzy1014211086,想加入技术交流群的小伙伴可以加我好友,群里会分享学习资料、学习方法


序号 内容 链接地址
1 Java基础知识面试题 https://blog.csdn.net/qq_35620342/article/details/119636436
2 Java集合容器面试题 https://blog.csdn.net/qq_35620342/article/details/119947254
3 Java并发编程面试题 https://blog.csdn.net/qq_35620342/article/details/119977224
4 Java异常面试题 https://blog.csdn.net/qq_35620342/article/details/119977051
5 JVM面试题 https://blog.csdn.net/qq_35620342/article/details/119948989
6 Java Web面试题 https://blog.csdn.net/qq_35620342/article/details/119642114
7 Spring面试题 https://blog.csdn.net/qq_35620342/article/details/119956512
8 Spring MVC面试题 https://blog.csdn.net/qq_35620342/article/details/119965560
9 Spring Boot面试题 https://blog.csdn.net/qq_35620342/article/details/120333717
10 MyBatis面试题 https://blog.csdn.net/qq_35620342/article/details/119956541
11 Spring Cloud面试题 待分享
12 Redis面试题 https://blog.csdn.net/qq_35620342/article/details/119575020
13 MySQL数据库面试题 https://blog.csdn.net/qq_35620342/article/details/119930887
14 RabbitMQ面试题 待分享
15 Dubbo面试题 待分享
16 Linux面试题 待分享
17 Tomcat面试题 待分享
18 ZooKeeper面试题 待分享
19 Netty面试题 待分享
20 数据结构与算法面试题 待分享

1.什么是 Spring Boot?

Spring Boot (Boot 顾名思义,是引导的意思)框架是用于简化 Spring 应用从搭建到开发的过程。应用开箱即用,只要通过一个指令,包括命令行 java -jar 、SpringApplication 应用启动类 、 Spring Boot Maven 插件等,就可以启动应用了。另外,Spring Boot 强调只需要很少的配置文件,所以在开发生产级 Spring 应用中,让开发变得更加高效和简易。目前,Spring Boot 版本是 2.x 版本。

2.Spring Boot 有哪些优点?

Spring Boot 主要有如下优点:

  • 简化Spring初始搭建以及开发过程,在短时间内快速构建项目
  • SpringBoot集成了大量的常用第三方库,例如Redis、Mongodb、JPA等,编码非常简单
  • SpringBoot提供了丰富的starter,集成主流的开源产品,只需要少量配置或零配置即可
  • SpringBoot内嵌了容器,通过简单命令就可以启动

3.为什么要用SpringBoot?

  • 为了解决java开发中的,繁多的配置、底下的开发效率,复杂的部署流程,和第三方技术集成难度大的问题,产生了SpringBoot。
  • SpringBoot 使用 “习惯优于配置”的理念让项目快速运行起来,使用SpringBoot很容易创建一个独立运行的jar,内嵌servlet容器
  • SpringBoot的核心功能一:独立运行Spring项目,SpringBoot可以以jar包的形式独立运行,运行一个SpringBoot项目只需要 java -jar xxx.jar 来运行
  • SpringBoot的核心功能二:内嵌servlet容器,可以内嵌tomcat,接天jetty,或者undertow,这样我们就可以不用war包形式部署项目
  • SpringBoot的核心功能三,提供starter简化maven配置,spring提供了一系列starter pom 来简化maven的依赖加载, 当使用了 spring-boot-starter-web时,会自动加载所需要的依赖包
  • SpringBoot的核心功能四:自动配置spring,springboot 会根据在类路径的jar包,类,为jar包中的类自动配置bean,这样会极大的减少使用的配置,会根据启动类所在的目录,自动配置bean

4.Starter 组件

Starter 是一组惯例依赖描述资源,可以包含在应用中。从 starter 中,您可以获得所需的所有 Spring 和相关技术的一站式支持,无须通过示例代码和复制粘贴来获取依赖。比如,如果您要使用 Spring 和 JPA 进行数据库访问,那么只需要在项目中包含 spring-boot-starter-data-jpa 依赖项即可。

starter 包含了许多您需要用于使项目快速启动和运行,并且需要一组受支持的可传递依赖关系的依赖。

官方的所有 starter 都遵循类似的命名规则:spring-boot-starter-*,其中 * 是特定类型的应用。这个命名结构旨在帮助您找到 starter。许多 IDE 中 Maven 集成允许您按名称搜索依赖。例如,安装了 Eclipse 或者 STS 插件后,您可以简单地在 POM 编辑器中按下 ctrl-space 并输入 spring-boot-starter 来获取完整的列表。

正如创建自己的 starter 章节所述,第三方的 starter 命名不应该以 spring-boot 开头,因为它是官方 Spring Boot 构件所保留的规则。例如,有一个第三方 starter 项目叫做 thirdpartyproject,它通常会命名为 thirdpartyproject-spring-boot-starter。

Spring Boot 在 org.springframework.boot group 下提供了以下应用 starter:

名称 描述 POM
spring-boot-starter 核心 starter,包含自动配置支持、日志和 YAML Pom
spring-boot-starter-activemq 提供 JMS 消息支持,使用 Apache ActiveMQ Pom
spring-boot-starter-amqp 提供 Spring AMQP 与 Rabbit MQ 支持 Pom
spring-boot-starter-aop 提供 Spring AOP 与 AspectJ 面向切面编程支持 Pom
spring-boot-starter-artemis 提供 JMS 消息服务支持,使用 Apache Artemis Pom
spring-boot-starter-batch 提供 Spring Batch 支持 Pom
spring-boot-starter-cache 提供 Spring Framework 缓存支持 Pom
spring-boot-starter-cloud-connectors 使用 Spring Cloud Connectors 简单连接到类似 Cloud Foundry 和 Heroku 等云平台 Pom
spring-boot-starter-data-cassandra 提供对 Cassandra 分布式数据库和 Spring Data Cassandra 的支持 Pom
spring-boot-starter-data-cassandra-reactive 提供对 Cassandra 分布式数据库和 Spring Data Cassandra Reactive 的支持 Pom
spring-boot-starter-data-couchbase 提供对 Couchbase 面向文档数据库和 Spring Data Couchbase 的支持 Pom
spring-boot-starter-data-couchbase-reactive 提供对 Couchbase 面向文档数据库和 Spring Data Couchbase Reactive 的支持 Pom
spring-boot-starter-data-elasticsearch 提供对 Elasticseach 搜索与分析引擎和 Spring Data Elasticsearch 的支持 Pom
spring-boot-starter-data-jpa 提供 Spring Data JPA 与 Hibernate 的支持 Pom
spring-boot-starter-data-ldap 提供对 Spring Data LDAP 的支持 Pom
spring-boot-starter-data-mongodb 提供对 MongoDB 面向文档数据库和 Spring Data MongoDB 的支持 Pom
spring-boot-starter-data-mongodb-reactive 提供对 MongoDB 面向文档数据库和 Spring Data MongoDB Reactive 的支持 Pom
spring-boot-starter-data-neo4j 提供对 Neo4j 图数据库与 SPring Data Neo4j 的支持 Pom
spring-boot-starter-data-redis 提供对 Redis 键值数据存储、Spring Data Redis 和 Lettuce 客户端的支持 Pom
spring-boot-starter-data-redis-reactive 提供对 Redis 键值数据存储、Spring Data Redis Reactive 和 Lettuce 客户端的支持 Pom
spring-boot-starter-data-rest 提供使用 Spring Data REST 通过 REST 暴露 Spring Data 资源库的支持 Pom
spring-boot-starter-data-solr 提供对 Apache Solr 搜索平台与 Spring Data Solr 的支持 Pom
spring-boot-starter-freemarker 提供使用 Freemakrer 视图构建 MVC web 应用的支持 Pom
spring-boot-starter-groovy-templates 提供使用 Groovy 模板视图构建 MVC web 应用的支持 Pom
spring-boot-starter-hateoas 提供使用 Spring MVC 与Spring HATEOAS 构建基于超媒体的 RESTful web 应用的支持 Pom
spring-boot-starter-integration 提供对 Spring Integration 的支持 Pom
spring-boot-starter-jdbc 提供 JDBC 与 Tomcat JDBC 连接池的支持 Pom
spring-boot-starter-jersey 提供对使用 JAX-RS 与 Jersey 构建 RESTful web 应用的支持。spring-boot-starter-web 的替代方案 Pom
spring-boot-starter-jooq 提供对使用 JOOQ 访问 SQL 数据库的支持。spring-boot-starter-data-jpaspring-boot-starter-jdbc 的替代方案 Pom
spring-boot-starter-json 提供了读写 json 的支持 Pom
spring-boot-starter-jta-atomikos 提供 Atomikos JTA 事务支持 Pom
spring-boot-starter-jta-bitronix 提供 Bitronix JTA 事务支持 Pom
spring-boot-starter-jta-narayana 提供 Narayana JTA 支持 Pom
spring-boot-starter-mail 提供使用 Java Mail 与 Spring Framework 的邮件发送支持 Pom
spring-boot-starter-mustache 提供使用 Mustache 视图构建 web 应用的支持 Pom
spring-boot-starter-quartz Quartz 支持 Pom
spring-boot-starter-security Spring Security 支持 Pom
spring-boot-starter-test 提供包含了 JUnit、Hamcrest 与 Mockito 类库的 Spring Boot 单元测试支持 Pom
spring-boot-starter-thymeleaf 提供使用 Thymeleaf 视图构建 MVC web 应用的支持 pom
spring-boot-starter-validation 提供 Hibernate Validator 与 Java Bean Validation 的支持 Pom
spring-boot-starter-web 提供使用 Spring MVC 构建 web(包含 RESTful)应用的支持,使用 Tomcat 作为默认嵌入式容器 Pom
spring-boot-starter-web-services Spring Web Services 支持 Pom
spring-boot-starter-webflux 提供使用 Spring Framework 的 Reactive Web 支持构建 WebFlux 应用的支持 Pom
spring-boot-starter-websocket 提供使用 Spring Framework 的 WebSocket 支持构建 WebSocket 应用的支持 Pom

5.@SpringBootApplication 注解

@SpringBootApplication 注解用标注启动类,被标注的类为一个配置类,并会触发自动配置和 Starter 组件扫描。根据源码可得,该注解配置了 @SpringBootConfiguration、 @EnableAutoConfiguration 和 @ComponentScan 三个注解, @SpringBootConfiguration 注解又配置了 @EnableAutoConfiguration 。所以该注解的职责相当于结合了@Configuration, @EnableAutoConfiguration 和 @ComponentScan 三个注解功能。

@SpringBootApplication 注解的职责如下:

  • 在被该注解修饰的类中,可以用 @Bean 注解来配置多个 Bean 。应用启动时,Spring 容器会加载 Bean 并注入到 Spring 容器。
  • 启动 Spring 上下文的自动配置。基于依赖和定义的 Bean 会自动配置需要的 Bean 和类。
  • 扫描被 @Configuration 修饰的配置类。也会扫描 Starter 组件的配置类,并启动加载其默认配置。

6.SpringApplication 类

大多数情况下,在 main 方法中调用 SpringApplication 类的静态方法 run(Class, String[]) ,用来引导启动 Spring 应用程序。默认情况下,该类的职责会执行如下步骤:

  • 创建应用上下文 ApplicationContext 实例
  • 注册 CommandLinePropertySource,将命令行参数赋值到 Spring 属性
  • 刷新应用上下文,加载所有单例
  • 触发所有 CommandLineRunner Bean

在实际开发中如果需要自定义创建高级的配置,可以通过 run(Class, String[]) 方法的第二个参数,并以 String 数组的形式传入。这是 run 几个重载方法的 API 文档:

API org.springframework.boot.SpringApplication

  • static run(Class<?>[] primarySources, String[] args)
    返回正在运行的应用上下文 ApplicationContext

    参数:
    primarySources 应用指定的主要类源,数组形式
    args 应用参数

  • static run(Class<?> primarySource, String… args)
    返回正在运行的应用上下文 ApplicationContext

    参数:
    primarySource 应用指定的主要类源
    args 应用参数

  • run(String… args)
    返回正在运行的应用上下文 ApplicationContext

    参数:
    args 应用参数

7.JavaConfig

Spring JavaConfig 是 Spring 社区的产品,它提供了配置 Spring IoC 容器的纯Java 方法。因此它有助于避免使用 XML 配置。使用 JavaConfig 的优点在于:

(1)面向对象的配置。由于配置被定义为 JavaConfig 中的类,因此用户可以充分利用 Java 中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean 方法等。

(2)减少或消除 XML 配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在 XML 和 Java 之间来回切换。JavaConfig 为开发人员提供了一种纯 Java 方法来配置与 XML 配置概念相似的 Spring 容器。从技术角度来讲,只使用 JavaConfig 配置类来配置容器是可行的,但实际上很多人认为将JavaConfig 与 XML 混合匹配是理想的。

(3)类型安全和重构友好。JavaConfig 提供了一种类型安全的方法来配置 Spring容器。由于 Java 5.0 对泛型的支持,现在可以按类型而不是按名称检索 bean,不需要任何强制转换或基于字符串的查找。

8.Spring Boot 自动配置原理

注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,

@EnableAutoConfiguration 给容器导入META-INF/spring.factories 里定义的自动配置类。

筛选有效的自动配置类。

每一个自动配置类结合对应的 xxxProperties.java 读取配置文件进行自动配置功能

9.Spring Boot 配置加载顺序

使用 Spring Boot 会涉及到各种各样的配置,如开发、测试、线上就至少 3 套配置信息了。Spring Boot 可以轻松的帮助我们使用相同的代码就能使开发、测试、线上环境使用不同的配置。

在 Spring Boot 里面,可以使用以下几种方式来加载配置。本章内容基于 Spring Boot 2.0 进行详解。

1、properties文件;

2、YAML文件;

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 指定);

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

(1)在主应用程序中添加 Java 系统参数。

@Bean
public CommandLineRunner commandLineRunner() {
    return (args) -> {
        System.setProperty("name", "javastack-system-properties");
    };
}

(2)在 application.properties 文件中添加属性。

name = javastack-application

(3)在 application-dev.properties 文件中添加属性。

name = javastack-application-dev

(4)添加测试类

@RunWith(SpringRunner.class)
@SpringBootTest(value = { "name=javastack-test", "sex=1" })
@ActiveProfiles("dev")
public class SpringBootBestPracticeApplicationTests {

    @Value("${name}")
    private String name;

    @Test
    public void test() {
        System.out.println("name is " + name);
    }

}

运行 test 单元测试,程序输出:

name is javastack-test

根据以上参数动态调整,发现参数会被正确被覆盖。了解了 Spring Boot 各种配置的加载顺序,如果配置被覆盖了我们就知道是什么问题了。

10.什么是 YAML?

YAML 是一种人类可读的数据序列化语言。它通常用于配置文件。与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML 文件就更加结构化,而且更少混淆。可以看出 YAML 具有分层配置数据。

11.YAML 配置的优势

YAML 现在可以算是非常流行的一种配置文件格式了,无论是前端还是后端,都可以见到 YAML 配置。那么 YAML 配置和传统的 properties 配置相比到底有哪些优势呢?

  • 配置有序,在一些特殊的场景下,配置有序很关键
  • 支持数组,数组中的元素可以是基本数据类型也可以是对象
  • 简洁

相比 properties 配置文件,YAML 还有一个缺点,就是不支持 @PropertySource 注解导入自定义的 YAML 配置。

12.Spring Boot 是否可以使用 XML 配置 ?

Spring Boot 推荐使用 Java 配置而非 XML 配置,如果您一定要使用基于 XML 的配置,可以使用 @ImportResource 注解来加载 XML 配置文件。

13.bootstrap & application

用过 Spring Boot 的都知道在 Spring Boot 中有以下两种配置文件
bootstrap (.yml 或者 .properties)
application (.yml 或者 .properties)

为什么会有这两种配置文件呢?大家都清楚它们的区别和具体使用场景吗?

bootstrap/ application 的区别:Spring Cloud 构建于 Spring Boot 之上,在 Spring Boot 中有两种上下文,一种是 bootstrap, 另外一种是 application, bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。

因此,对比 application 配置文件,bootstrap 配置文件具有以下几个特性。

  • boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载
  • boostrap 里面的属性不能被覆盖

bootstrap/ application 的应用场景:application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。

bootstrap 配置文件有以下几个应用场景:

  • 使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;
  • 一些固定的不能被覆盖的属性
  • 一些加密/解密的场景;

14.Profile 多环境配置

当应用程序需要部署到不同运行环境时,一些配置细节通常会有所不同,最简单的比如日志,生产日志会将日志级别设置为WARN或更高级别,并将日志写入日志文件,而开发的时候需要日志级别为DEBUG,日志输出到控制台即可。

如果按照以前的做法,就是每次发布的时候替换掉配置文件,这样太麻烦了,Spring Boot的Profile就给我们提供了解决方案,命令带上参数就搞定。

这里我们来模拟一下,只是简单的修改端口来测试

在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识,比如:

  • application-dev.properties:开发环境
  • application-prod.properties:生产环境

想要使用对应的环境,只需要在application.properties中使用spring.profiles.active属性来设置,值对应上面提到的{profile},这里就是指dev、prod这2个。

当然你也可以用命令行启动的时候带上参数:

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

我给不同的环境添加不同的端口属性server.port,然后根据指定不同的spring.profiles.active来切换使用。各位可以自己试试。这里就不贴代码了。

除了可以用profile的配置文件来分区配置我们的环境变量,在代码里,我们还可以直接用@Profile注解来进行配置,例如数据库配置,这里我们先定义一个接口

public  interface DBConnector { public  void  configure(); }

分别定义俩个实现类来实现它

/**
  * 测试数据库
  */
@Component
@Profile("testdb")
public class TestDBConnector implements DBConnector {
    @Override
    public void configure() {
        System.out.println("testdb");
    }
}
/**
 * 生产数据库
 */
@Component
@Profile("devdb")
public class DevDBConnector implements DBConnector {
    @Override
    public void configure() {
        System.out.println("devdb");
    }
}

通过在配置文件激活具体使用哪个实现类

spring.profiles.active=testdb

然后就可以这么用了

@RestController
@RequestMapping("/task")
public class TaskController {

    @Autowired DBConnector connector ;

    @RequestMapping(value = {"/",""})
    public String hellTask(){

        connector.configure(); //最终打印testdb     
        return "hello task !! myage is " + myage;
    }
}

除了spring.profiles.active来激活一个或者多个profile之外,还可以用spring.profiles.include来叠加profile

spring.profiles.active: testdb  
spring.profiles.include: proddb,prodmq

15.如何实现 Spring Boot 应用程序的安全性?

默认情况下,如果 Spring Security 在 classpath 上,则 Web 应用程序是受保护的。Spring Boot 依赖 Spring Security 的内容协商策略来确定是使用 httpBasic 还是 formLogin。要给 Web 应用程序添加方法级别的安全保护,可以使用 @EnableGlobalMethodSecurity 注解设置。有关更多其他信息,您可以在Spring Security 参考指南中找到。

默认的 UserDetailsS​​ervice 只有一个用户。用户名为 user,密码是随机的,在应用程序启动时会以 INFO 级别打印出来,如下所示:

Using generated security password: 0ce03db6-5884-b28a-655b-53849950aedd

如果您对日志配置进行微调,请确保将 org.springframework.boot.autoconfigure.security 的级别设置为 INFO。否则,默认密码不会打印出来。

您可以通过提供 spring.security.user.name 和 spring.security.user.password 来更改用户名和密码。

您在 Web 应用程序中默认会获得以下基本功能:

  • 一个 UserDetailsS​​ervice(或 WebFlux 应用程序中的 ReactiveUserDetailsS​​ervice)bean,采用内存存储形式,有一个自动生成密码的用户(有关用户属性,请参阅 SecurityProperties.User)。
  • 用于整个应用程序(如果 actuator 在 classpath 上,则包括 actuator 端点)基于表单登录或 HTTP Basic 认证(取决于 Content-Type)。
  • 一个用于发布身份验证事件的 DefaultAuthenticationEventPublisher。

您可以通过为其添加一个 bean 来提供不同的 AuthenticationEventPublisher。

16.Spring Boot 中如何解决跨域问题 ?

跨域资源共享(Cross-origin resource sharing,CORS)是大多数浏览器实现的一个 W3C 规范,其可允许您以灵活的方式指定何种跨域请求可以被授权,而不是使用一些不太安全和不太强大的方式(比如 IFRAME 或者 JSONP)。

Spring MVC 从 4.2 版本起开始支持 CORS。您可在 Spring Boot 应用程序中使用 @CrossOrigin 注解配置控制器方法启用 CORS。

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @DeleteMapping("/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

默认情况下,@CrossOrigin允许:

  • 所有origins
  • 所有headers

还可以通过注册一个 WebMvcConfigurer bean 并自定义 addCorsMappings(CorsRegistry) 方法来定义全局 CORS 配置:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/api/**")
            .allowedOrigins("http://domain2.com")
            .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3")
            .exposedHeaders("header1", "header2")
            .allowCredentials(true).maxAge(3600);

        // Add more mappings...
    }
}

17.前后端分离,如何维护Rest API接口文档 ?

前后端分离开发日益流行,大部分情况下,我们都是通过 Spring Boot 做前后端分离开发,前后端分离一定会有接口文档,不然会前后端会深深陷入到扯皮中。一个比较笨的方法就是使用 word 或者 md 来维护接口文档,但是效率太低,接口一变,所有人手上的文档都得变。在 Spring Boot 中,这个问题常见的解决方案是 Swagger ,使用 Swagger 我们可以快速生成一个接口文档网站,接口一旦发生变化,文档就会自动更新,所有开发工程师访问这一个在线网站就可以获取到最新的接口文档,非常方便。

18.什么是 CSRF 攻击?

CSRF 代表跨站请求伪造。这是一种攻击,迫使最终用户在当前通过身份验证的Web 应用程序上执行不需要的操作。CSRF 攻击专门针对状态改变请求,而不是数据窃取,因为攻击者无法查看对伪造请求的响应。

由于 Spring Boot 依赖 Spring Security 的默认值配置,因此默认情况下会启用 CSRF 保护。这意味着当使用默认安全配置时,需要 POST(shutdown 和 loggers 端点)、PUT 或 DELETE 的 actuator 端点将返回 403 禁止访问错误。

我们建议仅在创建非浏览器客户端使用的服务时才完全禁用 CSRF 保护。

有关 CSRF 保护的其他信息,请参阅Spring Security 参考指南

19.Spring Boot 中的监视器是什么?

Spring boot actuator 是 spring 启动框架中的重要功能之一。Spring boot 监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为 HTTP URL 访问的REST 端点来检查状态。

20.Actuator 安全

出于安全考虑,默认情况下禁用除 /health 和 /info 之外的所有 actuator。可用 management.endpoints.web.exposure.include 属性启用 actuator。

如果 Spring Security 位于 classpath 上且没有其他 WebSecurityConfigurerAdapter,则除了 /health 和 /info 之外的所有 actuator 都由 Spring Boot 自动配置保护。如果您定义了自定义 WebSecurityConfigurerAdapter,则 Spring Boot 自动配置将不再生效,您可以完全控制 actuator 的访问规则。

在设置 management.endpoints.web.exposure.include 之前,请确保暴露的 actuator 没有包含敏感信息和 / 或被防火墙保护亦或受 Spring Security 之类的保护。

20.我们如何监视所有 Spring Boot 微服务?

Spring Boot 提供监视器端点以监控各个微服务的度量。这些端点对于获取有关应用程序的信息(如它们是否已启动)以及它们的组件(如数据库等)是否正常运行很有帮助。但是,使用监视器的一个主要缺点或困难是,我们必须单独打开应用程序的知识点以了解其状态或健康状况。想象一下涉及 50 个应用程序的微服务,管理员将不得不击中所有 50 个应用程序的执行终端。为了帮助我们处理这种情况,我们将使用位于的开源项目。 它建立在 Spring Boot Actuator 之上,它提供了一个 Web UI,使我们能够可视化多个应用程序的度量。

21.什么是 WebSockets?

WebSocket 是一种计算机通信协议,通过单个 TCP 连接提供全双工通信信道。

  • WebSocket 是双向的 -使用 WebSocket 客户端或服务器可以发起消息发送。
  • WebSocket 是全双工的 -客户端和服务器通信是相互独立的。
  • 单个 TCP 连接 -初始连接使用 HTTP,然后将此连接升级到基于套接字的连接。然后这个单一连接用于所有未来的通信
  • Light -与 http 相比,WebSocket 消息数据交换要轻得多。

22.什么是 Spring Data ?

Spring Data 是 Spring 的一个子项目。用于简化数据库访问,支持NoSQL 和 关系数据存储。其主要目标是使数据库的访问变得方便快捷。Spring Data 具有如下特点:

SpringData 项目支持 NoSQL 存储:

  • MongoDB (文档数据库)
  • Neo4j(图形数据库)
  • Redis(键/值存储)
  • Hbase(列族数据库)

SpringData 项目所支持的关系数据存储技术:

  • JDBC
  • JPA

Spring Data Jpa 致力于减少数据访问层 (DAO) 的开发量. 开发者唯一要做的,就是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成!Spring Data JPA 通过规范方法的名字,根据符合规范的名字来确定方法需要实现什么样的逻辑。

23.什么是 Spring Batch?

Spring Batch 作为 Spring 的子项目,是一款基于 Spring 的企业批处理框架。通过它可以构建出健壮的企业批处理应用。Spring Batch 不仅提供了统一的读写接口、丰富的任务处理方式、灵活的事务管理及并发处理,同时还支持日志、监控、任务重启与跳过等特性,大大简化了批处理应用开发,将开发人员从复杂的任务配置管理过程中解放出来,使他们可以更多地去关注核心的业务处理过程。

24.模板引擎

除了 REST web 服务之外,您还可以使用 Spring MVC 来服务动态 HTML 内容。Spring MVC 支持多种模板技术,包括 Thymeleaf、FreeMarker 和 JSP。当然,许多其他模板引擎也有自己的 Spring MVC 集成。

Spring Boot 包含了以下的模板引擎的自动配置支持:

  • FreeMarker
  • Groovy
  • Thymeleaf
  • Mustache

如果可以,请尽量避免使用 JSP,当使用了内嵌 servlet 容器,会有几个已知限制。

当运行使用了内嵌 servlet 容器的 Spring Boot 应用程序时(打包为可执行归档文件),JSP 支持将存在一些限制。

  • 如果您使用 war 打包,在 Jetty 和 Tomcat 中可以正常工作,使用 java -jar 启动时,可执行的 war 可正常使用,并且还可以部署到任何标准容器。使用可执行 jar 时不支持 JSP。
  • Undertow 不支持 JSP。
  • 创建自定义的 error.jsp 页面不会覆盖默认错误处理视图,应该使用自定义错误页面来代替。

当您使用这些模板引擎的其中一个并附带了默认配置时,您的模板将从 src/main/resources/templates 自动获取。

IntelliJ IDEA 根据您运行应用程序的方式来对 classpath 进行不同的排序。在 IDE 中通过 main 方法来运行应用程序将导致与使用 Maven 或 Gradle 或来以 jar 包方式引用程序的排序有所不同,可能会导致 Spring Boot 找不到 classpath 中的模板。如果您碰到到此问题,可以重新排序 IDE 的 classpath 来放置模块的 classes 和 resources 到首位。或者,您可以配置模板前缀来搜索 classpath 中的每一个 templates 目录,比如:classpath*:/templates/。

25.ActiveMQ 支持

当 ActiveMQ 在 classpath 上可用时,Spring Boot 也可以配置一个 ConnectionFactory。如果 broker 存在,则会自动启动并配置一个内嵌式 broker(前提是未通过配置指定 broder URL)。

如果使用 spring-boot-starter-activemq,则提供了连接到 ActiveMQ 实例必须依赖或内嵌一个 ActiveMQ 实例,以及与 JMS 集成的 Spring 基础设施。

ActiveMQ 配置由 spring.activemq.* 中的外部配置属性控制。例如,您可以在 application.properties 中声明以下部分:

spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret

默认情况下,CachingConnectionFactory 将原生的 ConnectionFactory 使用可由 spring.jms.* 中的外部配置属性控制的合理设置包装起来:

spring.jms.cache.session-cache-size=5

如果您更愿意使用原生池,则可以通过向 org.messaginghub:pooled-jms 添加一个依赖并相应地配置 JmsPoolConnectionFactory 来实现,如下所示:

spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50

有关更多支持的选项,请参阅 ActiveMQProperties。您还可以注册多个实现了 ActiveMQConnectionFactoryCustomizer 的的 bean,以进行更高级的自定义。

默认情况下,ActiveMQ 会创建一个 destination(目标)(如果它尚不存在),以便根据提供的名称解析 destination。

26.Kafka 支持

通过提供 spring-kafka 项目的自动配置来支持 Apache Kafka。

Kafka 配置由 spring.kafka.* 中的外部配置属性控制。例如,您可以在 application.properties 中声明以下部分:

spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup

要在启动时创建主题(topic),请添加 NewTopic 类型的 Bean。如果主题已存在,则忽略该 bean。

有关更多支持的选项,请参阅 KafkaProperties

27.Spring Boot项目如何热部署?

这可以使用 DEV 工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat 将重新启动。Spring Boot 有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java 开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。开发人员可以重新加载 Spring Boot 上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot 在发布它的第一个版本时没有这个功能。这是开发人员最需要的功能。DevTools 模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供 H2 数据库控制台以更好地测试应用程序。

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

28.Maven

Maven 用户可以继承 spring-boot-starter-parent 项目以获取合适的默认值,父项目提供了以下功能:

  • Java 1.8 作为默认编译器级别。
  • 源代码使用 UTF-8 编码。
  • 依赖管理部分继承自 spring-boot-dependencies 的 POM,允许您省略常见依赖的 标签。
    合理的资源过滤。
  • 合适的插件配置(exec plugin、Git commit ID、shade)。
  • 针对 application.properties 和 application.yml 资源的合理过滤,包括特定 profile 的文件(例如 application-foo.properties 和 application-foo.yml)

由于 application.properties 和 application.yml 文件接受 Spring 风格的占位符(${​…}),因此 Maven 过滤改为使用 @…@ 占位符(您可以使用 Maven 的 resource.delimiter 属性重写它)

继承 Starter Parent

要将项目配置继承 spring-boot-starter-parent,只需要按以下方式设置 parent:

<!-- 从 Spring Boot 继承默认配置 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
</parent>

您只需要在此依赖上指定 Spring Boot 的版本号。如果您要导入其它 starter,则可以放心地省略版本号。

通过该设置,您还可以重写自己项目中的配置属性来覆盖个别依赖。例如,要升级到另一个 Spring Data 发行版本,您需要将以下内容添加到 pom.xml 文件中。

<properties>
    <spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>

不使用父 POM

不是每个人都喜欢从 spring-boot-starter-parent 继承 POM。您可能需要使用自己公司标准的父 POM,或者您可能只是希望明确地声明所有 Maven 配置。

如果您不想使用 spring-boot-starter-parent,则仍然可以通过使用 scope=import 依赖来获得依赖管理(但不是插件管理)的好处:

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- 从 Spring Boot 导入依赖管理 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

如上所述,上述示例设置不会让您使用属性来覆盖个别依赖。要达到相同的目的,需要在 spring-boot-dependencies 项之前在项目的 dependencyManagement 中添加一项。例如,要升级到另一个 Spring Data 发行版,您可以将以下元素添加到 pom.xml中:

<dependencyManagement>
    <dependencies>
        <!-- 覆盖 Spring Boot 提供的 Spring Data -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-releasetrain</artifactId>
            <version>Fowler-SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

以上示例中,我们指定了一个 BOM,但是任何的依赖类型都可以用这个方法来重写。

使用 Spring Boot Maven 插件

Spring Boot 包括了一个 Maven 插件,它可以将项目打包成一个可执行 jar。如果要使用它,请将插件添加到您的 中:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

如果您使用了 Spring Boot starter 的父 pom,则只需要添加插件。除非您要修改父级中定义的设置,否则不需要进行配置。

29.Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?

Spring Boot 项目最终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过 java -jar xxx.jar 命令来运行,这种 jar 不可以作为普通的 jar 被其他项目依赖,即使依赖了也无法使用其中的类。

Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes 目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将 Spring Boot 项目打包成两个 jar ,一个可执行,一个可引用。

30.运行 Spring Boot 有哪几种方式?

  • 打包用命令或者放到容器中运行

  • 用 Maven/ Gradle 插件运行

  • 直接执行 main 方法运行

31.Spring Boot 需要独立的容器运行吗?

可以不需要,Spring Boot 包含了对内嵌 Tomcat、Jetty 和 Undertow 服务器的支持。大部分开发人员只需简单地使用对应的 Starter 来获取完整的配置实例。默认情况下,内嵌服务器将监听 8080 上的 HTTP 请求。

如果您选择在 CentOS 使用 Tomcat,请注意,默认情况下,临时目录用于储存编译后的 JSP、上传的文件等。当您的应用程序运行时发生了故障,该目录可能会被 tmpwatch 删除。为了避免出现该情况,您可能需要自定义 tmpwatch 配置,使 tomcat.*目录不被删除,或者配置 server.tomcat.basedir 让 Tomcat 使用其他位置。

32.开启 Spring Boot 特性有哪几种方式?

1)继承spring-boot-starter-parent项目

2)导入spring-boot-dependencies项目依赖

33.如何使用 Spring Boot 实现异常处理?

默认情况下,Spring Boot 提供了一个使用了比较合理的方式来处理所有错误的 /error 映射,其在 servlet 容器中注册了一个全局错误页面。对于机器客户端而言,它将产生一个包含错误、HTTP 状态和异常消息的 JSON 响应。对于浏览器客户端而言,将以 HTML 格式呈现相同数据的 whitelabel 错误视图(可添加一个解析到 error 的 View 进行自定义)。要完全替换默认行为,您可以实现 ErrorController 并注册该类型的 bean,或者简单地添加一个类型为 ErrorAttributes 的 bean 来替换内容,但继续使用现用机制。

BasicErrorController 可以作为自定义 ErrorController 的基类,这非常有用,尤其是在您想添加一个新的内容类型(默认专门处理 text/html,并为其他内容提供后备)处理器的情况下。要做到这点,您只需要继承 BasicErrorController 并添加一个带有 produces 属性的 @RequestMapping 注解的公共方法,之后创建一个新类型的 bean。

您还可以定义一个带有 @ControllerAdvice 注解的类来自定义为特定控制器或异常类型返回的 JSON 文档:

@ControllerAdvice(basePackageClasses = AcmeController.class)
public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {

    @ExceptionHandler(YourException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
        HttpStatus status = getStatus(request);
        return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

}

以上示例中,如果同包下定义的控制器 AcmeController 抛出了 YourException,则将使用 CustomerErrorType 类型的 POJO 来代替 ErrorAttributes 做 JSON 呈现。

自定义错误页面

如果您想在自定义的 HTML 错误页面上显示给定的状态码,请将文件添加到 /error 文件夹中。错误页面可以是静态 HTML(添加在任意静态资源文件夹下) 或者使用模板构建。文件的名称应该是确切的状态码或者一个序列掩码。

例如,要将 404 映射到一个静态 HTML 文件,文件夹结构可以如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

使用 FreeMarker 模板来映射所有 5xx 错误,文件夹的结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftl
             +- <other templates>

对于更复杂的映射,您还通过可以添加实现了 ErrorViewResolver 接口的 bean 来处理:

public class MyErrorViewResolver implements ErrorViewResolver {

    @Override
    public ModelAndView resolveErrorView(HttpServletRequest request,
            HttpStatus status, Map<String, Object> model) {
        // Use the request or status to optionally return a ModelAndView
        return ...
    }

}

您还可以使用常规的 Spring MVC 功能,比如 @ExceptionHandler 方法和 @ControllerAdvice。之后,ErrorController 将能接收任何未处理的异常。

映射到 Spring MVC 之外的错误页面

对于不使用 Spring MVC 的应用程序,您可以使用 ErrorPageRegistrar 接口来直接注册 ErrorPages。抽象部分直接与底层的内嵌 servlet 容器一起工作,即使您没有 Spring MVC DispatcherServlet 也能使用。

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
    return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
    }

}

如果您注册了一个 ErrorPage,它的路径最终由一个 Filter(例如,像一些非 Spring web 框架一样,比如 Jersey 和 Wicket)处理,则必须将 Filter 显式注册为一个 ERROR dispatcher,如下示例:

@Bean
public FilterRegistrationBean myFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new MyFilter());
    ...
    registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
    return registration;
}

请注意,默认的 FilterRegistrationBean 不包含 ERROR 调度器(dispatcher)类型。

当部署到 servlet 容器时,Spring Boot 使用其错误页面过滤器会将有错误状态的请求转发到相应的错误页面。如果尚未提交响应,则只能将请求转发到正确的错误页面。默认情况下,WebSphere Application Server 8.0 及更高版本在成功完成 servlet 的 service 方法后提交响应。您应该将 com.ibm.ws.webcontainer.invokeFlushAfterService 设置为 false 来禁用此行为。

34.Spring Boot 中如何实现定时任务 ?

定时任务也是一个常见的需求,Spring Boot 中对于定时任务的支持主要还是来自 Spring 框架。

在 Spring Boot 中使用定时任务主要有两种不同的方式,一个就是使用 Spring 中的 @Scheduled 注解,另一个则是使用第三方框架 Quartz。

使用 Spring 中的 @Scheduled 的方式主要通过 @Scheduled 注解来实现。

使用 Quartz ,则按照 Quartz 的方式,定义 Job 和 Trigger 即可。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐