SpringBoot 目前最常用的Java技术框架之一, 但是涉及面试题并不一定能想起多少,整理几道个人觉得重要的面试题,用作复习!
1. SpringBoot的约定优于配置
- 首先, 约定优于配置是一种软件设计的范式,它的核心思想是减少软件开发人员对于配置项的维护,从而让开发人员更加聚焦在业务逻辑上。
- Spring Boot 就是约定优于配置这一理念下的产物,它类似于 Spring 框架下的一个脚手架,通过 Spring Boot,我们可以快速开发基于 Spring 生态下的应用程序。
- 基于传统的 Spring 框架开发 web 应用,我们需要做很多和业务开发无关并且只需要做一次的配置,比如
a. 管理 jar 包依赖
b. web.xml 维护
c. Dispatch-Servlet.xml 配置项维护
d. 应用部署到 Web 容器
e. 第三方组件集成到 Spring IOC 容器中的配置项维护
而在 Spring Boot 中,我们不需要再去做这些繁琐的配置,Spring Boot 已经自动帮我们完成了,这就是约定由于配置思想的体现。- Spring Boot 约定由于配置的体现有很多,比如
a. Spring Boot Starter 启动依赖,它能帮我们管理所有 jar 包版本
b. 如果当前应用依赖了 spring mvc 相关的 jar,那么 Spring Boot 会自动内置Tomcat 容器来运行 web 应用,我们不需要再去单独做应用部署。
c. Spring Boot 的自动装配机制的实现中,通过扫描约定路径下的spring.factories 文件来识别配置类,实现 Bean 的自动装配。
d. 默认加载的配置文件 application.properties 等等。
总的来说,约定优于配置是一个比较常见的软件设计思想,它的核心本质都是为了更高效以及更便捷的实现软件系统的开发和维护。
2. SpringBoot的自动配置原理
备注 : SpringBoot最高频面试题,也是框架最核心思想
@SpringBootApplication
public class AppApplication{
public static void main(String[] args){
SpringApplication.run(AppApplication.class,args);
}
}
//
@SpringBootConfiguration // 该注解作用同@Configuration ,声明当前是一个配置类
@ComponentScan // 组件扫描,默认扫描当前引导类所在包及其子包
@EnableAutoConfiguration // 自动化配置的核心注解
//
// 上面 @EnableAutoConfiguration 是自动化配置的核心注解,该注解通过@import注解导入对应的
配置选择器
内部就是读了该项目以及该项目引用的Jar包的 classpath路径下 META-INF/spring.factories文件所配
置的类的全类名.这些配置类所定义的Bean根据条件注解指定的条件决定是否需要将其导入到Spring容器;
// 条件判断 @ConditionalOnClass这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个
配置类的所有 Bean 放入 Spring 容器中使用
自动装配,简单来说就是自动把第三方组件的 Bean 装载到 Spring IOC 器里面,不需要开发人员再去写 Bean 的装配配置。
在 Spring Boot 应用里面,只需要在启动类加上@SpringBootApplication 注解就可以实现自动装配。
@SpringBootApplication 是一个复合注解,真正实现自动装配的注解是@EnableAutoConfiguration。
自动装配的实现主要依靠三个核心关键技术。
- 引入 Starter 启动依赖组件的时候,这个组件里面必须要包含@Configuration 配置类,在这个配置类里面通过@Bean 注解声明需要装配到 IOC 容器的 Bean 对象。
- 这个配置类是放在第三方的 jar 包里面,然后通过 SpringBoot 中的约定优于配置思想,把这个配置类的全路径放在 classpath:/META-INF/spring.factories 文件中。这样 SpringBoot 就可以知道第三方 jar 包里面的配置类的位置,这个步骤主要是用到了 Spring 里面的 SpringFactoriesLoader 来完成的。
- SpringBoot 拿到所第三方 jar 包里面声明的配置类以后,再通过 Spring 提供的ImportSelector 接口,实现对这些配置类的动态加载。
在我看来,SpringBoot 是约定优于配置这一理念下的产物,所以在很多的地方,都会看到这类的思想。它的出现,让开发人员更加聚焦在了业务代码的编写上,而不需要去关心和业务无关的配置。
其实,自动装配的思想,在 SpringFramework3.x 版本里面的@Enable 注解,就有了实现的雏形。@Enable 注解是模块驱动的意思,我们只需要增加某个@Enable 注解,就自动打开某个功能,而不需要针对这个功能去做 Bean 的配置,@Enable 底层也是帮我们去自动完成这个模块相关 Bean 的注入。
:::info
SpringBoot 自动装配主要是基于注解编程 和 约定优于配置的思想来设计的。
自动装配就是由 Spring 自动把其他组件中的 Bean 装载到 IoC 容器中,不需要开发人员再去配置文件中添加大量的配置。我们只需要在 Spring Boot 的启动类上添加@SpringBootApplication 注解,开启自动装配。
这种自动装配的思想,在 Spring 3.x 以后就开始支持,我们只要在类上添加 @Enable注解就可以了,只是没有像 Spring Boot 这样全面地去设计。
因此,Spring 和 Spring Boot 的最大区别就是在于 Spring Boot 的自动装配
自动装配原理
@SpringBootApplication 这个注解是暴露给用户使用的入口,它的底层是由@EnableAutoConfiguration 这个注解来实现的。这样一个自动装配实现,可分为以下三个核心步骤:
第一步:启动依赖组件的时候,组件中必须要包含 @Configuration 的配置类,在这个配置类里面声明为 @Bean 注解,就将方法的返回值或者属性值 注入到 IoC 容器中。
第二步:如果是使用第三方 jar 包,Spring Boot 采用 SPI 机制,只需要在/META-INF/目录下增加 spring.factories 配置文件。然后,Spring Boot 会根据约定规则,自动使用 SpringFactoriesLoader 来加载配置文件中的内容。
第三步:Spring 获取到第三方 jar 中的配置以后,会使用调用 ImportSelector 接口来完成动态加载。
这样的设计的好处在于,大幅减少了臃肿的配置文件,而且各模块之间的依赖实现了深度解耦。比如,我们使用 Spring 创建 Web 程序时需要导入非常多的 Maven 依赖,而Spring Boot 只需要一个 Maven 依赖来创建 Web 程序,并且 Spring Boot 还把我们最常用的依赖都放到了一起,我们只需要 引入 spring-boot-starter-web 这一个依赖就可以完成一个简单的 Web 应用。
以前用 Spring 的时候需要 XML 文件配置开启一些功能,现在 Spring Boot 不用 XML配置了,只需要写一个, 加了@Configuration 注解 或者实 现对应接口的配置类就可以了.
小结
Spring Boot 自动装配是 Spring 的完善和扩展,就是为我们便捷开发,方便测试和部署,提高效率而诞生的框架技术。
:::
2.1 SpringBoot是什么?
答:SpringBoot是一个基于Spring框架的快速开发框架,它提供了构建独立的、生产级别的Spring应用所需
的各种功能和约定,省去了繁琐的配置。SpringBoot主要优点有:
简化了Spring应用的开发,集成了常用的组件和工具;
提供了自包含的HTTP服务器,可以独立运行;
约定大于配置,开发者无需过多关注配置细节,提高了开发效率;
提供了多种开发测试工具和插件,可以使开发过程更顺畅;
可以通过自动配置的方式,快速的构建一个现代化的微服务应用。
2.2 SpringBoot启动器
答:SpringBoot启动器是一个依赖项管理的基础设施,可以让你无需了解所依赖项的具体细节,就能够创建
一个可运行的应用程序。启动器的作用是自动获取和装配运行SpringBoot应用所需的依赖项和配置,比如说,
使用spring-boot-starter-web可以轻松构建一个基于Web的SpringBoot应用程序。因此,启动器
是SpringBoot自动配置功能的基础。
2.3 SpringBoot中使用AOP
在SpringBoot中,使用AOP的方式与Spring框架是相同的。
常见的方法是使用@Aspect注解定义切面,
使用@Before、@After、@AfterReturning、@AfterThrowing等注解定义通知。
2.4 SpringBoot中使用自定义异常处理
答:需要使用@ControllerAdvice注解来定义一个通用的异常处理类。
在该类中使用@ExceptionHandler注解定义针对不同异常的处理。可以选择返回一个自定义的错误视图
或者JSON数据。
2.5 SpringBoot提供哪些方式来管理应用程序配置
答:SpringBoot提供了多种方式来管理应用程序配置,包括:
application.properties 或 application.yml 文件;
环境变量;
Java系统属性;
@ConfigurationProperties注解;
命令行参数。
2.6 SpringBoot中集成MyBatis
答:可以使用spring-boot-starter-mybatis来集成MyBatis。常用注解有:
@Mapper:标记一个MyBatis的Mapper;
@Select: 标记一个查询方法;
@Insert: 标记一个插入方法;
@Update: 标记一个更新方法;
@Delete: 标记一个删除方法。
2.7 SpringBoot中如何处理文件上传
答:处理文件上传可以使用spring-boot-starter-web集成的MultipartResolver。可以直接使
用@RequestParam注解来获取上传的文件,
然后利用SpringBoot的自动配置将上传的文件保存到本地或云存储。
2.8 SpringBoot实现缓存
答:SpringBoot提供了对缓存的支持,可以通过使用spring-boot-starter-cache集成常用的缓存框架,
比如Ehcache、Redis等。通过@Cacheable、@CachePut、@CacheEvict等注解来实现缓存的访问。
2.9 SpringBoot中如何处理跨域请求
答:默认情况下,SpringBoot禁止跨域请求。
如果需要启用跨域请求,可以使用@WebFilter注解可以实现跨域请求的支持。
2.10 SpringBoot实现任务调度
答:SpringBoot集成了一些常用的任务调度框架,比如Quartz和Spring自带的任务调度框架。
可以通过使用@EnableScheduling注解开启任务调度功能,并在需要调度的方法上标记@Scheduled注解。
2.11 什么是SpringBoot自动配置?它有哪些优点
在传统的Spring应用中,我们需要手动配置很多组件和依赖项,这往往会导致配置文件过于复杂,并且很
容易出现配置错误。为了解决这些问题,SpringBoot引入了自动配置机制,让应用程序无需进行复杂的配
置就能够便捷地构建和运行。
自动配置机制是通过一种约定大于配置的方式来工作的,也就是说,SpringBoot提供了一些常见的默认配置
和依赖项,可以根据应用程序上下文来判断是否需要启用它们。例如,如果在SpringBoot项目中使用
了Spring MVC,SpringBoot就会自动为应用程序添加默认的MVC配置,包括静态资源映射、视图解析器等等。
SpringBoot自动配置的优点包括:
1. 简化应用程序的构建和部署,提高开发效率;
2. 避免了繁琐的配置过程,降低了出错的风险;
3. 提高了应用程序的可维护性和可扩展性;
4. 通过自动配置机制来统一约定,方便团队协作开发;
5. 减少了应用程序的启动时间,提高了应用程序的性能表现。
总之,SpringBoot自动配置机制大大简化了应用程序开发的复杂性,让开发者能够更加专注于业务逻辑的
实现,提升了开发效率和程序质量。
2.12 如何在SpringBoot中使用Spring Data JPA进行数据访问
Spring Data JPA是Spring Data中的一个子项目,是对JPA规范的实现。在SpringBoot中使
用Spring Data JPA进行数据访问非常方便,下面是一些基本步骤:
1. 添加依赖
在pom.xml文件中添加以下依赖:
org.springframework.boot spring-boot-starter-data-jpa ```
- 配置数据源和JPA实现
在application.properties文件中配置数据源和JPA实现,例如:
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root1234
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
这里使用了MySQL作为数据源,选择了update模式,表示自动更新数据库模式。
- 创建实体类
使用@Entity注解定义一个实体类,例如:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// getters and setters
}
这个实体类表示一个用户,包含了id、name和email等属性。
- 创建Repository接口
创建一个继承自JpaRepository的接口来定义数据访问操作,例如:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByName(String name);
User findByEmail(String email);
}
这里定义了两个查询方法findByName和findByEmail。
- 使用Repository接口
在业务逻辑中直接注入UserRepository接口,并使用其提供的方法进行数据访问,例如:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUserByName(String name) {
return userRepository.findByName(name);
}
public User getUserByEmail(String email) {
return userRepository.findByEmail(email);
}
public void saveUser(User user) {
userRepository.save(user);
}
}
这里直接使用UserRepository接口提供的方法来实现对数据库的数据访问。
以上就是在SpringBoot中使用Spring Data JPA进行数据访问的基本步骤。使用Spring Data JPA可以使
数据访问变得更加方便和快捷,减少了很多重复的开发工作。
## 如何使用SpringBoot实现异步调用?
SpringBoot提供了多种异步调用的方式,包括使用线程池、使用消息队列等。下面是使用线程池实现异步
调用的方法。
- 添加依赖
在pom.xml文件中添加以下依赖项:
<!-- 异步调用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-async</artifactId>
</dependency>
- 配置异步线程池
在配置类中使用@Async注解开启异步调用支持,并配置异步线程池。
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(10);
// 设置最大线程数
executor.setMaxPoolSize(20);
// 设置队列容量
executor.setQueueCapacity(2000);
// 设置线程池活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置线程名字前缀
executor.setThreadNamePrefix("async-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
这里通过@Bean注解创建一个名为taskExecutor的线程池,设置了核心线程数、最大线程数、队列容量、
线程池活跃时间、线程名字前缀和拒绝策略等参数。
- 使用@Async注解
在需要异步执行的方法上使用@Async注解,并指定线程池名称。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Async("taskExecutor")
public void saveUser(User user) {
userRepository.save(user);
}
}
这里使用@Async注解指定了使用刚才配置的线程池来异步执行saveUser方法。
异步调用可以大大提升应用程序的并发能力和性能,避免了阻塞调用降低了应用程序的响应速度。同时需要
注意,异步调用可能会导致一些并发性问题,需要在逻辑处理上谨慎考虑。
## SpringBoot中如何使用RabbitMQ进行消息处理?
在SpringBoot中使用RabbitMQ进行消息处理有以下几个步骤:
- 添加依赖
在pom.xml文件中添加以下依赖项:
<!-- 消息队列 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 配置连接
在application.properties文件中配置RabbitMQ连接信息:
# rabbitmq连接信息
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
注意,这里的端口、用户名和密码等信息需要根据自己的实际情况修改。
- 创建消息队列
通过使用@Bean注解创建一个Queue对象:
@Bean
public Queue helloQueue() {
return new Queue("hello");
}
这里创建了一个名为"hello"的队列。
- 定义消息监听
使用@RabbitListener注解定义消息监听器方法,指定监听的队列和线程池:
@Service
public class MessageReceiver {
@Autowired
private UserRepository userRepository;
@RabbitListener(queues = "hello", containerFactory = "rabbitListenerContainerFactory")
public void handleMessage(String message) {
User user = new User();
user.setName(message);
userRepository.save(user);
}
}
这里使用RabbitListener注解标记handleMessage方法作为消息监听方法,监听"hello"队列的消息。
同时指定使用rabbitListenerContainerFactory作为异步处理容器,以进行异步处理。
- 发送消息
在需要发送消息的地方,使用@Autowired注入AmqpTemplate对象,并调用其convertAndSend方法发送
消息:
@Autowired
private AmqpTemplate rabbitTemplate;
public void sendMessage(String message) {
rabbitTemplate.convertAndSend("hello", message);
}
这里使用convertAndSend方法发送一条消息到名为"hello"的队列。
以上就是在SpringBoot中使用RabbitMQ进行消息处理的基本步骤,使用RabbitMQ可以协助应用程序间异步
消息传递,解耦应用程序之间的关系,提高应用程序的性能和可扩展性。
## 如何使用SpringBoot实现RESTful API?
在SpringBoot中实现RESTful API非常简单,下面是一些基本步骤:
- 添加依赖
在pom.xml文件中添加以下依赖项:
<!-- Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 创建Controller
创建一个@RestController注解的Controller类,并编写不同的方法对应不同的API接口:
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("")
public List<User> getUsers() {
return userService.getUsers();
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping("")
public void addUser(@RequestBody User user) {
userService.addUser(user);
}
@PutMapping("/{id}")
public void updateUser(@PathVariable Long id, @RequestBody User user) {
userService.updateUser(id, user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
这里定义了针对用户操作的RESTful API接口,包括获取全部用户、根据ID获取用户、添加用户、更新用户
和删除用户。
- 编写Service和Repository
创建一个Service类来处理业务逻辑,并使用@Autowired注解注入Repository接口:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getUsers() {
return userRepository.findAll();
}
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
public void addUser(User user) {
userRepository.save(user);
}
public void updateUser(Long id, User user) {
User oldUser = userRepository.findById(id).orElse(null);
if (oldUser == null) {
return;
}
oldUser.setName(user.getName());
oldUser.setEmail(user.getEmail());
userRepository.save(oldUser);
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
这里定义了UserService类,用于对用户的增删改查等操作。
- 运行应用程序
运行SpringBoot应用程序,打开测试工具(如Postman),通过访问API的路径和HTTP方法调用不同的接口
即可实现对用户的增删改查等操作。
以上就是在SpringBoot中实现RESTful API的基本步骤,SpringBoot通过注解的方式自动配置了大部分东
西,使得开发时非常简单和高效。
# 如何理解 Spring Boot 中的 Starter?
```java
Starter 是 Spring Boot 的四大核心功能特性之一,除此之外,Spring Boot 还有自动
装配、Actuator 监控等特性。
Spring Boot 里面的这些特性,都是为了让开发者在开发基于 Spring 生态下的企业级
应用时,只需要关心业务逻辑,减少对配置和外部环境的依赖。
其中,Starter 是启动依赖,它的主要作用有几个。
1. Starter 组件以功能为纬度,来维护对应的 jar 包的版本依赖,
使得开发者可以不需要去关心这些版本冲突这种容易出错的细节。
2. Starter 组件会把对应功能的所有 jar 包依赖全部导入进来,避免了开发者自己去引
入依赖带来的麻烦。
3. Starter内部集成了自动装配的机制,也就说在程序中依赖对应的starter组件以后,
这个组件自动会集成到 Spring 生态下,并且对于相关 Bean 的管理,也是基于自动装
配机制来完成。
4. 依赖 Starter 组件后,这个组件对应的功能所需要维护的外部化配置,会自动集成
到 Spring Boot 里面,
我们只需要在 application.properties 文件里面进行维护就行了,比如 Redis 这个
starter,只需要在 application.properties文件里面添加 redis 的连接信息就可以直接使用了。
在我看来,Starter 组件几乎完美的体现了 Spring Boot 里面约定优于配置的理念。
另外,Spring Boot 官方提供了很多的 Starter 组件,比如 Redis、JPA、MongoDB等等。
但是官方并不一定维护了所有中间件的 Starter,所以对于不存在的 Starter,第三方组
件一般会自己去维护一个。
官方的 starter 和第三方的 starter 组件,最大的区别在于命名上。
官方维护的 starter 的以 spring-boot-starter 开头的前缀。
第三方维护的 starter 是以 spring-boot-starter 结尾的后缀
这也是一种约定优于配置的体现。
3. SpringBoot 如何解决跨域问题
问题分析
跨域指的是浏览器在执行网页中的 JavaScript 代码时,由于浏览器同源策略的限制
只能访问同源(协议、域名、端口号均相同)的资源,而不能访问其他源(协议、域名、端口号任意一个不同)的资源。
而解决跨域问题的方法,就是在不破坏同源策略的情况下,能够安全地实现数据共享和交互
问题解答
常见的解决跨域问题的方法有两种,一种是 jsonp,另一种是 CORS。
其中,CORS 是一种在服务器后端解决跨域的方案,它的工作原理很简单。
如果一个网站需要访问另一个网站的资源,浏览器会先发送一个 OPTIONS 请求,
根据服务器返回的 Access-Control-Allow-Origin 头信息,决定是否允许跨域访问。
所以,我们只需要在服务器端配置 Access-Control-Allow-Origin 属性,并配置允许
哪些域名支持跨域请求即可。
在 Spring Boot 中,提供了两种配置 Access-Control-Allow-Origin 属性的方式来解决跨域问题
通过@CrossOrigin(origins = “http://localhost:8080”)注解,指定允许哪些origins 允许跨域
使用 WebMvcConfigurer 接口,重写 addCorsMappings 方法来配置允许跨域的请求源文章来源:https://www.toymoban.com/news/detail-468173.html
@Configuration
publicclassCorsConfigimplementsWebMvcConfigurer {
@Override
publicvoidaddCorsMappings(CorsRegistryregistry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("*");
}
}
写在最后 :
👉 💕" 过期的儿童也是儿童", 小伙伴们,六一快乐 ! 一起加油!
码字不易,麻烦大家小手一点 , 点赞或关注 , 感谢大家的支持!!文章来源地址https://www.toymoban.com/news/detail-468173.html
到了这里,关于第五章--SpringBoot重点面试题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!