概述
什么是Spring Boot
Spring Boot是Spring开源组织下的子项目,是Spring组件一站式解决方案,主要是简化了使用Spring的难度,简省了繁重的配置,提供了各种启动器,方便开发者快速上手。
优点
- 容易上手,提升开发效率,为 Spring 开发提供一个更快、更广泛的入门体验。
- 开箱即用,远离繁琐的配置。
- 提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。
- 没有代码生成,也不需要XML配置。
- 避免大量的 Maven 导入和各种版本冲突。
Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是**@SpringBootApplication**,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
- @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
- @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。 - @ComponentScan:Spring组件扫描。
配置
什么是JavaConfig?
Spring JavaConfig是Spring社区的产品,它提供了一种纯Java方法来配置Spring IoC容器。因此,它有助于避免使用XML配置。使用JavaConfig 的优点是:
-
面向对象的配置。由于配置在JavaConfig中定义为类,因此用户可以充分利用Java中面向对象的功能。一个配置类可以子类化另一个,覆盖其@Bean方法等。
-
减少或消除XML配置。已经证明了基于依赖注入原理的外部化配置的好处。但是,许多开发人员不希望在XML和Java之间来回切换。JavaConfig为开发人员提供了一种纯Java方法来配置Spring容器,该容器在概念上类似于XML配置。在技术上可以仅使用JavaConfig配置类来配置容器,但是在实践中,许多人发现将JavaConfig与XML混合匹配是理想的。
-
类型安全和重构友好。JavaConfig提供了一种类型安全的方法来配置Spring容器。由于Java5.0支持泛型,现在可以按类型而不是按名称检索bean,而不需要任何强制转换或基于字符串的查找。
Spring Boot自动配置原理是什么
1、当Spring Boot启动的时候,就从主方法里面进行启动
它主要是加载了@SpringBootApplication
注解主配置类,主配置类里边最主要的功能就是SpringBoot开启了一个@EnableAutoConfiguration
注解实现自动配置功能。
2、@EnableAutoConfiguration主要利用了一个EnableAutoConfigurationImportSelector
选择器给Spring容器中来导入一些组件。
3、导入的组件
通过查看EnableAutoConfigurationImportSelector的父类selectImports
中的selectImports
方法查看具体导入了哪些组件?
在selectImports这个方法里面主要有一个configurations,并且这个configurations最终会被返回。
configurations用来获取候选的配置:
作用就是利用SpringFactoriesLoader.loadFactoryNames
从类路径下得到一些资源。
4、那么得到哪些资源呢?
它是扫描javajar包类路径下的META-INF/spring.factories
这个文件
那么扫描到的这些文件作用是把这个文件的urls拿到之后遍历每一个url,最终把这些文件整成一个properties对象。
然后它从properties对象里边获取一些值,用这些获取到的值来加载我们最终要返回的这个结果,这个结果就是我们要交给Spring容器中的所有组件,这个factoryClassNames就是我们传过来的Class的类名。
而传过来的Class是调用这个getSpringFactoriesLoaderFactoryClass()
这个方法,得到从properties中获取到EnableAutoConfiguration.class类名对应的值,然后把它们添加在容器中。
5、Springjar包的META-INF下的spring.factories这个文件找到配置所有EnableAutoConfiguration的值加入到Spring容器中,每一个xxxAutoConfiguration类都是容器中的一个组件,并都加入到容器中。
加入到容器中之后的作用就是用它们来做自动配置,这就是Springboot自动配置之源,也就是自动配置的开始,只有这些自动配置类进入到容器中以后,接下来这个自动配置类才开始进行启动
6、每一个自动配置类进行自动配置功能
以一个自动配置类HttpEncodingAutoConfiguration(HTTP的编码自动配置)为例来解释SpringBoot的自动配置原理:
1). 这个HttpEncodingAutoConfiguration类上面标注了一大堆的注解:
@Configuration
//表示这是一个配置类,类似于以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties(HttpEncodingProperties.class)
//启用ConfigurationProperties功能:
//这个ConfigurationProperties里面引入了一个类,这个类就是启用指定类的ConfigurationProperties功能
//有了这个@EnableConfigurationPropertie注解以后相当于把配置文件中对应值就和这个HttpEncodingProperties.class类绑定起来了。
@ConditionalOnWebApplication
//判断当前是不是web应用,@Conditional是spring底层,根据不同的条件来进行自己不同的条件判断,如果满足指定的条件,那么整个配置类里边的配置才会生效。
@ConditionalOnClass(CharacterEncodingFilter.class)
//判断当前项目里边有没有CharacterEncodingFilter这个类,
//这个CharacterEncodingFilter类是Springmvc中乱码解决的过滤器。
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
//@ConditionalOnProperty注解是来判断配置文件中是否存在某个配置,就是是否存在
//spring.http.encoding.enabled这个配置,matchIfMissing = true即使配置文件
//中不配置spring.http.encoding.enabled=true这个属性,也是默认生效的
public class HttpEncodingAutoConfiguration {
点进去HttpEncodingProperties这个类,发现这个HttpEncodingProperties类上面标注了@ConfigurationProperties注解
xxx.Properties配置文件中该配置什么,是根据HttpEncodingProperties这个类中定义的属性来定的。
7、这个HttpEncodingProperties类就是根据当前不同的条件判断,决定这个配置类是否生效。
如果一旦生效了,所有的配置类都成功了,就给容器中添加各种组件,这些组件的属性是从对应的properties类中获取的,而这properties类里边的每一个属性又是和配置文件绑定的;
这个HttpEncodingAutoConfiguration只有一个有参构造器,在只有一个有参构造器的情况下,参数的值就会从容器中拿。
8、而容器中它怎么去拿到呢?
相当于是前面的这个@EnableConfigurationProperties(HttpEncodingProperties.class) 注解,这个@EnableConfigurationProperties注解的作用就是把HttpEncodingProperties.class和配置文件进行绑定起来并把HttpEncodingProperties加入到容器中。
接下来这个自动配置类,通过一个有参构造器把这个属性拿到,而这个属性已经和SpringBoot映射了,接下来要用什么编码,就是去HttpEncodingProperties这个类里边获取对应的属性。
用好SpringBoot只要把握这几点:
- SpringBoot启动会加载大量的自动配置类,我们首先要做的就是检查我们需要的功能SpringBoot有没有帮我们写好自动配置类:
- 如果有就再来看这个自动配置类中到底配置了哪些组件,Springboot自动配置类里边只要我们要用的组件有,我们就不需要再来配置了;
- 但是如果说没有我们所需要的组件,那么我们就需要自己来写一个配置类来把我们相应的组件配置起来。
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,而这些属性我们就可以在配置文件指定这些属性的值。
Spring Boot配置加载顺序
SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
1.命令行参数
所有的配置都可以在命令行上进行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
多个配置用空格分开; --配置项=值
2.来自java:comp/env的JNDI属性
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
由jar包外向jar包内进行寻找;
优先加载带profile
6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
再来加载不带profile
8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar
10.@Configuration注解类上的@PropertySource
11.通过SpringApplication.setDefaultProperties指定的默认属性
什么是YAML
YAML 是一种数据序列化语言。它通常用于配置文件。与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML 文件就更加结构化,而且更少混淆。可以看出 YAML 具有分层配置数据。
YAML配置的好处
- 支持注释
- 良好的层级结构
- 格式松散
- 书写方便
相比 properties 配置文件,YAML 还有一个缺点,就是不支持 @PropertySource 注解导入自定义的 YAML 配置。
Spring Boot核心配置文件是什么?说说它们之间的区别?
spring boot 核心配置文件是bootstrap和application
1.加载顺序上的区别
- bootstrap.yml(bootstrap.properties)先加载
- application.yml(application.properties)后加载
- 在 Spring Boot 中有两种上下文,一种是 bootstrap, 另外一种是 application, bootstrap是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。bootstrap主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。bootstrap里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。
2.bootstrap和application 的应用场景。
- bootstrap.yml 和application.yml 都可以用来配置参数。
- bootstrap.yml 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。
- application.yml 可以用来定义应用级别的,主要用于 Spring Boot 项目的自动化配置。
bootstrap 配置文件有以下几个应用场景:
- 使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap
配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息; - 一些固定的不能被覆盖的属性
- 一些加密/解密的场景;
什么是 Spring Profiles?
Spring Profiles允许用户根据配置文件(dev,test,prod等)来注册bean。因此,当应用程序在开发中运行时,只有某些bean可以加载,而在生产环境中,某些其他bean可以加载。假设我们的要求是Swagger文档仅适用于QA环境,并且禁用所有其他文档。这可以使用配置文件来完成。Spring Boot使得使用配置文件非常简单。
安全
如何实现Spring Boot应用程序的安全性
为了实现Spring Boot的安全性,我们使用spring-boot-starter-security依赖项,并且进行相关安全配置,配置类必须扩展WebSecurityConfigurerAdapter,并覆盖其方法。
比较Spring Security和Shiro的优缺点
- Shiro比Spring Security更容易理解、使用;
- Spring Security有更好的社区支持;
- Apache Shiro在处理密码学方面有一个额外的模块;
- Spring Security对Spring结合较好,如果项目中没有用到Spring,建议用Shiro;
- Shiro功能强大,且简单、灵活,不跟任何的框架或者容器绑定,可以独立运行;
Spring Boot 解决跨域问题
跨域可以在前端通过JSONP(JSON with Padding)来解决,但是JSONP只可以发送GET请求,在RESTful风格的应用中显得很鸡肋。
因此推荐在后端通过CORS(Cross-origin resource sharing,跨域资源共享) 来解决跨域问题。
跨域问题产生的根源是浏览器的“同源策略”。
1、同源策略
所谓同源,是指协议、域名以及端口要相同,同源策略是浏览器最核心、最基础的安全功能。
2、CORS解决方案
它是一个W3C标准,是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略。
这种解决方案并非 Spring Boot 特有的,在传统的 SSM 框架中,就可以通过 CORS 来解决跨域问题,只不过之前我们是在 XML 文件中配置 CORS ,现在可以通过实现WebMvcConfigurer接口,然后重写addCorsMappings方法解决跨域问题。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
}
项目中前后端分离部署,所以需要解决跨域的问题。
我们使用cookie存放用户登录的信息,在spring拦截器进行权限控制,当权限不符合时,直接返回给用户固定的json结果。
当用户登录以后,正常使用;当用户退出登录状态时或者token过期时,由于拦截器和跨域的顺序有问题,出现了跨域的现象。
我们知道一个http请求,先走filter,到达servlet后才进行拦截器的处理,如果我们把cors放在filter里,就可以优先于权限拦截器执行。
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
什么是 CSRF 攻击?
CSRF 代表跨站请求伪造。这是一种网络攻击方式,利用网站对于用户网页浏览器的信任,挟持用户当前已登录的web应用程序,去执行并非用户本意的操作。
CSRF攻击实例:
- 用户登录、浏览正规但是具有漏洞的网站webA,webA通过用户的验证,并在用户的浏览器中产生Cookie;
- 攻击者webB通过在webA中添加图片链接等方式诱导用户访问网站webB;
- 在用户被诱导到webB后,webB会利用用户的浏览器访问第三方网站webA,并发出操作请求(用户自身并不知情);
- 用户的浏览器根据webB的要求,带着之前产生的Cookie访问webA;
- 网站webA接收到用户浏览器的请求,webA无法分辨请求由何处发出,由于浏览器访问时带上用户的Cookie,因此webA会响应浏览器的请求,如此一来,攻击网站webB就达到了模拟用户操作的目的。
整合第三方项目
什么是WebSocket
WebSocket是一种在单个TCP连接上进行全双工通讯的网络通信协议,因为HTTP协议的通信只能由客户端发起,在某些特殊的场景下,如:聊天室,假如用HTTP协议,那么只能轮询获取服务端有没有消息,而WebSocket是双向的,客户端和服务端都可以进行消息发送,另外WebSocket是全双工的,客户端和服务端通信相互独立;WebSocket 消息数据交换要比HTTP开销更小,效率更高。
什么是Spring Data
Spring Data是Spring的一个子项目,用于简化数据库访问,支持NoSQL和关系数据存储,其主要目标是使数据库的访问变得方便快捷。
什么是 FreeMarker 模板?
FreeMarker 是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
什么是Apache kafka
Apache Kafka 是一个分布式数据流处理平台,可以实时发布、订阅、存储和处理数据流。它设计为处理多种来源的数据流,并将它们交付到多个消费者。简而言之,它可以移动大量数据,不仅是从 A 点移到 B 点,而是能从 A 到 Z 的多个点移到任何您想要的位置,并且可以同时进行。
Apache Kafka 可以取代传统的企业级消息传递系统。它最初是 Linkedin 为处理每天 1.4 万亿条消息而开发的一个内部系统,现已成为应用于各式各样企业需求的开源数据流处理解决方案。
什么是Swagger
Swagger 广泛用于可视化 API,使用 Swagger UI 为前端开发人员提供在线沙箱。Swagger 是用于生成 RESTful Web 服务的可视化表示的工具,规范和完整框架实现。它使文档能够与服务器相同的速度更新。当通过 Swagger 正确定义时,消费者可以使用最少量的实现逻辑来理解远程服务并与其进行交互。因此,Swagger 消除了调用服务时的猜测。
其他
如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?Spring Boot项目如何热部署?
使用DEV工具来实现,Spring Boot有一个开发工具(DevTools)模块,会将文件更改自动部署到服务器,无需重新启动服务器,消除了每次手动部署更改的需要,以此来提高开发人员的生产力。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
Spring Boot中的starter到底是什么
- 首先它提供了一个自动化配置类(xxxAutoConfiguration),在这个配置类中通过条件注解来决定一个配置是否生效;
- 然后提供一系列默认配置,允许开发者根据实际情况自定义相关配置,然后通过类型安全的属性注入将这些配置属性注入进来。
spring-boot-starter-parent 有什么用 ?
- 定义了Java编译版本为1.8
- 使用UTF-8格式编码
- 提供Dependency Management进行项目依赖的版本管理
- 默认的资源过滤和插件管理
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
目录下才是我们的代码,因此无法直接被引用。
微服务分布式session共享解决方案
-
tomcat的session共享
优点:不需要额外开发,只需搭建tomcat集群即可
缺点:tomcat 是全局session复制,集群内每个tomcat的session完全同步(也就是任何时候都完全一样的) 在大规模应用的时候,用户过多,集群内tomcat数量过多,session的全局复制会导致集群性能下降, 因此,tomcat的数量不能太多,而且依赖tomcat容器移植性不好(所以不采用) -
cookie同步session 如JWT(json web token)
这种完全把客户的登陆信息保存在客户端的cookie中,每次请求带着cookie中的Token
优点:由于完全舍弃了session 会减轻服务器端的压力
缺点:是把信息暴露在外,就算有加密算法还是存在安全问题;禁止使用cookie的情况下无效。 -
redis 集中管理session(常用)
优点:redis为内存数据库,读写效率高,并可在集群环境下做高可用
Spring Boot 中如何实现定时任务 ?
定时任务也是一个常见的需求,Spring Boot 中对于定时任务的支持主要还是来自 Spring 框架。
在 Spring Boot 中使用定时任务主要有两种不同的方式,一个就是使用 Spring 中的 @Scheduled 注解,另一个则是使用第三方框架 Quartz。
- 使用 Spring 中的 @Scheduled 的方式主要通过 @Scheduled 注解来实现。
- 使用 Quartz ,则按照 Quartz 的方式,定义 Job 和 Trigger 即可。