常见问题分析
什么是 Spring Boot?
- “Spring Boot是由Pivotal团队提供的全新框架,是一个框架,一种全新的编程规范,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。
Spring Boot 有哪些优点?
- 容易上手,提升开发效率,为 Spring 开发提供一个更快、更广泛的入门体验。
- 开箱即用,远离繁琐的配置。
- 提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。
- 没有代码生成,也不需要XML配置。
- 避免大量的 Maven 导入和各种版本冲突。
SpringBoot中常用的注解有哪些?
- @SpringBootApplication 是启动类上面的注解,也是核心注解。
- @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
- @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项。
- @ComponentScan:Spring组件扫描。
配置SpringBoot相关
什么是 JavaConfig?
Spring JavaConfig是Spring社区的产品,他提供了配置Spring IOC容器的纯Java方法。因此它有助于避免使用XML配置。使用JavaCofig的优点在于:
-
1.面向对象的配置。由于配置被定义为JavaConfig中的类,因此用户可以充分使用Java中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean方法等。
-
2.减少或者消除XML配置。基于依赖注入原则的外化配置的好处已经被证明。但是,许多开发人员不希望在XML和Java之间来回切换。javaconfig为开发人员提供了一种纯Java的方法来配置与XML配置概念相似的Spring容器。从技术角度来说,只使用javaconfig配置类来配置容器是可行的,但是实际开发中,很多场景都是javaconfig和xml配置共用是最方便,理想的。
-
3.类型安全和重构友好。javaconfig提供了一种类型安全的方法了来配置spring容器,由于Java5.0对泛型的支持,现在可以按类型而不是名称检索bean,不需要任何的强制转换或者基于字符串的查找。
Spring Boot 自动配置原理是什么?
- SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration
- @EnableAutoConfiguration利用EnableAutoConfigurationImportSelector给容器中导入一些组件,将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容中,每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置
你如何理解 Spring Boot 配置加载顺序?
在 Spring Boot 里面,可以使用以下几种方式来加载配置
- 1、properties文件;
- 2、YAML文件;
- 3、系统环境变量;
- 4、命令行参数;
什么是 YAML?
YAML是一种人类可读的数据序列化语言。它通常用于配置文件。与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。
YAML 配置的优势在哪里 ?
- 配置有序,在一些特殊的场景下,配置有序很关键
- 支持数组,数组中的元素可以是基本数据类型也可以是对象
- 内容简洁
相比 properties 配置文件,YAML 还有一个缺点,就是不支持 @PropertySource 注解导入自定义的 YAML 配置
Spring Boot 是否可以使用 XML 配置 ?
可以,Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过 @ImportResource 注解可以引入一个 XML 配置。
spring boot 核心配置文件是什么?application.yml和 application.properties 有何区别 ?
spring boot 核心的两个配置文件:
- bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加载的,比 applicaton 优先加载,配置在应用程序上下文的引导阶段生效。一般来说我们在 Spring Cloud Config 或者 Nacos 中会用到它。且 boostrap 里面的属性不能被覆盖;
- application (. yml 或者 . properties): 由ApplicatonContext 加载,用于 spring boot 项目的自动化配置。
如何在自定义端口上运行 Spring Boot 应用程序?
- 为了在自定义端口上运行 Spring Boot 应用程序,您可以在application.properties 中指定端口。
安全相关问题
比较一下 Spring Security 和 Shiro 各自的优缺点 ?
由于 Spring Boot 官方提供了大量的非常方便的开箱即用的 Starter ,包括 Spring Security 的 Starter ,使得在 Spring Boot 中使用 Spring Security 变得更加容易,甚至只需要添加一个依赖就可以保护所有的接口,所以,如果是 Spring Boot 项目,一般选择 Spring Security 。当然这只是一个建议的组合,单纯从技术上来说,无论怎么组合,都是没有问题的。Shiro 和 Spring Security 相比,主要有如下一些特点:
- Spring Security 是一个重量级的安全管理框架;Shiro 则是一个轻量级的安全管理框架
- Spring Security 概念复杂,配置繁琐;Shiro 概念简单、配置简单
- Spring Security 功能强大;Shiro 功能简单
Spring Boot 中如何解决跨域问题 ?
跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,无法发送其他类型的请求,在 RESTful 风格的应用中,就显得非常鸡肋,因此我们推荐在后端通过 (CORS,Cross-origin resource sharing) 来解决跨域问题。这种解决方案并非 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 攻击专门针对状态改变请求,而不是数据窃取,因为攻击者无法查看对伪造请求的响应
SpringBoot问题补充
如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?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>
spring-boot-starter-parent 有什么用 ?
我们都知道,新创建一个 Spring Boot 项目,默认都是有 parent 的,这个 parent 就是 spring-boot-starter-parent ,spring-boot-starter-parent 主要有如下作用:
- 定义了 Java 编译版本为 1.8 。
- 使用 UTF-8 格式编码。
- 继承自 spring-boot-dependencies,这个里边定义了依赖的版本,也正是因为继承了这个依赖,所以我们 在写依赖时才不需要写版本号。
- 执行打包操作的配置。
- 自动化的资源过滤。
- 自动化的插件配置。
- 针对 application.properties 和 application.yml 的资源过滤,包括通过 profile 定义的不同环境的配置文件,例如 application-dev.properties 和 application-dev.yml。
运行 Spring Boot 有哪几种方式?
- 1.打包用命令或者放到容器中运行
- 2.用 Maven/ Gradle 插件运行
- 3.直接执行 main 方法运行
Spring Boot 需要独立的容器运行吗?
不需要,里面内置Tomcat和Jetty 容器
微服务中如何实现 session 共享 ?
在微服务中,一个完整的项目被拆分成多个不相同的独立的服务,各个服务独立部署在不同的服务器上,各自的 session 被从物理空间上隔离开了,但是经常,我们需要在不同微服务之间共享 session ,常见的方案就是 Spring Session + Redis 来实现 session 共享。将所有微服务的 session 统一保存在 Redis 上,当各个微服务对 session 有相关的读写操作时,都去操作 Redis 上的 session 。这样就实现了 session 共享,Spring Session 基于 Spring 中的代理过滤器实现,使得 session 的同步操作对开发人员而言是透明的,非常简便。
Spring Boot 中如何实现定时任务 ?
定时任务也是一个常见的需求,Spring Boot 中对于定时任务的支持主要还是来自 Spring 框架。
在 Spring Boot 中使用定时任务主要有两种不同的方式,
- 一个就是使用 Spring 中的 @Scheduled 注解
- 另一个则是使用第三方框架 Quartz。
使用 Spring 中的 @Scheduled 的方式主要通过 @Scheduled 注解来实现。
使用 Quartz ,则按照 Quartz 的方式,定义 Job 和 Trigger 即可。