Spring起步
- 什么是Spring
- 初始化Spring应用
- pom文件
- 启动类
- 测试类
- 编写spring应用
- 控制器
- 视图
- 测试
- 了解Spring Boot DevTools
- 回顾
- 俯瞰Spring风景线
- 小结
什么是Spring
组件:任何实际的应用程序都是由很多组件组成的, 每个组件负责整个应用功能的一部分, 这些组件需要与其他的应用元素进行协调以完成自己的任务。 当应用程序运行时, 需要以某种方式创建并引入这些组件。
Spring的核心是提供了一个容器(container),通常称为Spring应用上下文(Spring application context) ,它们会创建和管理应用组件。 这些组件也可以称为bean,会在Spring应用上下文中装配在一起, 从而形成一个完整的应用程序。
将bean装配在一起的行为是通过一种基于依赖注入(dependencyinjection, DI) 的模式实现的。 此时, 组件不会再去创建它所依赖的组件并管理它们的生命周期, 使用依赖注入的应用依赖于容器来创建和维护所有的组件, 并将其注入到需要它们的bean中。
Spring依赖注入的方式:使用XML文件方式和使用注解方式。无论是XML文件还是注解方式,只有当Spring不能进行自动配置的时候才是必要的。
InventoryService bean 和 ProductService bean注入容器, 并且通过构造器参数将InventoryService装配到了
ProductService中。
<bean id="inventoryService" class="com.example.InventoryService" /><bean id="productService" class="com.example.ProductService" /><constructor-arg ref="inventoryService" />
</bean>
使用注解方式,@Configuration告知Spring,这是一个配置类。配置类的方法使用@Bean注解进行了标注, 表明这些方法所返回的对象会以bean的形式添加到Spring的应用上下文中(默认情况下, 这些bean所对应的bean ID与定义它们的方法名称是相同的) 。
@Configuration
public class ServiceConfiguration {@Beanpublic InventoryService inventoryService() {return new InventoryService();} @Beanpublic ProductService productService() {return new ProductService(inventoryService());}
}
Spring的自动配置:自动装配(autowiring) 和组件扫描(component scanning)。借助组件扫描技术, Spring能够自动发现应用类路径下的组件, 并将它们创建成Spring应用上下文中的bean。 借助自动装配技术, Spring能够自动为组件注入它们所依赖的其他bean。
Spring Boot:Spring Boot是Spring框架的扩展, 提供了很多增强生产效率的方法。 最为大家所熟知的增强方法就是自动配置(autoconfiguration),Spring Boot 能够基于类路径中的条目、环境变量
和其他因素合理猜测需要配置的组件并将它们装配在一起。尽可能多地使用Spring Boot, 只有在必要的时候才使用显式配置。 XML是过时的方式,主要关注Spring基于Java的配置。
初始化Spring应用
在IntelliJ IDEA中创建新项目,使用Spring Initializr初始化应用。
src/main/java 下存放的是源代码。src/test/java 存放的是测试代码。src/main/resources 存放的是非Java的资源文件。
pom.xml: 这是Maven构建规范。
mvnw和mvnw.cmd: 这是Maven包装器(wrapper) 脚本。
Chap11Application 是SpringBoot的主类,用于启动该项目。
Chap11ApplicationTests 是一个测试类。
pom文件
在使用Spring Initializr创建项目后,pom.xml文件已经包含了我们所选择的依赖。 Spring Initializr默认会使用基于JAR的打包方式。
<packaging>jar</packaging>
parent标签,指明项目要以spring-boot-starter-parent作为其父POM。 这个父POM为Spring项目常用的一些库提供了
依赖管理, 现在你不需要指定它们的版本, 因为这是通过父POM来管理的。
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version><relativePath/> <!-- lookup parent from repository -->
</parent>
dependency 标签,添加一个依赖。
这 3 个依赖的artifact ID上都有starter这个单词。Spring Boot starter依赖的特别之处在于它们本身并不包含库代码, 而是传递性地拉取其他的库。
这种starter依赖主要有3个好处。
- 构建文件会显著减小并且更易于管理, 因为这样不必为每个所需的依赖库都声明依赖。
- 我们能够根据它们所提供的功能来思考依赖, 而不是根据库的名称。 如果是开发Web应用, 那么你只需要添加web starter就可以了。
- 我们不必再担心库版本的问题。 传递性引入的库的版本是兼容的。 只需要关心使用的是哪个版本的Spring Boot就可以了。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency>
<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>
最后pom.xml中包含一个Spring Boot插件,它提供了一个Maven goal, 允许我们使用Maven来运行应用。它会确保依赖的所有库都会包含在可执行JAR文件中, 并且能够保证它们在运行时类路径下是可用的。它会在JAR中生成一个manifest文件, 将引导类声明为可执行JAR的主类。
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>
启动类
@SpringBootApplication
public class Chap11Application {public static void main(String[] args) {SpringApplication.run(Chap11Application.class, args);}
}
@SpringBootApplication注解明确表明这是一个Spring Boot应用。 但是,@SpringBootApplication远比看上去更强大。@SpringBootApplication是一个组合注解, 它组合了3个其他的注解。
- @SpringBootConfiguration: 将该类声明为配置类。 这个注解实际上是@Configuration注解的特殊形式。
- @EnableAutoConfiguration: 启用Spring Boot的自动配置。 这个注解会告诉Spring Boot自动配置它认为我们会用到的组件。
- @ComponentScan: 启用组件扫描。 能够将@Component、 @Controller、 @Service这样的注解声明其他类,Spring会自动发现它们并将它们注册为Spring应用上下文中的组件。
类中的main()方法会调用SpringApplication中静态的run()方法, 后者会真正执行应用的引导过程, 也就是创建Spring的应用上下文。 在传递给run()的两个参数中, 一个是配置类, 另一个是命令行参数。
测试类
@SpringBootTest
class Chap11ApplicationTests {@Testvoid contextLoads() {}
}
测试是软件开发的重要组成部分。Spring Initializr为我们提供了一个测试类作为起步。
这个类中只有一个空的测试方法。这个测试类会执行必要的检查, 确保Spring应用上下文能够成功加载。 如果你所做的变更导致Spring应用上下文无法创建, 那么这个测试将会失败, 你就可以做出反应来解决相关的问题了。
@SpringBootTest会告诉JUnit在启动测试的时候要添加上SpringBoot的功能。
编写spring应用
在本节应用添加一个主页。
在添加主页时, 我们将会创建两个代码构件:
一个控制器类, 用来处理主页相关的请求;
一个视图模板, 用来定义主页看起来是什么样子。
测试是非常重要的, 所以我们还会编写一个简单的测试类来测试主页。
控制器
处理Web请求
Spring自带了一个强大的Web框架, 名为Spring MVC。 Spring MVC的核心是控制器(controller) 的理念。 控制器是处理请求并以某种方式进行信息响应的类。 在面向浏览器的应用中, 控制器会填充可选的数据模型并将请求传递给一个视图, 以便于生成返回给浏览器的HTML。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class HomeController {@GetMapping("/")public String home() {return "home";}
}
声明一个控制器,用来处理对根路径的请求。
@Controller注解,主要目的是让组件扫描将这个类识别为一个组件。 因为HomeController带有@Controller, 所以Spring的组件扫描功能会自动发现它, 并创建一个HomeController实例作为Spring应用上下文中的bean。
@Component、 @Service和@Repository与@Controller功能相同,但是描述的组件角色不同
@GetMapping(“/”) 表示home方法是针对“/”发送HTTP GET请求, 这个方法将会处理请求。 该方法所做的只是返回String类型的home值。这个值将会被解析为视图的逻辑名。
视图
使用Thymeleaf来创建视图模版:
模板名称是由逻辑视图名派生而来的, 再加上“/templates/”前缀和“.html”后缀。 最终形成的模板路径将是“/templates/home.html”。 需要将模板放到项目 “/src/main/resources/templates/home.html” 目录中。
图片这样的静态资源是放到“/src/main/resources/static”文件夹中的。
<!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>
测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {@Autowiredprivate MockMvc mockMvc;@Testpublic void testHomePage() throws Exception {mockMvc.perform(get("/")).andExpect(status().isOk()).andExpect(view().name("home")).andExpect(content().string(containsString("Welcome to...")));}
}
HomeControllerTest没有使用@SpringBootTest标记, 而是添加了@WebMvcTest注解。 这是Spring Boot所提供的一个特殊测试注解, 它会让这个测试在Spring MVC应用的上下文中执行。 会将HomeController注册到Spring MVC中,这样的话,我们就可以向它发送请求了。@WebMvcTest同样会为测试Spring MVC应用提供Spring环境的支持。
通过testHomePage()方法, 我们定义了针对主页想要执行的测试。
它首先使用MockMvc对象对“/”(根路径) 发起HTTP GET请求。 对于这个请求, 我们设置了如下的预期:响应应该具备HTTP 200 (OK)状态;视图的逻辑名称应该是home;渲染后的视图应该包含文本“Welcome to…”。
在Idea中点击启动类,运行,就可以了,打开浏览器访问 http://localhost:8080,就可以得到运行结果。
了解Spring Boot DevTools
顾名思义, DevTools为Spring开发人员提供了一些便利的开发期工具。
其中包括:
- 代码变更后应用会自动重启;
- 当面向浏览器的资源(如模板、 JavaScript、 样式表) 等发生变化时, 会自动刷新浏览器;
- 自动禁用模板缓存;
- 如果使用H2数据库的话, 内置了H2控制台。
应用自动重启:如果将DevTools作为项目的一部分, 那么你可以看到, 当对项目中的Java代码和属性文件做出修改后, 这些变更稍后就能发挥作用。DevTools会监控变更, 当它看到有变化的时候, 将会自动重启应用。
浏览器自动刷新和禁用模板缓存:在应用运行的时候, 如果缓存模板, 那么我们刷新浏览器就无法看到模板变更的效果了。 即便我们对模板做了修改,在应用重启之前,缓存的模板依然会有效。DevTools通过禁用所有模板缓存解决了这个问题。 你可以对模板进行任意数量的修改, 只需要刷新一下浏览器就能看到结果。
内置的H2控制台:如果你使用H2数据库进行开发, DevTools将会自动启用H2。可以通过Web浏览器进行访问。 你只需要让浏览器访问http://localhost:8080/h2-console, 就能看到应用所使用的数据。
回顾
在构建应用的过程中,执行了以下的步骤:
- 使用Spring Initializr创建初始的项目结构;
- 编写控制器类处理针对主页的请求;
- 定义了一个视图模板来渲染主页;
- 编写了一个简单的测试类来验证工作符合预期。
在pom.xml文件中, 我们声明了对Web和Thymeleaf starter的依赖。这两项依赖会传递引入大量其他的依赖, 包括:Spring的MVC框架;嵌入式的Tomcat;Thymeleaf和Thymeleaf布局方言;
还引入了Spring Boot的自动配置库。 当应用启动的时候, SpringBoot的自动配置将会探测到这些库, 并自动完成如下功能:
- 在Spring应用上下文中配置bean以启用Spring MVC;
- 在Spring应用上下文中配置嵌入式的Tomcat服务器;
- 配置Thymeleaf视图解析器, 以便于使用Thymeleaf模板渲染SpringMVC视图
自动配置功能完成了所有的脏活累活, 让我们能够集中精力编写实现应用功能的代码。
俯瞰Spring风景线
Spring核心框架是Spring领域中的一切基础,提供了核心容器和依赖注入。
Spring MVC:也就是Spring的Web框架,使用Spring MVC来编写控制器类以处理Web请求。Spring核心框架还提供了一些对数据持久化的基础支持, 尤其是基于模板的JDBC支持。 在最新版本的Spring中,还添加了对反应式(reactive)风格编程的支持,其中包括名为Spring WebFlux的新反应式Web框架,这个框架大量借鉴了Spring MVC。
Spring Boot:带来的很多收益, 包括starter依赖和自动配置。 尽可能多地使用Spring Boot, 并避免任何形式的显式配置, 除非显式配置是绝对必要的。
Spring Data:提供了非常令人惊叹的功能: 将应用程序的数据repository定义为简单的Java接口, 在定义驱动存储和检索数据的方法时使用一种命名约定即可。Spring Data能够处理多种不同类型的数据库, 包括关系型数据库(JPA) 、 文档数据库(Mongo) 、 图数据库(Neo4j) 等。
Spring Security:解决了应用程序通用的安全性需求, 包括身份验证、 授权和API安全性。
Spring Integration和Spring Batch:从一定程度上来讲,大多数应用程序都需要与其他应用甚至本应用中的其他组件进行集成。Spring Integration和Spring Batch为基于Spring的应用程序提供了这些模式的实现。Spring Integration解决了实时集成问题。在实时集成中,数据在可用时马上就会得到处理。Spring Batch解决的则是批处理集成的问题,在此过程中,数据可以收集一段时间,直到某个触发器(可能是一个时间触发器)发出信号,表示该处理批量数据了才会对数据进行批处理。
Spring Cloud:应用程序开发领域正在进入一个新的时代, 我们不再将应用程序作为单个部署单元来开发, 而是使用由微服务组成的多个独立部署单元来组合形成应用程序。Spring Cloud是使用Spring开发云原生应用程序的一组项目。
小结
- Spring旨在简化开发人员所面临的挑战, 比如创建Web应用程序、处理数据库、 保护应用程序以及实现微服务。
- Spring Boot构建在Spring之上, 通过简化依赖管理、 自动配置和运行时洞察, 使Spring更加易用。
Spring应用程序可以使用Spring Initializr进行初始化。 SpringInitializr是基于Web的应用, 并且为大多数Java开发环境提供了原生支持。 - 在Spring应用上下文中, 组件(通常称为bean) 既可以使用Java或XML显式声明, 也可以通过组件扫描发现, 还可以使用Spring Boot自动配置功能实现自动化配置。