【Spring实战】笔记——1.Spring起步
1.1 什么是Spring
**核心:**提供了一个容器(container),通常称为Spring应用上下文(Spring application Context),它们会创建和管理应用组件。
**组件:**这些组件称为bean,会在Spring应用上下文中装配在一起,从而形成一个完整的应用程序。
**装配:**将bean装配在一起的行为是通过一种基于依赖注入(dependency injection,DI)的模式实现的。此时,组件不再去创建它所依赖的组件并管理它们的生命周期,而是使用依赖注入的应用依赖于单独的实体(容器)来创建和维护所有的组件,并将其注入到需要它们的bean中。通常通过构造器参数和属性访问方式来实现。
Spring的装配方式:
-
使用一个或多个XML文件:
<bean id="inventoryService" class="com.example.InventryService"/> <bean id="productService" class="com.example.ProductService"/> <constructor-arg ref="imventoryService"/> </bean>
-
基于Java的配置类:
@Configuration public class ServiceConfiguration { @Bean public InventoryService inventoryService() { return new InventotyService(); } @Bean public ProductService productService() { return new ProductService(inventoryService()); } }
@Configuration 注解会告知Spring这是一个配置类,会为Spring应用上下文提供bean。这个配置类的方法使用**@Bean**注解进行了标注,表明这些方法所返回的对象会以bean的形式添加到Spring的应用上下文中。
-
自动配置
不管是Java配置还是xml配置,只有当Spring不能进行自动配置时才是必要的。
自动配置起源于所谓的自动装配(autowiring)和组件扫描(component scanning)。
- 组件扫描技术:自动发现应用类路径下的组件,并为它们创建成Spring应用上下文中的bean
- 自动装配技术:Spring能够自动为组件注入它们所依赖的其他bean
随着SpringBoot的引入,自动配置的能力已经远远超出了组件扫描和自动装配。
SpringBoot
SpringBoot是Spring框架的扩展,提供了很多增强生产效率的方法。能够基于类路径中的条目、环境变量和其他因素合理猜测需要配置的组件并将它们装配在一起。
1.2 初始化Spring应用
1.2.1 初始化Spring项目
1.创建project,选择Spring Initializr
3.选择依赖,目前只需要这三个,可以从搜索框搜索
1.2.2 检查项目结构
-
**src/main/java:**应用的源码
-
**src/test/java:**测试代码
-
**src/main/resources:**非Java资源
-
mvnw和mvnw.cmd:这是Maven包装器(wrapper)脚本。借助这些脚本,即便你的机器上没有安装Maven,也可以构建项目。
-
pom.xml:Maven构建规范。
-
xxxApplication.java:这是Spring Boot主类,它会启动该项目。
-
application.properties:这个文件起初是空的,但是它为我们提供了指定配置属性的地方。
-
static:在这个文件夹下,你可以存放任意为浏览器提供服务的静态内容(图片、样式表、JavaScript等),该文件夹初始为空。
-
templates:这个文件夹中存放用来渲染内容到浏览器的模板文件
-
xxxApplicationTests.java:这是一个简单的测试类,它能确保Spring应用上下文可以成功加载。
探索构建规范
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.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-
代码第14行:
<packaging>
,选择将应用构建为jar,而不是war。(如果没有这行代码可以自己加上) 通常,传统的Java web应用都是打包成war文件,而jar只是用来打包库和较为少见的桌面UI应用的。
打包为jar文件是基于云思维做出的选择,尽管war文件非常适合部署到传统的Java应用服务器上,但对于大多数云平台来说它们并不是理想的选择。有些云平台也能够部署和运行war文件,但是所有的Java云平台都能够运行可执行的jar文件。
如果想要将应用部署到传统的Java应用服务器上,那么需要选择使用基于war的打包方式并要包含一个web初始化类。(后面会提到)
-
第5行:
<parent>
元素<artifactId>
表明我们的项目要以spring-boot-starter-parent作为其父POM。除了其他的一些功能之外,这个父POM为Spring项目常用的一些库提供了依赖管理。<version>
表明版本。会由这个版本的SpringBoot定义来继承依赖管理。 -
第22行:`````元素声明了几个依赖。
这些依赖的
<artifact ID>
上都有spring-boot-starter。spring-boot-starter依赖的特别之处在于它们本身并不包含库代码,而是传递性地拉取其他的库。这种依赖有3个好处:- 构建文件会显著减小并且更易于管理,因为不必为每个所需的依赖库都
声明依赖 - 我们能够根据它们所提供的功能来思考依赖,而不是根据库的名称。
- 我们不必再担心库版本的问题,你可以直接相信给定版本的SpringBoot,传递性引入的库的版本是兼容的。
- 构建文件会显著减小并且更易于管理,因为不必为每个所需的依赖库都
-
最后,构建规范还包含一个SpringBoot插件。这个插件提供了一些重要的功能:
- 提供了一个Maven goal,允许我们使用Maven来运行应用。
- 会确保依赖的所有库都会包含在可执行的JAR文件中,并且能够保证它们在运行时类路径下是可用的
- 会在JAR中生成一个manifest文件,将引导类声明为可执行的JAR的主类。
引导应用
DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
-
@SpringBootApplication是一个组合注解,它组合了3个其他的注解。
- @SpringBootConfiguration:将该类声明为配置类。
- @EnableAutoConfiguration:启用SpringBoot的自动配置。
- @ComponentScan:启用组件扫描。我们可以通过像@Component、@Controller、@Services这样的注解声明其他类,Spring会自动发现它们并将它们注册为Spring应用上下文中的组件
-
main()方法。这是JAR文件执行的时候要运行的方法。
这个main()方法会调用SpringApplication中静态的run()方法,后者会真正执行应用的引导过程,也就是创建Spring的应用上下文。在传递给run()的两个参数中,一个是配置类,另一个是命令行参数。
测试应用
DemoApplicationTests
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}
1.3 编写Spring应用
为Demo应用添加一个主页:
- 一个控制器类,用来处理主页相关的请求
- 一个视图模板,用来定义主页的内容
- 一个简单的测试类
1.3.1 处理Web请求
Spring自带一个强大的web框架——Spring MVC。
SpringMVC的核心是==控制器(Controller)==理念。控制器是处理请求并以某种方式进行信息响应的类。在面向浏览器的应用中,控制器会填充可选的数据模型,并将请求传递给一个视图,以便于生成返回给浏览器的HTML。
主页控制器:编写一个简单的控制器类以处理对根路径(“/”)的请求,并将请求转发至主页视图。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}
@Controller的主要目的是让组件扫描并将这个类识别为一个组件。Spring的组件扫描功能会自动发现HomeController,并创建一个HomeController实例作为Spring应用上下文中的bean。
home()是一个简单的控制器方法。它带有@GetMapping注解,表明如果针对“/”发送HTTP GET请求,那么这个方法将会处理请求。该方法所做的只是返回String类型的home值。
这个值将会被解析为视图的逻辑名。
1.3.2 定义视图
home.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<h1>Welcome to ...</h1>
<img th:src="@{/image/001.png}" alt="">
</body>
</html>
第9行:<img>
标签使用了Thymeleaf的th:src
属性和@{…}
表达式,以便于引用相对于上下文路径的图片。
图片是相对于上下文的路径来进行引用的。图片这样的静态资源是放到文件夹中的。这意味着图片必须要位于
1.3.3 测试控制器
HomeControllerTest
package com.example.demo;
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 org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHomePage() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/"))
.andExpect(status().isOk())
.andExpect(view().name("home"))
.andExpect(content().string(
containsString("Welcome to...")
));
}
}
22行
mockMvc.perform(MockMvcRequestBuilders.get("/"))
原书为
mockMvc.perform(get(“/”))
,并import import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
,我尝试后不行,所以做出了更改
HomeControllerTest没有使用@SpringBootTest标记,而是使用了@WebMvcTest注解。这是SpringBoot所提供的一个特殊测试注解,会让测试在SpringMVC应用的上下文中执行。
@WebMvcTest同样会为测试SpringMVC应用提供Spring环境的支持。测试类被注入了一个MockMvc,能够让测试实现mockup。
通过testHomePage()方法,我们定义了针对主页想要执行的测试。它首先使用了MockMvc对象对“/”(根路径)发起了HTTP GET请求。对于这个请求,我们设置了如下的预期:
- 响应应该具备HTTP 200 (OK)状态;
- 视图的逻辑名称应该是home;
- 渲染后的视图应该包含文本“Welcome to…”。
推荐阅读
-
【Spring实战】笔记——1.Spring起步
-
1.spring boot起步之Hello World【从零开始学Spring Boot】
-
Spring实战 读书笔记 1.Spring之旅
-
spring微服务实战---zuul笔记
-
微服务架构实战学习笔记 第五章 Spring Cloud Netflix Hystrix与服务容错
-
微服务架构实战学习笔记 第四章 Spring Cloud Netflix Ribbon与负载均衡
-
Spring Cloud 微服务实战笔记
-
微服务架构实战学习笔记 第八章 Spring Cloud Stream与事件驱动
-
Spring实战 读书笔记 1.Spring之旅
-
Spring实战第五版(中文版)学习笔记-第一章 Spring起步