学习 Spring 实战第5版:spring起步

目录:spring-in-action-5-目录下一节: spring-in-action-5-编写基础类和design功能

这节是第一课,我将使用IDEA来初始化Spring Boot项目

Spring注解

Spring应用上下文使用bean作为其基本单位。

过去,spring使用xml文件来实现bean的装配,现在spring提倡使用于xml文件等价的Java配置类来完成相同工作。

1
2
3
4
5
6
7
<bean id="inventoryService"
class="com.example.InventoryService"/>

<bean id="productService"
class="com.example.ProductService"/>
<constructour-arg ref="inventoryService"/>
</bean>

等价的Java配置类,使用@Configuration注解来告知Spring这是一个配置类。会在Spring上下文中提供bean

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class ServiceConfiguration{
@Bean
public InventoryService inventoryService(){
return new InventoryService();
}

@Bean
public ProductService productService(){
return new ProductService(inventoryService());
}
}

同时基于Java的配置会带来多项收益。

  • 更强的类型安全性
  • 更好的重构能力

只有当Spring不能进行自动配置的时候,上面的两种操作才是必要的。

自动配置

spring的自动配置起源于自动装配(autowiring)和组件扫描(component scanning)。见:spring-in-action-4-装配bean

使用组件扫描技术,Spring能够自动发现应用类路径下的组件,并将它们创建成Spring应用上下文中的bean。

使用自动装配技术,Spring能够自动为组件注入它们所依赖的其他bean。

Spring Boot

Spring Boot提供了更强的自动配置能力。它使用了增强方法自动配置(autoconfiguration)

Spring Boot能够基于类路径中的条目,环境变量,以及其他因素,合理猜测需要配置的组件并将它们装配在一起。

@SpringBootApplication组合注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

package com.zyj.tacocloud;

import com.zyj.tacocloud.Ingredient.Type;
import com.zyj.tacocloud.data.IngredientRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

/**
* SpringBootApplication SpringBoot应用
* '@SpringBootApplication' 这个注解包含了三个注解
* 用来声明该类为配置类
* 启用SpringBoot的自动配置
* 启用组件扫描
*
* @author ZYJ
*/
@SpringBootApplication
public class TacoCloudApplication {

public static void main(String[] args) {
/*
应用运行
左侧参数是配置类
右侧参数是命令行传递参数
*/
SpringApplication.run(TacoCloudApplication.class, args);
}


}

@SpringBootApplication是一个组合注解,它组合了其他3个注解:

  • @SpringBootConfiguration:将该类声明为配置类。这样我们可以按需添加基于Java的Spring框架配置。其本质上是@Configuration注解的特殊形式。
  • @EnableAutoConfiguration:启用Spring Boot的自动配置。这个注解告诉Spring Boot自动配置它认为我们会用到的组件 。
  • @ComponentScan:启用组件扫描.这样我们就可以对其他类使用@Component``@Controller``@Service这样的注解.Spring会自动发现它们,并将它们注册为Spring应用上下文中的组件

SpringBoot Application类

作为整个Spring Boot的应用启动类。其包深(package depth)必须要等于会低于其他所有类。不要把启动类放在过深的包里,这会影响Spring Boot的正常启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

package com.zyj.tacocloud;

import com.zyj.tacocloud.Ingredient.Type;
import com.zyj.tacocloud.data.IngredientRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

/**
* SpringBootApplication SpringBoot应用
* '@SpringBootApplication' 这个注解包含了三个注解
* 用来声明该类为配置类
* 启用SpringBoot的自动配置
* 启用组件扫描
*
* @author ZYJ
*/
@SpringBootApplication
public class TacoCloudApplication {

public static void main(String[] args) {
/*
应用运行
左侧参数是配置类
右侧参数是命令行传递参数
*/
SpringApplication.run(TacoCloudApplication.class, args);
}


}

启动类实际上可以通过extends配置类的方式,在其中配置Spring Boot的一些运行中配置,但是不建议这么做。

如果你有时间,还是新建一个专门的配置类,完成某一项功能的专门配置为好。

@Controller注解

@Controller注解使得组件扫描将这个类识别为一个组件,这样会创建一个实例作为Spring应用上下文中的bean。

1
2
3
4
5
6
7
8
9
10
package com.zyj.tacocloud.web;  
/**
* @author ZYJ
*/

@Controller
public class DesignTacoController {
...

}

其他类似目的的注解还有:

  • @Component
  • @Service
  • @Repository

@<menthond>Mapping注解

这包括@GetMapping注解、@PostMapping注解等。它们的作用是向指定视图发送对应的HTPP method请求,比如GET请求,POST请求等等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.zyj.tacocloud;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
* @author ZYJ
*/
@Controller
public class HomeController {


/**
* 表明针对“/”发送 http get 请求
* @author zyj
*/
@GetMapping("/")
public String home() {
//返回视图名
return "home";
}

public String getHomeMapName() {
return home;
}
}


使用@GetMapping注解,表明这个方法将处理请求,并且返回一个String类型的视图名称。

@SpringBootTest注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.zyj.tacocloud;

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注解,是junit4中提供的,提供一个测试运行器 runner,本例中是使用Spring提供的SpringRunner.class
* 它是Soring提供的测试运行器,创建测试所需的Spring上下文
*/
@RunWith(SpringRunner.class)
@SpringBootTest
class TacoCloudApplicationTests {

@Test
void contextLoads() {
}

}

@WebMvcTest注解

它提供比@SpringBootTest粒度更小的测试。

这是Spring Boot提供的一个特殊测试注解。它会让这个测试在Spring Mvc应用的上下文中执行。

它会为Spring MVC应用提供Spring环境的支持。

一般用于,我们需要仿造Spring MVC的运行机制,在其中进行一些测试。

测试类可以注入一个MockMvc,让测试实现mockup。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.zyj.tacocloud.controller;

import com.zyj.tacocloud.HomeController;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;

/**
* 测试web应用
* 针对 HomeController 的 Web 测试
*/
@WebMvcTest(HomeController.class)
class HomeControllerTest {

@BeforeEach
void setUp() {
}

@AfterEach
void tearDown() {
}

//注入MockMvc
@Autowired
private MockMvc mockMvc;

@Test
void home() {
}

@Test
void getHomeMapName() {
}

@Test
public void testHomePage() throws Exception {
// 发起对 "/" 的 GET
mockMvc.perform(get("/"))
// 期望得到HTTP 200
.andExpect(status().isOk())
// 期望得到 home 视图
.andExpect(view().name("home"))
// 期望包含 “Welcome to ...”
.andExpect(content().string(containsString("Welcome to ...")));
}
}

Spring Boot DevTools

DevTools为Spring开发人员提供了一些便利的工具。

  • 代码变更后后,应用会自动重启。
  • 当面向浏览器的资源(模板、JavaScript、样式表)等发生变化时,会自动刷新浏览器。
  • 自动禁用模板缓存
  • 如果使用H2数据库,会内置H2控制台

使用某些模板方案,如Thymeleaf、FreeMarker,会缓存模板解析的结果。这样的话,为每个请求提供服务的时候,模板就不用重新解析了。

生产环境中,这是一种很好的特性,会带来一定的性能收益。但在开发环境中,我们最好禁用它,因为不禁用会导致,即使我们手动刷新浏览器,也无法看到模板变更过的效果。

效果等同于自己配置:
Pasted image 20210203145525.png

DevTools会在运行的时候,自动启动LiveReload服务器。当你浏览器安装LiveReload浏览器插件后,会在模板、图片、样式表、JavaScript等发生变化的时候自动刷新浏览器。

课后作业

模仿前面要求,实际动手来初始化一个Spring Boot项目

见:spring-in-action-5-spring起步-课后作业