Docker 实战

安装 Docker

1
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
阅读全文

SpringBoot 参数校验

准备工作

引入相关依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Bean Validation 中的约束

约束 说明
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式

Hibernate Validator 附加的约束

约束 说明
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内

代码中校验

spring 中可以直接从 aop 容器中获取

1
2
@Autowired
private Validator validator;

通过工厂方法获取

1
2
3
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<DemoDTO>> violations = validator.validate(dto);

@Validated 与@Valid 的简单对比说明

@Valid 注解与@Validated 注解功能大部分类似;两者的不同主要在于:

  • @Valid 属于 javax 下的,而@Validated 属于 Spring 下
  • @Valid 支持嵌套校验,而@Validated 不支持
  • @Validated 支持分组,而@Valid 不支持

普通方法校验参数

除了验证接口,我们还可以验证普通的方法,首先在需要验证的方法所在类上面增加注解 @Validated

1
2
3
4
5
6
@Validated
@Service
public class DemoService {
public void demo(@Valid DemoDTO dto) {
}
}

注意:

  • 基于 aop 机制,被验证的方法需要注册为组件
  • 只能在类上面增加注解@Validated,不能在单个方法上
  • 抛出的异常为 ConstraintViolationException,需要单独拦截,示例:
1
2
3
4
5
6
7
8
9
10
@ResponseBody
@ExceptionHandler(ConstraintViolationException.class)
public HttpResponse handle(ConstraintViolationException e) {
return HttpResponse.builder().code(500).msg(
e.getConstraintViolations()
.stream()
.findFirst()
.map(ConstraintViolation::getMessage)
.orElse("参数校验失败")).build();
}

嵌套验证

当我们要验证的类 DemoBO 有成员属性为 OtherObject,对 OtherObject 中的属性进行校验,需要在 DemoBO 的成员属性 OtherObject 之上加上 @Valid

1
2
3
4
5
6
@Data
public class DemoBO {

@Valid
private OtherObject otherObject;
}

分组校验

在很多时候,同一个模型可能会在多处被用到,但每处的校验场景又不一定相同(如:新增用户接口、修改用户接口,参数都是 User 模型,在新增时 User 中 name 字段不能为空,userNo 字段可以为空;在修改时 User 中 name 字段可以为空,userNo 字段不能为空)。我们可以用 groups 来实现:同一个模型在不同场景下,(动态区分)校验模型中的不同字段。

创建分组 Create 和 Update 继承 Default

继承 Default 并不是必须的。只是说,如果继承了 Default,那么@Validated(value = Create.class)的校验范畴就为【Create】和【Default】;如果没继承 Default,那么@Validated(value = Create.class)的校验范畴只为【Create】,而@Validated(value = {Create.class, Default.class})的校验范畴才为【Create】【Default】。

Default 组和无参构造机制类似,当没有指定分组时,会默认当前校验属于 Default 组,但是一旦主动给当前校验指定
了分组(如上图中的 name 字段,主动指定了属于 Create 组),那么就不会再额外指定属于 Default 组了。
当然,也可以画蛇添足的主动指定所属分组为 Default。

1
2
3
import javax.validation.groups.Default;

public interface Create extends Default{}
1
2
3
import javax.validation.groups.Default;

public interface Update extends Default{}

创建实体类 Student

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

@Data
public class Student{

@NotNull(groups=Update.class)
private Long id;

@NotEmpty(groups=Create.class)
private String name;

@NotEmpty
private Integer age;

@NotEmpty(groups=Default.class) // 等价于 @NotEmpty
private Integer gender;
}

maven多仓库配置 - 公司仓库与阿里云仓库共存

以下操作在 maven 配置文件 settings.xml 中修改

配置公司账户信息 server

1
2
3
4
5
6
7
<servers>
<server>
<id>nexus</id>
<username>xxx</username>
<password>xxx</password>
</server>
</servers>

删除掉原来的 mirror

1
2
<mirrors>
</mirrors>

配置公司和阿里云 profile

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
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>nexus-pub</id>
<name>private-nexus</name>
<url>http://192.168.50.1:8899/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus-pub</id>
<name>private nexus</name>
<url>http://192.168.50.1:8899/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>aliyun</id>
<repositories>
<repository>
<id>central</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>

配置 activeProfiles

1
2
3
4
<activeProfiles>
<activeProfile>nexus</activeProfile>
<activeProfile>aliyun</activeProfile>
</activeProfiles>

Java8 Stream API

概述

Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

阅读全文