目录
- 1.Spring Boot 快速入门
- 什么是 Spring Boot?有什么优点?
- Spring Boot 与 Spring MVC 有什么区别?
- Spring 与 Spring Boot 有什么关系?
- ✨什么是 Spring Boot Starters?
- Spring Boot 支持哪些内嵌 Servlet 容器?如何设置其它的内嵌 Servlet 容器?
- Spring Boot 中 Tomcat 内嵌原理是什么?
- ✨请介绍一下 @SpringBootApplication 注解。
- ✨Spring Boot 的自动配置是如何实现的?
- 什么是 RESTful 风格?为什么要使用 RESTful 风格?
- 2.Spring Boot Web 开发
- Spring Boot 中常用的注解有哪些?
- 介绍一下 Spirng Boot 常用的两种配置文件。
- 在 Spring Boot 中如何实现定时任务?
- ✨在 Spring Boot 中如何实现全局异常处理?
- 在 Spring Boot 中如何监控系统实际运行状况?
- Spring Boot 中内嵌 Tomcat 的实现原理是什么?
- Tomcat-embed
- Spring Boot 源码解读
- 总结
- Spring Boot 项目启动命令是什么?
参考文章:
Spring Boot 进阶
1.Spring Boot 快速入门
什么是 Spring Boot?有什么优点?
(1)Spring Boot 是一个快速开发框架,提供了一系列的快捷、便利的工具,让开发者可以更加专注于应用程序的业务逻辑,而不用花费太多时间和精力在构建和配置应用程序环境上。它是建立在 Spring 基础之上的,并非代替了 Spring 框架,而是让 Spring 框架更加容易得到快速的使用。
(2)Spring Boot 的优点如下:
Spring Boot 是一个基于 Spring 框架的快速应用开发框架,包含了大量预定义的配置、依赖项和代码组件,可以帮助开发人员快速搭建稳健可靠的 Web 应用程序以及微服务。下面是 Spring Boot 的优点:
- 简化配置:Spring Boot 简化了庞大的配置文件和冗长的 XML 配置。通过使用 Starter,Spring Boot 可以自动配置应用程序所需的所有组件和服务。
- 快速开发:使用 Spring Boot,开发人员可以快速搭建 Web 应用程序和微服务,不需要进行任何配置或安装,只需选择适当的 Starter,即可快速入门。
- 易于集成:Spring Boot 可以与许多流行的框架和库集成,如 Spring Data、Spring Security 等等。它还支持多个 Web 框架和模板引擎,例如 Thymeleaf、Freemarker 等等。
- 自动配置:Spring Boot 的自动配置机制可以帮助开发人员减少应用程序的开发时间和成本。根据应用程序依赖关系,Spring Boot 可以自动配置许多组件和服务,例如数据库和消息队列。
- 易于部署:Spring Boot 应用程序可以作为独立的 Jar 包或 War 包部署。它们还可以在云中进行部署,例如 AWS、Google Cloud。
- 易于测试:Spring Boot 提供了广泛的测试支持,包括单元测试和集成测试。开发人员可以使用 JUnit 或 Spring 的测试框架来测试应用程序。
总之,Spring Boot 为 Java 开发人员提供了一个高效且灵活的开发框架,可以简化开发过程,减少代码冗余和复杂性,并提高开发效率和开发体验。
Spring Boot 与 Spring MVC 有什么区别?
(1)Spring MVC 是 Spring 框架的 MVC (Model-View-Controller) 模式的实现,而 Spring Boot 是一种快速开发框架,用于简化 Spring 应用程序的开发。虽然它们都是 Spring 框架的一部分,但二者之间还是有几个区别:
- 依赖项:Spring MVC 依赖于许多其他 Spring 框架组件来实现 MVC 模式,例如 Spring Core、Spring Beans 和 Spring Context 等等。而 Spring Boot 可以快速地搭建应用程序,因为它包含了大量的预定义配置、依赖关系和代码组件,开发人员只需要选择适当的 Starter,即可快速入门。
- 配置:Spring MVC 需要繁琐的 XML 配置文件或 Java 注释来启用自动扫描、处理器映射、请求映射等等。然而,Spring Boot 使用自动配置机制,使得配置更加简单。
- 应用程序生命周期:使用 Spring MVC,开发人员必须手动配置并启动服务器,部署应用程序。但是使用 Spring Boot,应用程序可以使用外部应用程序容器或自带的 Tomcat 直接启动,这样开发人员可以专注于应用程序的开发而无需关注服务器或应用程序容器的配置。
- 引入其他库的方式:在Spring MVC中,如果想要使用一些第三方库或框架,必须手动添加相关依赖和配置。但是在Spring Boot中,只需要引入相关的Starter依赖,就可以实现自动配置和集成。
(2)总之,Spring MVC 和 Spring Boot 都是 Spring 框架的一部分,但它们的目的和方式不同。Spring MVC 更侧重于实现 MVC 模式,而 Spring Boot 则更关注于快速开发以及简化配置。
Spring 与 Spring Boot 有什么关系?
(1)Spring 和 Spring Boot 是两个紧密相关的Java开发框架,它们之间存在以下关系:
- Spring 是一个轻量级的开源 Java 框架,提供了一套全面的企业级应用程序开发解决方案。它基于 IoC (Inversion of Control) 和 AOP (Aspect-Oriented Programming) 原则,提供了对依赖注入、面向切面编程、数据访问、事务管理、MVC 等功能的支持,并集成了许多其他开源库。Spring框架是模块化的,可以根据需求选择不同的模块来构建应用程序。
- Spring Boot 是基于 Spring 框架的一个开箱即用的框架(可以理解为脚手架),旨在简化 Spring 应用程序的搭建和部署。它提供了自动配置、约定优于配置的原则,以及快速的开发体验。Spring Boot 通过预设的默认设置,减少了开发者进行配置的工作量,并提供了一种简化和快速构建独立的、可执行的 Spring 应用程序的方式。
(2)具体而言,Spring Boot 是在 Spring 框架的基础上构建的,通过引入单一的 starter 依赖,可以非常方便地集成和配置多个 Spring 模块和功能。Spring Boot 提供了自动配置和约定的方式来简化开发流程,开发者只需要关注业务逻辑的实现,而无需过多关注框架的配置和集成细节。
(3)因此,可以将 Spring Boot 看作是 Spring 框架的一种扩展或增强,旨在提供更加简化和高效的开发体验。使用 Spring Boot 可以快速搭建 Spring 应用程序,并提供内嵌的 Web 服务器、自动化的配置和管理等功能,大大简化了 Spring 项目的开发和部署过程。
✨什么是 Spring Boot Starters?
(1)Spring Boot Starters 是一组预定义的依赖项集合,可以让我们更加方便地创建 Spring Boot 应用程序。使用 Spring Boot Starters,我们可以避免手动添加大量的依赖项,同时也可以避免因为版本冲突和依赖项缺失而带来的问题。另外,Spring Boot Starters 还提供了一些预定义的默认配置,可以让我们更加快速地启动一个 Spring Boot 应用程序。一些常见的 start 有:
spring-boot-starter-web
:用于快速启动 Spring MVC 应用程序,并包含 Tomcat Web 容器的依赖。spring-boot-starter-security
:集成 Spring Security,用于 Web 应用程序的身份验证和授权。spring-boot-starter-test
:包含了用于在 Spring Boot 应用程序中进行单元测试和集成测试的依赖。spring-boot-starter-amqp
:集成了 AMQP(高级消息队列协议)功能,通过 RabbitMQ 作为消息代理实现消息传递。
(2)通过引入 Spring Boot Starters,开发人员可以离开 Spring Boot 配置文件和自定义依赖项的细节,从而更快地开始开发应用程序,并增加代码的可读性和可维护性。
Spring Boot 支持哪些内嵌 Servlet 容器?如何设置其它的内嵌 Servlet 容器?
(1)Spring Boot 支持以下内嵌 Servlet 容器:
- Tomcat:Tomcat 是 Apache 软件基金会的一个开源 Servlet/JSP 容器,同时也是 Spring Boot 中默认的 Servlet 容器。
- Jetty:Jetty 是 Eclipse Foundation 的企业级 Java Servlet 容器,也是开源的。Spring Boot 也包含了 Jetty 的依赖项,可以作为替代 Tomcat 的 Servlet 容器启动应用程序。
- Undertow:Undertow 是一个快速、灵活的 Web 服务器,而且是可以嵌入的。它也是 Red Hat 社区项目之一,Spring Boot 中同样包含了 Undertow 的依赖项。
(2)通过使用内嵌 Servlet 容器,Spring Boot 可以把应用程序打包成一个可执行的 jar 包,从而可以非常方便地部署和运行。同时,内嵌 Servlet 容器对开发和测试也非常方便,因为可以避免在开发、测试和部署时需要手动配置和启动一些独立的容器。
① Servlet 是一种 Java 类,用于在 Web 服务器上处理客户端请求和生成响应。Servlet 通常用于处理浏览器发送的 HTTP 请求,可以动态生成 HTML、处理表单和上传文件、修改 Cookies 和 Session 数据等等。Servlet 是一个标准的 Java 接口,需要借助 Servlet 容器才能被执行。Web 服务器在接收到 HTTP 请求后,会从 Servlet 容器中找到对应的 Servlet,然后将请求传递给 Servlet,并将处理结果返回给客户端。
② Servlet 容器是指能够运行 Servlet 的环境,通常是 Web 服务器或应用服务器中的一个组件。Servlet 容器在接收到客户端的请求后会将请求转发给相应的 Servlet 进行处理,并将 Servlet 的响应返回给客户端。
(3)如果需要使用其他内嵌 Servlet 容器,可以在 Maven 或 Gradle 构建文件中添加相应的依赖项,例如使用 Jetty 作为内嵌 Servlet 容器,可以先从 spring-boot-starter-web 中排除 Tomcat,然后再添加 Jetty 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--从 spring-boot-starter-web 中排除 Tomcat-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加 Jetty 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Spring Boot 中 Tomcat 内嵌原理是什么?
✨请介绍一下 @SpringBootApplication 注解。
(1)@SpringBootApplication 注解是 Spring Boot 中的核心注解之一,该注解作用是标识一个类为 Spring Boot 应用程序的主程序类。该注解集成了其他三个注解:
@Configuration
:用于标记某个类为 Spring 容器中的一个配置类,配置类中的方法通过 @Bean 注解可以向 Spring 容器注册一个 Bean 对象。被该注解标记的类类似于 XML 中的 Bean 定义文件,在其中我们可以声明和组合 Bean 对象。@EnableAutoConfiguration
:用于启动 Spring Boot 的自动配置机制,它会根据项目中引入的依赖,自动配置 Spring Boot 应用程序。如果我们需要修改自动配置中的某些配置,可以使用 Spring Boot 提供的一些属性进行修改。同时,我们也可以使用exclude
属性排除自动配置中的一些组件。@ComponentScan
:默认扫描主程序所在的包及其下面的子包中所有被 Spring 管理的组件(即类名上使用了 @Component、@Controller、@Service、@Repository、@Configuration 等注解的类),然后将它们注册到 Spring 容器中;此外,还可以通过该注解的basePackages
属性和basePackageClasses
属性分别来自定义要扫描包及其子包,以及指定类所在的包路径。
(2)上述三个注解的组合使得 Spring Boot 应用程序能够自动配置和启动。此外,@SpringBootApplication 注解还可以通过其属性进行更多配置,例如 exclude
属性可用于排除自动配置中的一些组件,scanBasePackages
属性可用于手动设置要扫描的组件的基本包名等。
✨Spring Boot 的自动配置是如何实现的?
与 Spring Boot 的自动配置相关的知识可以参考 Spring Boot 面试题——自动装配这篇文章。
什么是 RESTful 风格?为什么要使用 RESTful 风格?
(1)RESTful 风格是一种设计和组织 Web 服务的架构风格,它基于 HTTP 协议,旨在提供一种简洁、可扩展和易于理解的方式来构建和交互分布式系统。RESTful 风格的特点包括:
- 基于资源:将 Web 服务中的数据和功能抽象为资源的概念,并通过 URI 来标识和定位资源。每个资源对应一个唯一的 URL,并通过 HTTP 方法(如 GET、POST、PUT、DELETE 等)对资源进行操作。
- 无状态性:每次 HTTP 请求都是独立的,不依赖之前的请求状态。服务器不保存客户端的状态信息,客户端需要在每个请求中提供必要的身份验证和数据。
- 统一接口:RESTful 接口定义了一组标准的方法(如 GET、POST、PUT、DELETE)和约束条件(如使用 HTTP 状态码、使用可扩展的标记语言如 JSON 或 XML 进行数据传输)来进行通信。
- 可缓存性:RESTful 服务可以利用HTTP协议的缓存机制,提高性能和可伸缩性。
(2)使用 RESTful 风格的原因在于:
- 简单和易于理解:RESTful 风格使用统一的接口和资源的概念,使得API设计更加直观和易于理解。
- 可扩展性:RESTful 风格允许逐步扩展 API,添加新的资源和功能,并与现有系统和资源进行组合和整合。
- 松耦合性:RESTful 风格通过使用 HTTP 标准方法来操作资源,使得客户端和服务器之间的耦合度降低,提高了系统的灵活性和可维护性。
- 跨平台和语言无关性:RESTful 风格使用标准的 HTTP 协议和数据格式,使得不同平台和编程语言的应用程序可以进行互操作。
(3)总之,RESTful 风格提供了一种简单、灵活和可扩展的架构设计方式,适用于构建各种规模的分布式系统和 Web 服务。它通过基于资源、无状态、统一接口和可缓存等特点,帮助开发人员设计和实现高效、可伸缩的 API 和服务。
2.Spring Boot Web 开发
Spring Boot 中常用的注解有哪些?
参考 Spring Boot 面试题——常用注解这篇文章。
介绍一下 Spirng Boot 常用的两种配置文件。
参考 Spring Boot 面试题——配置文件这篇文章。
在 Spring Boot 中如何实现定时任务?
参考 Spring Boot 面试题——定时任务这篇文章。
✨在 Spring Boot 中如何实现全局异常处理?
参考 Spring Boot 面试题——全局异常处理这篇文章。
在 Spring Boot 中如何监控系统实际运行状况?
(1)在 Spring Boot 中,可以通过以下几种方式来监控系统的实际运行状况:
- Actuator 模块:Spring Boot Actuator 提供了多种监控和管理接口,包括 health、metrics、trace、heapdump 等。可以将 Actuator 模块添加到应用程序的 classpath 中(例如,通过在 pom.xml 中添加依赖项的方式),然后以 RESTful Web 服务的形式访问这些 Actuator 端点。例如,可以在浏览器中输入
http://localhost:8080/actuator/health
来访问应用程序的健康状态信息。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- Spring Boot Admin:Spring Boot Admin 是一款管理和监控 Spring Boot 应用程序的 Web 应用程序,它提供了实时的监控和管理功能,可以监控 CPU 使用率、内存使用率、请求次数、响应时间等指标。使用 Spring Boot Admin 需要添加 Spring Boot Actuator 和 Spring Boot Admin Server 依赖项,然后在应用程序中添加@EnableAdminServer 注释。
- 容器监控工具:JMX(Java Management Extension)和 JConsole(Java Monitoring & Management Console)是基于 JDK 监视和管理 JVM 应用程序的标准工具。可以使用 JMX 和 JConsole 来监控 Spring Boot 应用程序的运行状况、线程池等。
- 日志:Spring Boot 应用程序使用日志记录器来记录运行时信息。可以配置日志来监控应用程序的运行状态,包括异常信息、异常堆栈等。例如,可以使用 Spring Boot 的 Logging System 来配置日志记录器,或者使用 Logback、Log4j 等常见的日志框架。
(2)综上所述,以上列出了一些常用的监控方式。需要根据实际情况选择监控工具进行使用,并根据业务需求及时对应用程序的状态进行调整和优化。
Spring Boot 中内嵌 Tomcat 的实现原理是什么?
Tomcat-embed
首先,Spring Boot 能够将 Tomcat 内嵌,是因为 Tomcat 提供了一套 Java API,能够通过 Tomcat tomcat = new Tomcat()
来创建一个 Tomcat 容器。具体来说只需要引入对应的 Maven 依赖即可:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
Spring Boot 源码解读
(1)在 Spring Boot 源码中,Spring 则使用这套 API 与自身结合进行结合。
(2)首先,任意一个 Spring Boot 应用,都有一个 main() 函数作为应用的启动方法,里面调用了 SpringApplication.run(MyApplication.class, args)
方法,这个 run() 的核心实现代码如下(这里去掉了一些与主线逻辑无关的代码):
public class SpringApplication {
//...
/**
* Run the Spring application, creating and refreshing a new
* {@linkApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
ConfigurableApplicationContext context = null;
//创建 Spring 容器对象 ApplicationContext
context = createApplicationContext();
//做一些初始化容器之前的预备操作
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//启动 Spring 容器核心方法,包括启动 tomcat
refreshContext(context);
//做一些容器启动之后的操作(当前这个方法是空的)
afterRefresh(context, applicationArguments);
return context;
}
}
看过 Spring 源码的同学应该清楚,启动 Spring 容器的核心方法就是 refresh()
,而这里的方法名叫 refreshContext(context)
,不过是 Spring Boot 对 refresh() 的封装罢了,所以内部依然是调用的 AbstractApplicationContext
中的 refresh()
,于是我们来到这个核心方法内部。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
//...
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//在容器启动之前做一些准备操作
prepareRefresh();
//通知子类去刷新实例工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//初始化当前容器中的实例工厂
prepareBeanFactory(beanFactory);
try {
//允许容器中的基类对实例工厂进行后置处理
postProcessBeanFactory(beanFactory);
//调用实例工厂中的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
//注册实例的后置处理器,在创建实例时进行拦截
registerBeanPostProcessors(beanFactory);
//初始化消息资源
initMessageSource();
//初始化容器中的事件处理器
initApplicationEventMulticaster();
//初始化一些在特定容器中特殊的实例,包括创建 Tomcat
onRefresh();
//检查监听器的实例并注册它们
registerListeners();
//实例化所有非懒加载的实例
finishBeanFactoryInitialization(beanFactory);
//最后一步:发布一些响应事件
finishRefresh();
}
catch (BeansException ex) {
//...
}
finally {
//...
}
}
}
}
当这个方法调用完,Spring 容器就基本完成了初始化过程,Tomcat 当然也是在这个方法内部完成的创建。
(3)Spring Boot 内嵌的各种 web 容器实例,都是在 onRefresh()
中进行创建的。虽然这个方法是个空方法,但是其子类的都实现了这个方法,子类列表如下:
因为 Tomcat 是一个 Servlet 容器,所以我们直接看 ServletWebServerApplicationContext
这个类中是如何实现的
public class ServletWebServerApplicationContext extends GenericWebApplicationContext
implements ConfigurableWebServerApplicationContext {
//...
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
//通过工厂创建 WebServer 实例
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
}
总结
- 首先,当前 Spring Boot 应用程序通过
SpringApplication.run(MyApplication.class, args)
方法启动,所以说 Tomcat 的内嵌实现也在这个方法中; - 其次,在
run
方法中有一个非常重要的方法,名为refreshContext(context)
,而实际上该方法是 Spring Boot 对启动 Spring 容器的核心方法refresh()
的封装。在refresh
方法中有 12 个方法来共同完成 Spring 容器的创建与启动,其中 Tomcat 的创建就在onRefresh()
方法进行的。 - 虽然
onRefresh()
是个空方法,但是其子类实现了这个方法,与 Tomcat 创建相关的子类是ServletWebServerApplicationContext
; ServletWebServerApplicationContext
中的createWebServer()
则通过工厂方法来创建相应的 WebServer。既然这里通过工厂方法创建对象,肯定对象类型就不止一种,并且 Spring Boot 支持的内嵌 Web 容器不止有 Tomcat,还有 Jetty、Undertow 等。- 由于 Spring Boot 默认内嵌的 Web 容器是 Tomcat,因此这里主要是
TomcatServletWebServerFactory
中的getWebServer
方法来获取 Web Server。在该方法中,Spring Boot 就调用了tomcat-embed
提供的 API,从而来完成 Tomcat 的创建、启动等一系列过程。 - 此外,Spring 抽象了
WebServer
接口,提供了“启动”和“停止”两个基本方法,具体方法由不同的 Web 容器各自实现,其中 Tomcat 的实现类叫TomcatWebServer
。 - 最后,
TomcatWebServer
在构造方法中调用initialize()
初始化 Tomcat,调用start()
方法启动 Web 服务,在 Spring 容器销毁之前调用stop()
完成 Tomcat 生命周期。
Spring Boot 项目启动命令是什么?
(1)Spring Boot 项目可以使用以下命令进行启动:
- 使用 Maven 插件启动:如果你的 Spring Boot 项目使用 Maven 作为构建工具,可以通过以下命令启动项目:
mvn spring-boot:run
- 使用 Gradle 插件启动:如果你的 Spring Boot 项目使用 Gradle 作为构建工具,可以通过以下命令启动项目:
gradle bootRun
- 打包成可执行 JAR 文件后启动:首先使用 Maven 或 Gradle 将项目打包成可执行的 JAR 文件,然后通过以下命令启动项目:
java -jar your-project-name.jar
其中,your-project-name.jar
是生成的可执行 JAR 文件的名称。
(2)无论使用哪种方式启动 Spring Boot 项目,都会自动扫描并加载项目中的主类,并启动嵌入式的 Tomcat 服务器,使得应用程序可以通过默认端口(一般为 8080)进行访问。
(3)另外,还可以通过在 IDE 中直接运行 Spring Boot 主类的方式启动项目,具体操作取决于使用的开发工具。例如,在 IntelliJ IDEA 中,可以右键点击主类,选择 “Run” 或 “Debug” 来启动项目。