This commit is contained in:
Shuaishuai Dai 2022-08-11 18:10:37 +08:00
parent 9f86b9ad1f
commit 6552c69567
15 changed files with 1079 additions and 1 deletions

124
java/jdk8/Lambda.md Normal file
View File

@ -0,0 +1,124 @@
## Lambda 表达式-函数式编程
#### 介绍
+ 只有是函数式的接口才可以使用lambda表达式
+ 接口中有且只有一个抽象方法的接口称为函数式接口
+ @FunctionalInterface 注解强制检测是否为函数式接口
#### 用法
+ 无参数,无返回值:()-> 具体实现
+ 有一个参数无返回值x-> 具体实现
+ 若只有一个参数小括号可以省略不写x -> 具体实现
+ 若有多个参数多条语句加个大括号就行了x,y-> { 具体实现 }
+ 若 lambda 中只有一条语句return 和大括号都可以省略不写,如`Comparator<Integer>com = (x,y) -> Integer.compare(x,y)`
#### 四大内置函数式接口
| 接口 | 语法 |
| :----------------------: | :---------------: |
| Consumer<T> 消费型接口 | void accept(T t) |
| Supplier<T> 供给型接口 | T get() |
| Function<T,R> 函数型接口 | R apply(T t) |
| Predicate<T> 断言型接口 | boolean test(T t) |
+ ##### Consumer
+ ##### 实例
```java
String name = "大山";
private void consumer(Consumer<String> consumer){
consumer.accept(name);
}
@Test
public void test1(){
consumer((name)-> System.out.println("我的名字:"+name));
// 若只有一个参数小括号可以省略不写x -> 具体实现
consumer(name-> System.out.println("他的名字:"+name));
}
```
+ ##### 输出内容
```
我的名字:大山
他的名字:大山
```
+ ##### Supplier
+ ##### 实例
```java
private void supplier(Supplier<Integer> supplier){
System.out.println("今日生产数量:"+supplier.get());
}
@Test
public void test2(){
supplier(()-> {return 123;});
// 若 lambda 中只有一条语句return 和大括号都可以省略不写,如`Comparator<Integer>com = (x,y) -> Integer.compare(x,y)`
supplier(()-> 150);
}
```
+ ##### 输出内容
```sh
今日生产数量:123
今日生产数量:150
```
+ ##### Function
+ ##### 实例
```java
private void function(String num,Function<String,Integer> function){
System.out.println("生产数量:"+(function.apply(num)+100));
}
@Test
public void test3(){
function("200",num-> Integer.parseInt(num));
}
```
+ ##### 输出内容
```
生产数量300
生产数量120
```
+ ##### Predicate
+ 实例
```java
private void predicate(Integer age,Predicate<Integer> predicate){
System.out.println("我今年成年了吗:"+predicate.test(age));
}
@Test
public void test4(){
predicate(15,age->age>=18);
predicate(23,age->age>=18);
}
```
+ ##### 输出内容
```
我今年成年了吗:false
我今年成年了吗:true
```

0
java/jdk8/LocalDate.md Normal file
View File

0
java/jdk8/Optional.md Normal file
View File

0
java/jdk8/Stream.md Normal file
View File

102
java/jdk8/方法引用.md Normal file
View File

@ -0,0 +1,102 @@
## 方法引用
#### 介绍
+ 若 **lambda体** 中的内容有方法已经实现了,我们可以使用 “方法引用” (可以理解为方法引用是 lambda 表达式的另外一种表现形式)
#### 用法
+ 通过对象名引用成员方法 对象 :: 成员方法名
+ 通过类名访问静态方法 类 :: 静态方法名
+ 通过super调用父类的成员方法 super :: 成员方法名
+ 通过this调用本类的成员方法 this :: 成员方法名
+ 构造器引用 类名 :: new
+ 数组引用 Type[] :: new
#### 实例
+ ##### 对象 :: 成员方法名
+ ##### 实例
```java
```
+ ##### 输出内容
```
```
+ ##### 类 :: 静态方法名
+ ##### 实例
```java
```
+ ##### 输出内容
```
```
+ ##### super :: 成员方法名
+ ##### 实例
```java
```
+ ##### 输出内容
```
```
+ ##### this :: 成员方法名
+ ##### 实例
```java
```
+ ##### 输出内容
```
```
+ ##### 类名 :: new
+ ##### 实例
```java
```
+ ##### 输出内容
```
```
+ ##### Type[] :: new
+ ##### 实例
```java
```
+ ##### 输出内容
```
```

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,52 @@
## JAVAX Validation工具类
##### 手动对对象进行验证
```java
/**
* @author dss
* @since 2022/7/6
*/
public class ValidationUtil {
/**
* 开启快速结束模式 failFast (true)
*/
private static final Validator validator = Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator();
/**
* 校验对象
*
* @param t bean
* @param groups 校验组
* @return ValidResult
*/
public static <T> void validateBean(T t,Class<?>...groups) {
if (t==null) throw new MyException(RestResponse.MSG.PARAM_VALIDATION_FAILURE);
Set<ConstraintViolation<T>> violationSet = validator.validate(t,groups);
boolean hasError = violationSet != null && !violationSet.isEmpty();
//存在验证错误直接抛出异常
if (hasError){
for (ConstraintViolation<T> violation : violationSet) {
throw new MyException(RestResponse.MSG.PARAM_VALIDATION_FAILURE).setMsg(violation.getMessage());
}
}
}
/**
* 校验bean的某一个属性
*
* @param obj bean
* @param propertyName 属性名称
* @return ValidResult
*/
public static <T> void validateProperty(T obj, String propertyName) {
Set<ConstraintViolation<T>> violationSet = validator.validateProperty(obj, propertyName);
boolean hasError = violationSet != null && !violationSet.isEmpty();
//存在验证错误直接抛出异常
if (hasError){
for (ConstraintViolation<T> violation : violationSet) {
throw new MyException(RestResponse.MSG.PARAM_VALIDATION_FAILURE).setMsg(violation.getMessage());
}
}
}
}
```

View File

@ -0,0 +1,198 @@
## 枚举工具类
#### EnumCodeService
##### 作用枚举Service 对实现此接口的枚举实现序列化以及其他功能
```java
@JsonDeserialize(using = EnumCodeDeserializer.class) //jackson注解
@JsonSerialize(using = EnumCodeSerializer.class) //jackson注解
public interface EnumCodeService {
/**
* 获取状态吗
* @return
*/
Integer getCode();
/**
* 获取Name
* @return
*/
String getName();
}
```
#### EnumCodeUtil
##### 作用:枚举工具类
```java
public class EnumCodeUtil {
public static <E extends Enum<E> & EnumCodeService> E manageCode(Class<E> enumClass, int code) {
E[] enumConstants = enumClass.getEnumConstants();
for (E e : enumConstants) {
if (e.getCode() == code) {
return e;
}
}
return null;
}
public static <E extends Enum<E> & EnumCodeService> E convert(Class<E> enumClass, String str) {
E[] enumConstants = enumClass.getEnumConstants();
for (E e : enumConstants) {
if (e.toString() .equals(str.toUpperCase()) ||e.getName().equals(str.toLowerCase()) || String.valueOf(e.getCode()).equals(str)) {
return e;
}
}
throw new CommonException(enumClass.getName()+"枚举不存在");
}
public static List<Map<String, Object>> enumToListMap(Class<?> clazz) {
List<Map<String, Object>> resultList = null;
// 判断是否是枚举类型
if ("java.lang.Enum".equals(clazz.getSuperclass().getCanonicalName())) {
resultList = new ArrayList<>();
// 获取所有public方法
Method[] methods = clazz.getMethods();
List<Field> fieldList = new ArrayList<>();
for (int i = 0; i < methods.length; i++) {
String methodName = methods[i].getName();
// 找到枚举类中的以get开头的(并且不是父类已定义的方法)所有方法
if (methodName.startsWith("get") && !"getDeclaringClass".equals(methodName)
&& !"getClass".equals(methodName)) {
Field field = null;
try {
// 通过方法名获取自定义字段
field = clazz.getDeclaredField(StringUtils.uncapitalize(methodName.substring(3)));
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
// 如果不为空则添加到fieldList集合中
if (field != null) {
fieldList.add(field);
}
}
}
// 判断fieldList集合是否为空
if (!fieldList.isEmpty()) {
Map<String, Object> map = null;
// 获取所有枚举
Enum<?>[] enums = (Enum[])clazz.getEnumConstants();
for (int i = 0; i < enums.length; i++) {
map = new HashMap<>();
for (int l = 0, len = fieldList.size(); l < len; l++) {
Field field = fieldList.get(l);
field.setAccessible(true);
try {
//如果字段名称等于则跳过 非必要判断可不写
if (field.getName().equals("cls")){
continue;
}
// 向map集合添加字段名称 和 字段值
map.put(field.getName(), field.get(enums[i]));
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
map.put("enumValue",enums[i].toString());
// 将Map添加到集合中
resultList.add(map);
}
}
}
return resultList;
}
}
```
#### EnumCodeSerializer
##### 作用基于jackson实现枚举序列化规则
```java
public class EnumCodeSerializer<T extends Enum & EnumCodeService> extends JsonSerializer<T> {
@Override
public void serialize(T t, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(t.getCode().toString());
}
}
```
#### EnumCodeDeserializer
##### 作用基于jackson实现枚举反序列化规则
```java
@Slf4j
public class EnumCodeDeserializer<E extends Enum & EnumCodeService> extends JsonDeserializer<E> {
@Override
public E deserialize(
JsonParser jsonParser,
DeserializationContext deserializationContext
) throws IOException {
Class c = jsonParser.getCurrentValue().getClass();
Field declaredField = ReflectionUtils.getDeclaredField(c,jsonParser.getCurrentName());
Class<E> type = (Class<E>) declaredField.getType();
if (NullUtils.isNotEmptyString(jsonParser.getValueAsString())){
return (E) EnumCodeUtil.convert(type, jsonParser.getValueAsString());
}else{
return null;
}
}
}
```
#### EnumTypeHandler
##### 作用基于mybatis框架实现对实现了EnumService的枚举进行数据库和服务器之间的序列化和反序列化
```java
public class EnumTypeHandler<E extends Enum<E> & EnumCodeService> extends BaseTypeHandler<EnumCodeService> {
private Class<E> type;
public EnumTypeHandler(){
}
public EnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
} else {
this.type = type;
}
}
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, EnumCodeService enumCode, JdbcType jdbcType) throws SQLException {
preparedStatement.setInt(i, enumCode.getCode());
}
@Override
public EnumCodeService getNullableResult(ResultSet resultSet, String s) throws SQLException {
return EnumCodeUtil.manageCode(type, resultSet.getInt(s));
}
@Override
public EnumCodeService getNullableResult(ResultSet resultSet, int i) throws SQLException {
return EnumCodeUtil.manageCode(type, resultSet.getInt(i));
}
@Override
public EnumCodeService getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return EnumCodeUtil.manageCode(type, callableStatement.getInt(i));
}
}
```

View File

@ -0,0 +1,275 @@
## 自定义restful接口响应体
#### RestResponse
##### 作用响应体载体响应内容都在此对象中存储此类定义MSG枚举消息体
```java
@Data
@Accessors(chain = true)
@ToString
@NoArgsConstructor
public class RestResponse<T> implements Serializable {
private static boolean showError = true;
public enum MSG {
// 成功
SUCCESS(1, "SUCCESS"),
// 失败
FAILURE(0, "FAILURE"),
// 参数为空
NULL_PARAM(10000, "参数为空"),
// 对象为空
NULL_OBJ(10001, "对象为空"),
// 有数据为空
NO_DATA_BASE_EXISTS(10002, "数据在库中为空"),
// 参数未找到
NO_EXISTS_PARAM(10003, "参数未找到"),
// 数据不存在
NO_DATA_EXISTS(10004, "数据不存在"),
// 分页参数为空
NULL_PAGE_PARAM(10005, "分页参数为空"),
// 参数验证失败
PARAM_VALIDATION_FAILURE(10006, "参数验证未通过"),
// 参数不一致
PARAM_NOT_EQUAL(10007, "执行修改操作异常,参数id不一致"),
// 参数验证失败
DATA_EXISTS(10008, "数据已存在"),
// 参数值不符合规范
PARAM_VALUE_ERROR(11000, "参数值不符合规范");
int code;
String msg;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public void setCode(int code) {
this.code = code;
}
public void setMsg(String msg) {
this.msg = msg;
}
MSG(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
private int code;
private String msg;
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})
private T data;
public RestResponse(MSG msg) {
this.code = msg.code;
this.msg = msg.msg;
}
/**
* 通过预设错误码和自定义错误信息创建
* @param code 错误码
* @param msg 错误信息
*/
private RestResponse(int code, String msg) {
this.code = code;
this.msg = msg;
}
public RestResponse(T obj) {
this.code = MSG.SUCCESS.code;
this.msg = MSG.SUCCESS.msg;
this.data = obj;
}
public RestResponse(MSG msg, T obj) {
this.code = msg.code;
this.msg = msg.msg;
this.data = obj;
}
public RestResponse(int code,String msg, T obj) {
this.code = code;
this.msg = msg;
this.data = obj;
}
public static RestResponse<Void> success() {
return new RestResponse<>(MSG.SUCCESS);
}
public static <T> RestResponse<T> success(T obj) {
return new RestResponse<>(MSG.SUCCESS, obj);
}
public static RestResponse<Void> success(int code, String msg) {
return new RestResponse<>(code, msg);
}
public static <T> RestResponse<T> success(T obj,String msg) {
return new RestResponse<>(MSG.SUCCESS.code,msg, obj);
}
public static RestResponse<Void> failure() {
return new RestResponse<>(MSG.FAILURE);
}
public static RestResponse<Void> failure(int code, String msg) {
return new RestResponse<>(code, msg);
}
public static RestResponse<Void> failure(MSG e) {
return new RestResponse<>(e.getCode(), e.getMsg());
}
public static RestResponse<Void> failure(MyException e) {
return new RestResponse<>(e.getCode(), e.getMsg());
}
public static <T> RestResponse<T> failure(T obj) {
return new RestResponse<>(MSG.FAILURE, obj);
}
/**
* 分页信息
* @param content 内容列表
* @param page 当前页数
* @param size 每页数据量
* @param total 数据总量
* @param totalPage 总页数
* @return res
*/
public static <T> RestResponse<PageResult<T>> pageList(List<T> content, long page, long size, long total, long totalPage) {
PageResult<T> pr = new PageResult<>(content, page, total, size, totalPage);
return new RestResponse<>(MSG.SUCCESS, pr);
}
/**
* 分页信息
* @param content 内容列表
* @param total 数据总量
* @return res
*/
public static <T> RestResponse<PageResult<T>> simplePageList(List<T> content, long total) {
PageResult<T> pr = new PageResult<>(content, total);
return new RestResponse<>(MSG.SUCCESS, pr);
}
}
```
#### PageResult
##### 作用:分页查询响应体载体
```java
@Data
@Builder
@NoArgsConstructor
@Accessors(chain = true)
@ApiModel("分页返回对象")
public class PageResult<T> implements Serializable {
private static final long serialVersionUID = 1402394526521183854L;
@ApiModelProperty("主题内容")
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})
private List<T> content;
@ApiModelProperty("当前页")
private long page;
@ApiModelProperty("每页数量")
private long size;
@ApiModelProperty("总数量")
private long total;
@ApiModelProperty("总页数")
private long totalPage;
public PageResult(List<T> content,
long page,
long size,
long total,
long totalPage){
this.content=content;
this.page=page;
this.size=size;
this.totalPage=totalPage;
this.total=total;
}
public PageResult(List<T> content,
long total){
this.content=content;
this.total=total;
}
}
```
#### MyException
##### 作用:自定义异常类
```java
@Data
@NoArgsConstructor
@Accessors(chain = true)
@Builder
public class MyException extends RuntimeException {
//错误码
private Integer code;
//错误信息
private String msg;
/**
* 自定义异常信息
*/
public MyException(Integer code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
/**
* 响应类异常信息
*/
public MyException(RestResponse.MSG msg) {
super(msg.getMsg());
this.code=msg.getCode();
this.msg=msg.getMsg();
}
public MyException append(String msg){
this.msg+=msg;
return this;
}
public MyException before(String msg){
this.msg=msg+this.msg;
return this;
}
}
```

View File

@ -0,0 +1,29 @@
## MySQL踩坑记录
### 【1235】 This version of MySQL doesnt yet support LIMIT & IN/ALL/ANY/SOME subquery
+ ##### 含义:这版本的 MySQL 不支持使用 LIMIT 子句的 IN/ALL/ANY/SOME 子查询
+ ##### 问题SQL
我想要查找凭证列表中的前十条记录
```mysql
SELECT * FROM voucher where id IN
(select DISTINCT(id) from voucher where is_deleted = 0 and DATE_FORMAT(v.bookkeeping_date,'%Y-%m') >= '2022-08' LIMIT 0,10)
```
+ ##### 原因
+ 原因在于子查询三层嵌套在 in或 not in 中使用了 limit
+ ##### 解决办法
将我们的SQL在进行嵌套一层绕开limit子查询就可以了
```mysql
SELECT * from voucher where id IN
(select id from (select DISTINCT(id) from voucher where is_deleted = 0 and DATE_FORMAT(v.bookkeeping_date,'%Y-%m') >= '2022-08' LIMIT 0,10) vtable)
```

View File

@ -1 +0,0 @@
##