Spring和Spring Boot必备知识
初始化Spring项目
Spring生态系统概览
什么是Spring
Spring的核⼼是提供了⼀个容器(container),通常称为Spring应⽤上下⽂(Spring application context),容器会创建和管理应⽤组件。
**这些组件也可以称为bean,会在Spring应⽤上下⽂中装配在⼀起,从⽽形成⼀个完整的应⽤程序。**这就像砖头、砂浆、⽊材、管道和电线组合在⼀起,形成⼀栋房⼦似的。
将bean装配在一起的行为是通过一种基于依赖注入(dependency injection)的模式进行实现的。此时组件不会再去创建它锁一i来的组件并管理它们的生命周期,使用依赖注入的应用依赖于单独的实体(容器)来创建和维护所有组件。
在核⼼容器之上,Spring及其⼀系列的相关库提供了Web框架、各种持久化可选⽅案、安全框架、与其他系统集成、运⾏时监控、微服务⽀持、反应式编程以及众多现代应⽤开发所需的特性。
在历史上,指导Spring应⽤上下⽂将bean装配在⼀起的⽅式是使⽤⼀个或多个XML⽂件(描述各个组件以及它们与其他组件的关联关系)。
<bean id="inventoryService"
class="com.example.InventoryService" />
<bean id="productService"
class="com.example.ProductService" />
<constructor-arg ref="inventoryService" />
</bean>
最近,随着Spring Boot的引⼊,⾃动配置的能⼒已经远远超出了组件扫描和⾃动装配。Spring Boot是Spring框架的扩展,提供了很多增强⽣产效率的⽅法。最为常见的就是自动配置(cutoconfiguration)。Spring
Boot能够基于类路径中的条⽬、环境变量和其他因素合理猜测需要配置的组件并将它们装配在⼀起。
将Spring和Spring Boot当成⼀回事。我们会尽可能多地使⽤Spring Boot,只有在必要的时候才使⽤显式配置。因为Spring XML配置是⼀种过时的⽅式,所以主要关注Spring基于Java的配置。
初始化Spring应用
利用vscode创建springboot项目TACO-CLOUD,将应⽤构建成⼀个可执⾏的JAR⽂件,包含依赖DevTools/Thymeleaf/Web三个初始依赖。
**打包为JAR⽂件是基于云思维做出的选择。尽管WAR⽂件⾮常适合部署到传统的Java应⽤服务器上,但对于⼤多数云平台来说它们并不是理想的选择。有些云平台(⽐如Cloud Foundry)也能够部署和运⾏WAR⽂件,但是所有的Java云平台都能够运⾏可执⾏的JAR⽂件。**因此,Spring Initializr默认会使⽤基于JAR的打包⽅式,除⾮我们明确告诉它采⽤其他的⽅式。如果你想要将应⽤部署到传统的Java应⽤服务器上,那么需要选择使⽤基于WAR的打包⽅式并要包含⼀个Web初始化类。
目录体系
- mvnw和mvnw.cmd:是Maven包装器(wrapper)脚本。借助脚本,即便及其没有安装Maven也可以构建项目。
- pom.xml:是Maven的构建规范
- TacoCloudApplication.java:这是Spring Boot主类,它会启动该项⽬。
- application.properties:这个文件起初是空的,但是位我们提供制定的配置属性的地方。
- static:在这个文件夹下存放任意为浏览器提供服务的静态内容。该文件夹初始为空。
- templates:这个⽂件夹中存放⽤来渲染内容到浏览器的模板⽂件。这个⽂件夹初始是空的。
- TacoCloudApplicationTests.java:这是⼀个简单的测试类,它能确保Spring应⽤上下⽂可以成功加载。在开发应⽤的过程中,我们会将更多的测试添加进来。
构建规范 pom.xml
pom.xml文件声明项目构建的规范
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version><!--Spring Boot版本-->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>taco-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>taco-cloud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
</properties>
<!--Starter依赖-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!--Spring Boot插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-
构建规范的parent 元素是的子元素,表示以spring-boot-starter-parent作为其父POM。这个父POM为Spring项目常用的一些库提供依赖管理。
-
构建规范里dependencies元素的 3 个依赖的artifact ID上都有starter这个单词。Spring Boot starter依赖的特别之处在于它们本⾝并不包含库代码,⽽是传递性地拉取其他的库。 这种starter依赖主要有3个好处。
1、构建文件显著的减小并易于管理(不在徐奥对每个所需的依赖库声明依赖)
2、根据提供的功能来思考依赖。开发Web应用只需要添加Web Starter不必添加一堆库来构建Web应用。
3、不必担心库的版本问题,只需关注Spring Boot的版本。 -
构建规范还包含⼀个Spring Boot插件提供了⼀些重要的功能。
1、提供一个Maven goal允许使用Maven来允许应用
2、确保依赖的库都包含在可执行的JAR文件里,保证在运行的类路径下是可用的。
3、在JAR里生成manifest文件,将引导类TacoCloudApplication声明为可执⾏JAR的主类。 -
构建规范声明对Web和Thymeleaf starter的依赖
1、Spring的MVC框架
2、嵌入式的Tomcat
3、Thymeleaf和Thymeleaf布局方言 -
引入Spring Boot自动配置库。当应用启动的时候Spring Boot的自动配置会探测到这些库并完成以下功能
1、在Spring应用上下文里配置bean以启动Spring MVC
2、在Spring应用上下文里嵌入式的Tomcat服务器
3、配置Thymeleaf视图解析器,以便于使用Thymeleaf模板渲染Spring MVC视图
引导应用
执行整个项目(JAR文件)的时候需要一个主类和一个最小化的Spring配置引导在JAR运行应用。这就是TacoCloudApplication类所做的事情
package com.example.tacocloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TacoCloudApplication {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args);
}
}
类的注解@SpringBootApplication表明是一个Spring Boot应用。@SpringBootApplication是一个组合注解,它组合了3个其他的注解。
- @SpringBootConfiguration:表明该类是配置类。
- @EnableAutoConfiguration:启⽤Spring Boot的⾃动配置。注解告诉Spring Boot自动配置用到的组件。
- @ComponentScan:启⽤组件扫描。这样我们能够通过像@Component、@Controller、@Service这样的注解声明其他类,Spring会⾃动发现它们并将它们注册为Spring应⽤上下⽂中的组件。
mian() 方法是JAR文件执行的时候运行的方法。方法调用SpringApplication里静态的run()方法,后者会真正的执行应用的引导过程,也就是创建Spring上下文。
在传递给run()的两个参数中,⼀个是配置类,另⼀个是命令⾏参数。尽管传递给run()的配置类不⼀定要和引导类相同,但这是最便利和最典型的做法。
对简单应用程序而语言,在引导类里配置一两个组件非常方便,但对于大多数应用而言,最好单独为没有实现自动配置的功能创建一个单独的配置类。
测试应用
package com.example.tacocloud;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class TacoCloudApplicationTests {
@Test
void contextLoads() {
}
}
TacoCloudApplicationTests类中的内容并不多:这个类中只有⼀个空的测试⽅法。即便如此,这个测试类还是会执⾏必要的检查,确保Spring应⽤上下⽂能够成功加载。
注意这个类带有@RunWith(SpringRunner.class)注解。**@RunWith是JUnit的注解,它会提供⼀个测试运⾏器(runner)来指导JUnit如何运⾏测试。**可以将其想象为给JUnit应⽤⼀个插件,以提供⾃定义的测试⾏为。
尽管@RunWith(SpringRunner.class)和@SpringBootTest会为测试加载Spring应⽤上下⽂,但是如果没有任何测试⽅法,那么它们其实什么事情都没有做。即便没有任何断⾔或代码,这个空的测试⽅法也会提⽰这两个注解完成了它们的⼯作并成功加载Spring应⽤上下⽂。如果这个过程中有任何问题,那么测试都会失败。
Spring编写TacoCloud主页
为Taco Cloud添加主页,将会创建两个代码的构件
- 一个控制器类,用来处理主页相关请求
- 一个视图模板,用来定义主页的样子
处理Web请求
Spring自带的强大Web框架——Sping MVC。
Spring MVC的核心是控制器(Controller)。控制器是处理请求并以某种方式进行信息的响应的类。
package tacos;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller //控制器
public class HomeController{
@GetMapping('/') //处理对根路径“/”的请求
public String home(){
return "home"; //返回视图名
}
}
这个类带有@Controller。就其本⾝⽽⾔,@Controller并没有做太多的事情。它的主要⽬的是让组件扫描将这个类识别为⼀个组件。因为HomeController带有@Controller,所以Spring的组件扫描功能会⾃动发现它并创建⼀个HomeController实例作为Spring应⽤上下⽂中的bean。
home()是⼀个简单的控制器⽅法。它带有@GetMapping注解,表明如果针对“/”发送HTTP GET请求,那么这个⽅法将会处理请求。该⽅法所做的只是返回String类型的home值。
Thymeleaf定义视图
模板名称是由逻辑视图名派⽣⽽来的,再加上“/templates/”前缀和“.html”后缀。最终形成的模板路径将是“/templates/home.html”。所以,我们需要将模板放到项⽬的“/src/main/resources/templates/home.html”⽬录
中。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Taco Cloud</title>
</head>
<body>
<h1>Welcome to ...</h1>
<img th:src="@{/images/TacoCloud.png}">
</body>
</html>
⽤于展现Taco Cloud Logo的标签。它使⽤了Thymeleaf的th:src属性和@{…}表达式,以便于引⽤相对于上下⽂路径的图⽚。
图⽚是使⽤相对于上下⽂的“/images/TacoCloud.png”路径来进⾏引⽤的。回忆⼀下我们的项⽬结构,像图⽚这样的静态资源是放到“/src/main/resources/static”⽂件夹中的。图⽚必须要位于“/src/main/resources/static/images/TacoCloud.png”
运行启动
利用Spring Boot DASHBROAD运行Spring程序,在浏览器查看对应端口。
了解Spring Boot DevTools
DevTools为Spring开发人员提供一些便利的开发期工具
- 代码变更后应用会自动重启
- 当面向浏览器的资源(如模板、JavaScript、样式表)等发生变化时,会自动刷新浏览器
- 自动禁用模板缓存
- 如果使用H2数据库,内置H2控制台
应用自动重启
当DevTools运⾏的时候,应⽤程序会被加载到Java虚拟机
(Java virtual Machine,JVM)两个独⽴的类加载器中。
- 其中⼀个类加载器会加载你的Java代码、属性⽂件以及项⽬中“src/main/”路径下⼏乎所有的内容。这些条⽬很可能会经常发⽣变化。
- 另外⼀个类加载器会加载依赖的库,这些库不太可能 经常发⽣变化。
当探测到变更的时候,**DevTools只会重新加载包含项目代码的类加载器,并重启Spring的应用上下文,在过程里另一个类加载器和JVM会原封不动,以此减少应用启动的时间。**不足之处就是自动重启反映依赖的变化。因为包含依赖库的类加载器不会自动重新加载,意味着当构建规范中添加、变更或移除依赖的时候,需要重新启动应用。
浏览器自动刷新的禁用模板缓存
默认情况下,像Thymeleaf和FreeMarker这样的模板⽅案在配置时会缓存模板解析的结果。这样的话,在为每个请求提供服务的时候,模板就不⽤重新解析了。在⽣产环境中,这是⼀种很好的⽅式,因为它会带来⼀定的性能收益。
在程序运行时候如果缓存模板,在刷新浏览器的时候就无法看到模板更新的效果。即使我们对模板进行修改,在应用重启之前,缓存的模板依然会有效。
DevTools在运行的时候回合应用程序一起,同时自动启动一个LiveReload服务器。LiveReload服务器本身没有太大的用处。但是当它与LiveReload浏览器插件结合起来的时候,能够在模板、图片、样式表、JavaScript等发生变化的时候自动刷新浏览器。
LiveReload有针对Google Chrome、Safari和Firefox的浏览器插件,但是没有对Internet Explorer和Edge的浏览器。
内置H2控制台
如果你使⽤H2数据库进⾏开发,DevTools将会⾃动启⽤H2。这样的话,可以通过Web浏览器进⾏访问。你只需要让浏览器访问http://localhost:8080/h2-console,就能看到应⽤所使⽤的数据。