1.Spring Boot概要
1.1 SpringBoot介绍
随着动态语言的流行(Ruby、Scala、Node.js), Java的开发显得格外的笨重;繁多的配置、低下的开发效率、复杂的部署流程以及第三方技术整合难度大。
在上述环境下,Spring Boot由此诞生,它的设计是为了使您能够尽可能快地启动和运行。它使用 “习惯 优于配置” (项目中存在大量的配置,而 Spring Boot 内置一个习惯性的配置,让你无须手动进行配 置)的理念让你的项目快速运行起来。使用 Spring Boot 很容易创建一个独立运行(运行jar,内嵌 Servlet 容器)、准生产强力的基于 Spring 框架的项目,使用 Spring Boot你可以不用或者只需要很少 的 Spring 配置。提供了 J2EE 开发的一站式解决方案。 2014 年 4 月,Spring Boot 1.0.0 发布。Spring的顶级项目之一(https://spring.io)。
1.2 SpringBoot优点
①创建独立Spring应用
②内嵌web服务器
③自动starter依赖,简化构建配置;起步依赖 ,起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM), 定义了对其他库的传递依赖 ,这些东西加在一起即支持某项功能。 简单的说,起步依赖就是 将具备某种功能的坐标打包到一起,并提供一些默认的功能
④自动配置Spring以及第三方功能
⑤提供生产级别的监控、健康检查及外部化配置
⑥无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架,SpringBoot是简化Spring技术栈的快速开发脚手架,Spring Boot 并不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式
1.3 SpringBoot缺点
①人称版本帝,迭代快,需要时刻关注变化
②封装太深,内部原理复杂,不容易精通
2.Spring Boot 核心配置
2.1 环境要求
java version "1.8.0_181"
Maven-3.6.1
SpringBoot 2.x 最新版
2.2 Spring Boot配置文件分类
SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yaml)进行配置
⚪application.properties语法结构:
key=value
⚪application.yml语法结构:
key: 空格 value(冒号后面必须要有空格)
⚪SpringBoot提供了2种配置文件类型:properteis和yml/yaml
⚪默认配置文件名称:application
⚪在同一级目录入如果三类文件共存,优先级为:properties > yml > yaml
2.3 YML基础语法
YML语法规定
1. 大小写敏感
2. 数据值前边必须有空格,作为分隔符
3. 严格使用缩进表示层级关系
4. 缩进时不允许使用Tab键,只允许使用空格(各个系统 Tab对应的 空格数目可能不同,导致层次混 乱)。
5. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
6. "#"表示注释,从这个字符一直到行尾,都会被解析器忽略。
YML的数据格式
字面量:普通的值 [ 数字,布尔值,字符串 ]
数组:一组按次序排列的值( List、set )
对象、Map(键值对)
YAML:参数引用
2.4 读取配置内容
yaml文件更强大的地方在于,他可以给我们的实体类直接注入匹配值.支持单个注入和批量注入。
批量注入:1.@ConfigurationProperties
2.Environment类
逐个注入
语法
逐个注入:@Value
实例
//写法1:直接传值,不使用yml配置文件
@Component
public class Dog {
@Value("大黄")
private String dname;
@Value("8")
private int dage;
@Override
public String toString() {
return "Dog{" +
"dname='" + dname + '\'' +
", dage=" + dage +
'}';
}
public Dog() {
}
public Dog(String dname, int dage) {
this.dname = dname;
this.dage = dage;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public int getDage() {
return dage;
}
public void setDage(int dage) {
this.dage = dage;
}
}
运行结果:Dog{dname='大黄', dage=8}
//写法2:通过yml配置文件传值
@Component
public class Dog {
@Value("${dname}")
private String name;
@Value("${dage}")
private Integer age;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
//yml配置文件
dname: 团团
dage: 10
运行结果:Dog{name='团团', age=10}
批量注入
//编写一个复杂一点的实体类:Person 类
//使用:@ConfigurationProperties(prefix = "persons")注解,prefix为我们要加载的yml文件中的配置内容
@Component
@ConfigurationProperties(prefix = "persons")
public class Person {
private String name;
private String email;
private int age;
private Date birthday;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
//getter setter 构造方法 toString方法。。。
}
//yml文件
persons:
last-name: 王
name: 王老师
email: 12345678@qq.com
age: 50
marry: true
birth: 1990/10/19
maps: {k1: v1,k2: v2}
lists:
- code
- bodybuilding
- music
dog:
name: summer
age: 1
//测试类
@SpringBootTest
class SpringbootInit01ApplicationTests {
@Autowired
Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
对比
@Value这个使用起来并不友好!我们需要为每个属性单独注解赋值,比较麻烦;我们来看个功能对比 图
1、@ConfigurationProperties只需要写一次即可 , @Value则需要每个字段都添加
2、松散绑定:这个什么意思呢? 比如我的yml中写的last-name,这个和lastName是一样的, - 后面跟 着的字母默认是大写的。这就是松散绑定。可以测试一下
3、JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法
4、复杂类型封装,yml中可以封装对象 , 使用value就不支持
结论:
配置yml和配置properties都可以获取到值 , 强烈推荐 yml;
如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties,不要犹豫!
JSR303数据校验
对于 web 服务来说,为防止非法参数对业务造成影响,在 Controller 层一定要做参数校验的!大部分 情况下,请求参数分为如下两种形式:
1. POST 、 PUT 请求,使用 requestBody 传递参数; 2. GET 请求,使用 requestParam/PathVariable 传递参数。
什么是 JSR303 标准?
JSR的全称是Java Specification Requests(Java 规范提案),是指向JCP ( Java Community Process )提出新增一个标准化技术规范的正式请求。 Java API 规范( JSR303 )定义了 Bean 校验的标准 validation-api ,但没有提供实现。 hibernate validation 是对这个规范的实现,并增加了校验注解如 @Email 、 @Length 等。 Spring Validation 是对 hibernate validation 的二次封装,用于支持 spring mvc 参数自动校验。接下 来,我们以 spring-boot 项目为例,介绍 Spring Validation 的使用
JSR303校验注解的使用步骤
1.添加依赖,导入spring-boot-starter-validation启动器
<!--jsr303数据验证-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2.在实体类需要校验的成员字段(Field)上,添加校验注解。并在Controller控制器的校验参数前,使用@Valid注解开启校验
@Component //注册bean到容器中
@ConfigurationProperties(prefix = "persons")
@Validated
public class Person {
private String lastName;
@Email(message = "邮箱格式不正确")
private String email;
@NotNull(message = "用户名称不能为空")
private String name;
@NotNull(message = "用户年龄不能为空")
@Max(value = 150,message = "给年轻人留点机会吧")
private int age;
private boolean marry;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
3.在Controller控制器的校验参数前,使用@Valid注解开启校验,使用BindingResult 绑定校验结果
验证方式一:
在yml文件中的数据必须符合刚刚我们定义的要求,如果不符合则报错,例如下面我们使用错误的邮箱格式:
结果:
验证方式二:
输入错误的邮箱格式(http://localhost:8081/demo01/dosave?lastName=王&email=123456&name=王老师&age=34&marry=true)
@Controller
public class UserController {
//用户发送请求:
//http://localhost:8081/demo01/dosave?lastName=王&email=123456@qq.com&name=王老师
&age=34&marry=true
//springMVC框架通过方法的参数进行请求中数据的获取,命名一直类型合法就可以接受到请求中的数据
@RequestMapping(path = "/dosave")
@ResponseBody
public String dosave(@Valid Person person, BindingResult result){
//得到所有错误信息计数
int errorCount = result.getErrorCount();
//错误数大于0
if (errorCount>0){
//得到所有错误
List<FieldError> fieldErrors = result.getFieldErrors();
//迭代错误
for (FieldError fieldError:fieldErrors) {
//错误信息
System.out.println( "属性:{},"+fieldError.getField()+"传来的值是:{}"+fieldError.getRejectedValue()+",出错的提示消息:{}"+fieldError.getDefaultMessage());
}
return "数据不合法";
}else{
return "数据合法";
}
}
但是当有多个类需要绑定校验结果时就要写多个BindingResult ,会导致数据冗余,所以我们可以使用全局异常处理器:
@ControllerAdvice //全局异常处理器
public class UserController {
//BindException:异常类型
@ExceptionHandler(BindException.class)
@ResponseBody
public String show(BindException e){
return "数据不合法(全局异常处理器)";
}
@RequestMapping(path = "/dosave")
@ResponseBody
public String dosave(@Valid Person person){
System.out.println(person);
return "数据合法";
}
运行结果: