Spring实战学习笔记 —— 1.Spring起步与开发web应用
1. Spring起步
1.1 什么是Spring
Spring的核心是提供了一个容器,通常称为Spring应用上下文(Spring Application Context),它们会创建和管理应用组件。这些组件也可以称为Bean,会在Spring应用上下文中装配在一起,从而形成一个完整的应用程序。
依赖注入(Dependency Injection,DI)
将bean装配在一起的行为。组件不会再去创建它所依赖的组件并管理它们的生命周期,使用依赖注入的应用依赖于单独的实体来创建和维护所有的组件,并将其注入到需要它们的bean中。
@configuration 注解会告知Spring这是一个配置类,会为Spring应用上下文提供bean。
相对于基于XML的配置方式,基于java配置提供了更强的类型安全性和更好的重构能力。
自动装配(autowiring)和 组件扫描(Component Scanning)
借助组件扫描技术,Spring能够自动发现应用类路径下的组件,并将它们创建成Spring应用上下文中的bean。
借助自动装配技术,Spring能够自动为组件注入他们所依赖的其他bean。
自动配置(autoconfiguration)
SpringBoot能够基于类路径中的条目、环境变量和其他因素合理猜测需要配置的组件并将它们装配在一起。
1.2 初始化Spring应用
方式很多,笔记不展示了,仅记录个人学习关键位置。
1.2.1 启动类
@SpringBootApplication 是一个组合注解,组合了3个其他的注解:
- @SpringBootConfiguration:将该类声明为配置类。@configuration 注解的特殊形式;
- @EnableAutoConfiguration: 启用Spring Boot的自动装配。告诉SpringBoot自动配置它认为我们会用到的组件;
- @ComponentScan: 启用组件扫描。这样Spring会自动发现如@Component、@Controller、@Service等注解声明的其他类,并注册为Spring应用上下文中的组件。
SpringApplication.run(Class<?> primarySource, String… args)
真正执行应用的引导过程,也是创建Spring应用上下文。primarySource是配置类,args是命令行参数。
1.2.2 测试类
@RunWith(SpringRunner.class)
是JUnit注解,提供一个测试运行器来指导JUnit如何运行测试。SpringRunner是Spring提供的测试运行器,它会创建测试运行所需的Spring应用上下文。
@SpringBootTest
会告诉JUnit在启动测试的时候要添加上SpringBoot的功能。
@WebMvcTest(Class.class)
会让这个测试在Spring MVC应用的上下文中执行。为测试Spring MVC应用提供Spring环境的支持。
1.2.3 处理Web请求
Spring MVC的核心是控制器的理念。控制器是处理请求并以某种方式进行信息响应的类。在面向浏览器的应用中,控制器会填充可选的数据模型并将请求传递给一个视图,以便生成返回给浏览器的HTML。
1.2.4 了解Spring Boot DevTools
DevTools为Spring开发人员提供了一些便利的开发工具,如:
- 代码变更后自动重启;
- 当面向浏览器的资源等发生变化时,自动刷新浏览器;
- 自动禁用模板缓存;
- 如使用H2数据库的话,内置了H2控制台。
DevTools运行的时候,应用程序会被加载到Java虚拟机两个独立的类加载器中。其中一个类加载器会加载你的Java代码、属性文件以及项目中“src/main/”路径下几乎所有的内容。这些条目很可能会经常发生变化。另外一个类加载器会加载依赖的库,这些库不太可能经常发生变化。
当探测到变更的时候,DevTools只会重新加载包含项目代码的类加载器,并重启Spring的应用上下文,在这个过程中另外一个类加载器和JVM会原封不动。
这种策略的一个不足之处是自动重启无法反映依赖项的变化。
1.2.5 回顾
只关注满足应用需求的代码,无须考虑如何满足框架的需求,可以视为感受不到框架的框架。
在pom.xml中,我们声明了对Web和Thymeleaf starter的依赖,会自动引导引入大量其他的依赖,如:
- Spring MVC;
- 嵌入式Tomcat;
- Thymeleaf和Thymeleaf布局方言。
他还引入了SpringBoot的自动配置库。当应用启动时,SpringBoot的自动配置将会探测到这些库,并自动完成如下功能: - 在Spring应用上下文中配置bean以启用Spring MVC;
- 在Spring应用上下文中配置嵌入式的Tomcat;
- 配置Thymeleaf视图解析器,以便于使用Thymeleaf模板渲染Spring MVC视图。
1.3 小结
- Spring旨在简化开发人员所面临的挑战,比如创建Web应用程序、处理数据库、保护应用程序以及实现微服务;
- SpringBoot构建在Spring之上,通过简化依赖注入、自动配置和运行时洞察。使Spring更加易用;
- Spring应用程序可以使用Spring Initializr进行初始化;
- 在Spring应用上下文中,组件(通常称为bean)既可以使用Java或xml显示声明,也可以通过组件扫描发现,还可以使用SpringBoot自动配置功能实现自动化配置。
2.开发web应用
对于Thymeleaf和基本项目结构不做过多阐述。
2.1 校验表单输入
Spring支持Java的bean校验API,Validation API(JSR-303与JSR-349标准)以及Validation API的Hibernate实现将会作为Spring Boot web starter的传递性依赖自动添加到项目中。
要在Spring MVC上应用校验,我们需要:
- 在要被校验的类上声明校验规则;
- 在控制器方法中声明要进行校验;
- 修改表单视图以展示校验错误。
2.1.1 声明校验规则
在实体类字段上进行注解声明
// 仅取部分作为展示,支持内容可自行寻找查阅
public class Order {
// 非空校验
@NotBlank(message = "Name is required")
private String name;
// 非null校验
@NotNull
private Long userId;
// 信用卡号校验
@CreditCardNumber(message = "ccNumber is wrong")
private String ccNumber;
// 正则校验
@Pattern(regexp = "^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$", message = "...")
private String ccExpiration
// 数字校验
@Digits(integer = 3, fraction = 0, message = "...")
private String ccCVV;
}
2.1.2 在绑定表单的时候进行校验
在控制器使用Java Bean Validation API的@Valid注解,校验时机是在绑定完表单数据之后,调用控制器方法之前。
@Controller
@RequestMapping("/order")
public class OrderController {
@PostMapping
public String creatOrder(@Valid Order order, Errors errors) {
if (errors.hasErrors())
// 返回原页面
return "order";
// 进入下一个页面
return "rediract:/order/next"
}
}
2.1.3 展现校验错误
Thymeleaf提供了便捷访问Errors对象的方法,借助fields及其th:errors属性。
<label for="ccNumber">Credit Card #:</label>
<input type="text" th:field="*{ccNumber}"/>
<span class="validationError" th:if="${#fields.hasErrors('ccNumber')}" th:errors="*{ccNumber}">CC Num Error</span>
2.2 使用视图控制器
除了通过@Controller声明控制器外,如果一个控制器非常简单,不需要填充模型或处理输入,那么还可以使用视图控制器:只将请求转发到视图而不做其他事情的控制器。
@Configuration
public class MyWebConfig implements WebMvcConfiguration {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
}
也可以使用Application启动类实现WebMvcConfiguration接口,采用扩展已有配置类的方式避免创建新类。
2.3 缓存模板
如要禁用Thymeleaf缓存,可以在application.properties添加:spring.thymeleaf.cache=false,正式环境需要开启。