参考文章:
Spring Boot 进阶
(1)Spring Boot 是一个快速开发框架,提供了一系列的快捷、便利的工具,让开发者可以更加专注于应用程序的业务逻辑,而不用花费太多时间和精力在构建和配置应用程序环境上。它是建立在 Spring 基础之上的,并非代替了 Spring 框架,而是让 Spring 框架更加容易得到快速的使用。
(2)Spring Boot 的优点如下:
Spring Boot 是一个基于 Spring 框架的快速应用开发框架,包含了大量预定义的配置、依赖项和代码组件,可以帮助开发人员快速搭建稳健可靠的 Web 应用程序以及微服务。下面是 Spring Boot 的优点:
总之,Spring Boot 为 Java 开发人员提供了一个高效且灵活的开发框架,可以简化开发过程,减少代码冗余和复杂性,并提高开发效率和开发体验。
(1)Spring MVC 是 Spring 框架的 MVC (Model-View-Controller) 模式的实现,而 Spring Boot 是一种快速开发框架,用于简化 Spring 应用程序的开发。虽然它们都是 Spring 框架的一部分,但二者之间还是有几个区别:
(2)总之,Spring MVC 和 Spring Boot 都是 Spring 框架的一部分,但它们的目的和方式不同。Spring MVC 更侧重于实现 MVC 模式,而 Spring Boot 则更关注于快速开发以及简化配置。
(1)Spring 和 Spring Boot 是两个紧密相关的Java开发框架,它们之间存在以下关系:
(2)具体而言,Spring Boot 是在 Spring 框架的基础上构建的,通过引入单一的 starter 依赖,可以非常方便地集成和配置多个 Spring 模块和功能。Spring Boot 提供了自动配置和约定的方式来简化开发流程,开发者只需要关注业务逻辑的实现,而无需过多关注框架的配置和集成细节。
(3)因此,可以将 Spring Boot 看作是 Spring 框架的一种扩展或增强,旨在提供更加简化和高效的开发体验。使用 Spring Boot 可以快速搭建 Spring 应用程序,并提供内嵌的 Web 服务器、自动化的配置和管理等功能,大大简化了 Spring 项目的开发和部署过程。
(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 配置文件和自定义依赖项的细节,从而更快地开始开发应用程序,并增加代码的可读性和可维护性。
(1)Spring Boot 支持以下内嵌 Servlet 容器:
(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.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jettyartifactId>
dependency>
(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 面试题——自动装配这篇文章。
(1)RESTful 风格是一种设计和组织 Web 服务的架构风格,它基于 HTTP 协议,旨在提供一种简洁、可扩展和易于理解的方式来构建和交互分布式系统。RESTful 风格的特点包括:
(2)使用 RESTful 风格的原因在于:
(3)总之,RESTful 风格提供了一种简单、灵活和可扩展的架构设计方式,适用于构建各种规模的分布式系统和 Web 服务。它通过基于资源、无状态、统一接口和可缓存等特点,帮助开发人员设计和实现高效、可伸缩的 API 和服务。
参考 Spring Boot 面试题——常用注解这篇文章。
参考 Spring Boot 面试题——配置文件这篇文章。
参考 Spring Boot 面试题——定时任务这篇文章。
参考 Spring Boot 面试题——全局异常处理这篇文章。
(1)在 Spring Boot 中,可以通过以下几种方式来监控系统的实际运行状况:
http://localhost:8080/actuator/health
来访问应用程序的健康状态信息。<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
(2)综上所述,以上列出了一些常用的监控方式。需要根据实际情况选择监控工具进行使用,并根据业务需求及时对应用程序的状态进行调整和优化。
首先,Spring Boot 能够将 Tomcat 内嵌,是因为 Tomcat 提供了一套 Java API,能够通过 Tomcat tomcat = new Tomcat()
来创建一个 Tomcat 容器。具体来说只需要引入对应的 Maven 依赖即可:
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-coreartifactId>
<version>${tomcat.version}version>
dependency>
(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();
}
}
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 等。TomcatServletWebServerFactory
中的 getWebServer
方法来获取 Web Server。在该方法中,Spring Boot 就调用了 tomcat-embed
提供的 API,从而来完成 Tomcat 的创建、启动等一系列过程。WebServer
接口,提供了“启动”和“停止”两个基本方法,具体方法由不同的 Web 容器各自实现,其中 Tomcat 的实现类叫 TomcatWebServer
。TomcatWebServer
在构造方法中调用 initialize()
初始化 Tomcat,调用 start()
方法启动 Web 服务,在 Spring 容器销毁之前调用stop()
完成 Tomcat 生命周期。(1)Spring Boot 项目可以使用以下命令进行启动:
mvn spring-boot:run
gradle bootRun
java -jar your-project-name.jar
其中,your-project-name.jar
是生成的可执行 JAR 文件的名称。
(2)无论使用哪种方式启动 Spring Boot 项目,都会自动扫描并加载项目中的主类,并启动嵌入式的 Tomcat 服务器,使得应用程序可以通过默认端口(一般为 8080)进行访问。
(3)另外,还可以通过在 IDE 中直接运行 Spring Boot 主类的方式启动项目,具体操作取决于使用的开发工具。例如,在 IntelliJ IDEA 中,可以右键点击主类,选择 “Run” 或 “Debug” 来启动项目。