[TOC]
1 函数式编程
2 流式编程
3 资源关闭
3.1 垃圾回收(GC)的特点
3.2 常见需手动释放的物理资源
3.3 物理资源可以不手动释放吗?
资源被长时间无效占用
超过最大限制后,将无资源可用
导致系统无法正常运行
3.4 传统方式关闭流资源
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 58 59 60 61 62 63
|
public class FileCopyTest {
@Test public void copyFile() {
String originalUrl = "lib/FileCopyTest.java"; String targetUrl = "targetTest/target.txt";
FileInputStream originalFileInputStream = null; FileOutputStream targetFileOutputStream = null;
try { originalFileInputStream = new FileInputStream(originalUrl);
targetFileOutputStream = new FileOutputStream(targetUrl);
int content;
while ((content = originalFileInputStream.read()) != -1) { targetFileOutputStream.write(content); }
} catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally {
if (targetFileOutputStream != null) { try { targetFileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (originalFileInputStream != null) { try { originalFileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
}
}
|
3.5 TWR方式关闭流资源
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
| public class NewFileCopyTest {
@Test public void copyFile() {
// 先定义输入/输出路径 String originalUrl = "lib/NewFileCopyTest.java"; String targetUrl = "targetTest/new.txt";
// 初始化输入/输出流对象 try ( FileInputStream originalFileInputStream = new FileInputStream(originalUrl);
FileOutputStream targetFileOutputStream = new FileOutputStream(targetUrl); ) {
int content;
// 迭代,拷贝数据 while ((content = originalFileInputStream.read()) != -1) { targetFileOutputStream.write(content); }
} catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
}
}
|
3.6 TWR简介
try-with-resource
Java7引入新特性
优雅关闭资源
一种java语法糖
3.7 TWR使用
多资源自动关闭
实现AutoCloseable接口
避免异常屏蔽
3.8 资源关闭顺序问题
3.9 资源关闭特殊情况
4 工具集
4.1 Guava简介
背靠Google好乘凉,Guava工程包含了若干被Google的Java项目广泛依赖的核心库,例如:集合,缓存,原生类型支持,并发库,通用注解,字符串处理,I/O等等。
所有这些工具每天都在被Google的工程师应用在产品中。
4.2 使用和避免null
大多数情况下,使用null表明的是某种缺失情况。
Guava引入Optional<T>
表明可能为null的T类型引用。Optional实例可能包含非null的引用(引用存在),也可能什么也不包括(引用缺失)。
正是受到Guava的启发,Java8将Optional类作为一个新特性引入到Java8的类库。
4.3 实战案例:Java8新特性Optional
4.4 不可变集合
创建对象的不可变拷贝是一项很好的防御性编程技巧
Guava为所有的JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本。
不可变对象的优点

4.5 新集合类型
4.6 实战:新集合类型使用
4.7 集合工具类
4.8 实战:IO流工具类的使用
4.9 总结
5 线程池
6 实用工具
6.1 Lombok简介
Project Lombok
是一个Java库,可以自动插入编辑器并构建工具,为Java增添色彩。永远不要再写另一个getter或equals方法,使用一个注释,您的类具有一个功能齐全的构建器,自动化您的日志记录变量。
–Lombok官网
6.2 Lombok实现原理
注解的两种解析方式
编译时解析的两种机制
- Annotation Processing Tool(注解处理器)—-JDK1.8去除
- Pluggable Annotation Processing API(JSR269插入式注解处理器)

6.3 Lombok插件安装
IDEA–>setting–>plugins–>搜索lombok安装即可
6.4 Lombok常用注解使用
实战:演示Lombok注解使用方式,并通过查看编译后class文件,理解其工作原理
https://www.cnblogs.com/ooo0/p/12448096.html
https://www.cnblogs.com/muxi0407/p/11611885.html

1.@Data注解
一种大而全的注解:包含@Getter,@Setter,@ToString,@EqualsAndHashCode,@NoArgsConstructor
2.@Val注解
弱语言变量,作用范围是本地方法
https://blog.csdn.net/cauchy6317/article/details/102851120
3.@NotNull注解:生成非空的检查
4.@Builder注解:简化对象创建过程
5.@Singular注解:配合@Builder注解,简化集合类型操作
6.5 Lombok优缺点
lombok虽然可以极大的提高我们的开发效率,但却降低了源代码的可读性和完整性,也加大了对问题排查的难度
7 验证框架
7.1 分层验证与JavaBean验证
分层验证模型

JavaBean验证

Bean Validation简介
Bean Validation为JavaBean验证定义了相应的元数据模型和API
JCP,JSR简介
JCP(Java Community Process)成立于1998年,是使有兴趣的各方参与定义Java的特性和未来版本的正式过程
JCP使用JSR(Java规范请求,Java Specification Requests)作为正式规范文档,描述被提议加入到Java体系中的规范和技术。
JSR303,Bean Validation 1.0
JSR349,Bean Validation 1.1
JSR380,Bean Validation 2.0
Bean Validation与Hibernate Validator
Bean Validation 1.0参考实现:Hibernate Validator 4.3.1.Final
Bean Validation 1.1参考实现:Hibernate Validator 5.1.1.Final
Bean Validation 2.0参考实现:Hibernate Validator 6.0.1.Final
常用约束注解
- 空值校验类:@Null,@NotNull,@NotEmpty,@NotBlank等
- 范围校验类:@Min,@Size,@Digits,@Future,@Negative等
- 其他校验类:@Email,@URL,@AssertTrue,@Pattern等
@NotBlank 用于 String 判断空格
@NotEmpty 用于集合
@NotNull 用在基本类型上
注解 |
描述 |
@AssertFalse |
被注释的元素必须为 false |
@AssertTrue |
同@AssertFalse |
@DecimalMax |
被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin |
同DecimalMax |
@Digits |
被注释的元素是数字 |
@Future |
将来的日期 |
@Max |
被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Min |
被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@NotNull |
不能是Null |
@Null |
元素是Null |
@Past |
被注释的元素必须是一个过去的日期 |
@Pattern |
被注释的元素必须符合指定的正则表达式 |
@Szie |
被注释的元素必须在指定长度内 |
@Email |
元素必须是格式良好的电子邮箱地址 |
@Length |
字符串的大小必须在指定的范围内,有min和max参数 |
@NotEmpty |
字符串的不能是空 |
@NotBlank |
字符串不能使空,但是与@NotEmpty不同的是尾随的空白被忽略 |
@URL |
字符串必须是一个URL |
8-5 案例演示框架搭建 (05:13)
引入pom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.16.Final</version> </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.6</version> </dependency>
|
简单的使用,还是以Person实体类为例(大家在尝试时最好在web项目上,毕竟这个功能基本也都在web上才用得到。非web项目可能会出现一些错误,这时候就要引入el依赖):
1 2 3 4 5 6 7 8 9 10 11
| @Data @AllArgsConstructor public class Person { @NotNull(message = "用户名不能为空") @Size(min = 2,max = 15) private String name; @NotNull private int age; @NotNull(message = "性别不能为空") private String gender; }
|
1 2 3 4 5 6
| private static Validator validator=Validation.buildDefaultValidatorFactory().getValidator(); public static void main(String[] args) { Person person=new Person("",15,"男"); Set<ConstraintViolation<Person>> validate = validator.validate(person); validate.forEach(item ->System.out.println(item.getMessage())); }
|
7.2 完成验证的步骤
- 约束注解的定义
- 约束验证规则(结束验证器)
- 约束注解的声明
- 约束验证流程
7.3 测试案例
自定义手机号约束注解
- 定义@interface Phone注解
- 实现约束验证器PhoneValidator.java
- 声明@Phone约束验证
- 执行手机号约束验证流程
8 常用工具
开发常用工具总结:https://liuurick.github.io/2021/04/18/%E5%BC%80%E5%8F%91%E5%B8%B8%E7%94%A8%E5%B7%A5%E5%85%B7%E6%80%BB%E7%BB%93/
开发工具
自测工具
检查工具
9 综合实战
整合一下,搭建通用型基础组件
- 集成MyBatis-plus实现数据持久化
- 集成CaffeineCache(GuavaCache替代品)实现本地缓存
- 集成Lombok注解
- 集成校验框架实现自动/手动数据校验
- 实现统一异常处理
- 集成Guava令牌桶实现全局限流器
- 使用线程池实现任务异步处理
- 使用TWR实现文件关闭
- 集成EasyExcel实现Excel异步导出
- 实现VO/DTO/DO实现代码分层
- 使用Stream实现集合操作
- 集成Swagger2实现接口文档自动生成
- 使用TraceId实现系统请求追踪
引入依赖
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| <dependencies>
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.6</version> </dependency> <dependency> <groupId>org.ow2.asm</groupId> <artifactId>asm-all</artifactId> <version>5.2</version> </dependency>
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>28.0-jre</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1</version> </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-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <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>
|
集成Mybatis Plus步骤
- 在pom.xml文件引入相关的jar包依赖
- 实现XxxMapper接口。通过此接口来操作数据持久化
- 对XxxDO实体进行注解的定义,如:数据库表名,字段的定义
- 如需修改Plus默认配置,需实现MybatisPlusConfig类
- 如需要自定义一个方法,需实现XxxMapper.xml,来定义自定义SQL
实现VO/DTO/DO实现代码分层
领域模型转换那些事儿:http://www.imooc.com/article/293314

自动更新系统级字段
- 公共元数据处理器
- 为XxxDO配置注解
集成验证框架步骤
- 在pom.xml引入相关的jar包支持
- 在待验证的实体里面添加相应的注解
- 在Controller中添加相应的注解
- 做参数校验工具类,完成service层的参数校验
实现统一异常处理功能
- 实现一个异常处理的类,并且用@ControllerAdvice修饰
集成CaffeineCache缓存功能
- @Cacheable : 缓存数据,一般用在查询方法上。将查询到的数据进行缓存 @CachePut : 更新方法上,将数据从缓存中进行更新 @CacheEvict : 删除缓存
- pom.xml cache相关的jar包支持
- CacheManager Bean
- 使用注解,标识我们的方法哪些需要缓存
集成Guava令牌桶实现全局限流功能
- 先pom.xml引入Guava工具包的支持
- 定义一个拦截器,实现令牌的发放和获取
- 将拦截器配置到web系统中
使用TraceId实现日志跟踪
- 建立一个过滤器,在过滤器中给线程设置TraceId
- 将日志配置文件进行修改,把TraceId打印到日志中
文件上传下载
- 文件上传的Controller,负责处理文件上传
- 文件上传的服务接口,通过接口的形式来定义出文件上传的功能
- 实现文件上传业务逻辑
- 文件下载,采用静态路径映射的方式实现
数据导出功能
- pom.xml把相关的jar配置好
- UserController新增加数据导出的方法
- 要实现数据导出的功能
- 定义导出实体
- 分批加载数据,分批使用EasyExcel导出
- 将导出的文件上传
导出功能异步化
- 先创建线程池
- 将导出方法使用@Aync注解标记为异步执行
使用Swagger2帮助我们生成API文档
- pom.xml引入jar包
- 配置Swagger2的配置类
- Controller及相关的实体中写对应的注解