mirror of
https://gitee.com/jzsw-it/yexuejc-base.git
synced 2025-11-19 05:47:45 +08:00
Compare commits
13 Commits
1.5.2-jre8
...
41a9f1b507
| Author | SHA1 | Date | |
|---|---|---|---|
| 41a9f1b507 | |||
| bf731e753a | |||
| 8d5e653d2b | |||
| c4fc4bd4f8 | |||
|
|
667ad26971 | ||
|
|
a260b41fae | ||
|
|
0754660c45 | ||
| 0dc13a6aa1 | |||
|
|
3ddd11f9c9 | ||
|
|
a05bb00123 | ||
|
|
77a0e29916 | ||
|
|
b0b8cbc7ab | ||
| 4c77c4ebe8 |
14
UPDATE.md
14
UPDATE.md
@@ -1,6 +1,20 @@
|
||||
yexuejc-base 更新记录
|
||||
------------------
|
||||
|
||||
#### version :1.5.1-jre11
|
||||
**time:2023-6-8 16:02:56** <br/>
|
||||
**branch:** jre11 <br/>
|
||||
**update:** <br/>
|
||||
1. FileUtil 增加读取csv文件(分页读取)
|
||||
提供读取IO流方法合集
|
||||
2. 增加AES加解密
|
||||
3. 增加文件压缩ZipUtil
|
||||
4. DateUtil,DateTimeUtil 时间操作工具优化
|
||||
5. JsonUtil [feat] 增加json化时对LocalDateTime,LocalDate,Timestamp时间的优化,增加特殊场景序列化反序列化
|
||||
|
||||
|
||||
|
||||
---
|
||||
#### version :1.5.0-jre8
|
||||
**time:2022-5-9 13:37:31** <br/>
|
||||
**branch:** master <br/>
|
||||
|
||||
30
pom.xml
30
pom.xml
@@ -6,16 +6,16 @@
|
||||
|
||||
<groupId>top.yexuejc</groupId>
|
||||
<artifactId>yexuejc-base</artifactId>
|
||||
<version>1.5.0-jre8</version>
|
||||
<version>1.5.1-jre11</version>
|
||||
|
||||
<name>yexuejc-base</name>
|
||||
<url>https://github.com/yexuejc/yexuejc-base</url>
|
||||
<description>Common toolkits based on JDK8 packaging</description>
|
||||
<description>Common toolkits based on JDK11 packaging</description>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
@@ -44,14 +44,15 @@
|
||||
<repos.jitpack.url>https://jitpack.io</repos.jitpack.url>
|
||||
<jjwt.version>0.11.5</jjwt.version>
|
||||
<maven.compiler.verbose>true</maven.compiler.verbose>
|
||||
<java.version>1.8</java.version>
|
||||
<validation-api.version>3.0.1</validation-api.version>
|
||||
<java.version>11</java.version>
|
||||
<validation-api.version>3.0.2</validation-api.version>
|
||||
|
||||
<commons-io.version>2.11.0</commons-io.version>
|
||||
<bcprov-jdk15on.version>1.70</bcprov-jdk15on.version>
|
||||
<guava.version>31.1-jre</guava.version>
|
||||
<apache-poi.version>5.2.2</apache-poi.version>
|
||||
<jackson.version>2.13.2</jackson.version>
|
||||
<jackson.version>2.14.2</jackson.version>
|
||||
<zip4j.version>2.11.4</zip4j.version>
|
||||
<!-- 文件拷贝时的编码 -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
@@ -117,11 +118,22 @@
|
||||
<artifactId>jackson-dataformat-csv</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.lingala.zip4j</groupId>
|
||||
<artifactId>zip4j</artifactId>
|
||||
<version>${zip4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.8.1</version>
|
||||
<version>5.9.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -136,8 +148,8 @@
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 打包源码 -->
|
||||
|
||||
@@ -11,11 +11,21 @@ import java.lang.annotation.*;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface CsvHeader {
|
||||
public @interface CsvToBean {
|
||||
|
||||
/**
|
||||
* 在类头上设置csv格式的header
|
||||
* @return
|
||||
* csv文件和java bean的映射
|
||||
*/
|
||||
String header();
|
||||
|
||||
/**
|
||||
* csv文件的分割符号
|
||||
*/
|
||||
char delimiter() default ',';
|
||||
|
||||
/**
|
||||
* CSV文件是否有header
|
||||
*/
|
||||
boolean hasHeader() default false;
|
||||
}
|
||||
21
src/main/java/com/yexuejc/base/constant/DateConsts.java
Normal file
21
src/main/java/com/yexuejc/base/constant/DateConsts.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.yexuejc.base.constant;
|
||||
|
||||
/**
|
||||
* @author yexuejc
|
||||
* @class-name DateConsts
|
||||
* @description
|
||||
* @date 2023/05/17 13:45
|
||||
*/
|
||||
public class DateConsts {
|
||||
public static final String BAR = "-";
|
||||
public static final CharSequence DATE_KEY_AM = "AM";
|
||||
public static final CharSequence DATE_KEY_PM = "PM";
|
||||
public static final String DATE_TIMESTAMP_LINUX = "M/dd/yy, h:mm a";
|
||||
public static final CharSequence SLASH = "/";
|
||||
public static final CharSequence COLON = ":";
|
||||
public static final String DATE_YYYY_MM_DD_SLASH = "yyyy/MM/dd";
|
||||
public static final CharSequence DATE_KEY_T = "T";
|
||||
public static final String DATE_KEY_Z = "Z";
|
||||
public static final String DATE_TIMESTAMP = "yyyy/MM/dd H:m:s";
|
||||
public static final String DATE_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.yexuejc.base.converter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.yexuejc.base.constant.DateConsts;
|
||||
import com.yexuejc.base.util.StrUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* json转LocalDate
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2022/10/08
|
||||
*/
|
||||
public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
|
||||
|
||||
@Override
|
||||
public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
|
||||
throws IOException {
|
||||
String timeString = jsonParser.getValueAsString();
|
||||
if (StrUtil.isEmpty(timeString)) {
|
||||
return null;
|
||||
}
|
||||
if (timeString.contains(DateConsts.BAR)) {
|
||||
return LocalDate.parse(timeString, DateTimeFormatter.ISO_DATE);
|
||||
} else if (timeString.contains(DateConsts.DATE_KEY_AM)
|
||||
|| timeString.contains(DateConsts.DATE_KEY_PM)) {
|
||||
return LocalDate.parse(timeString,
|
||||
DateTimeFormatter.ofPattern(DateConsts.DATE_TIMESTAMP_LINUX, Locale.ENGLISH));
|
||||
} else if (timeString.contains(DateConsts.SLASH) && timeString.contains(DateConsts.COLON)) {
|
||||
return LocalDate.parse(timeString.substring(0, 10),
|
||||
DateTimeFormatter.ofPattern(DateConsts.DATE_YYYY_MM_DD_SLASH));
|
||||
} else if (timeString.contains(DateConsts.SLASH)) {
|
||||
return LocalDate.parse(timeString, DateTimeFormatter.ofPattern(DateConsts.DATE_YYYY_MM_DD_SLASH));
|
||||
} else {
|
||||
return LocalDate.parse(timeString, DateTimeFormatter.BASIC_ISO_DATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.yexuejc.base.converter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* localDate转json
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2022/10/08
|
||||
*/
|
||||
public class LocalDateSerializer extends JsonSerializer<LocalDate> {
|
||||
@Override
|
||||
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
|
||||
throws IOException {
|
||||
jsonGenerator.writeString(localDate.format(DateTimeFormatter.ISO_DATE));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.yexuejc.base.converter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.yexuejc.base.constant.DateConsts;
|
||||
import com.yexuejc.base.util.StrUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* json转LocalDateTime
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2022/10/08
|
||||
*/
|
||||
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
|
||||
@Override
|
||||
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
|
||||
throws IOException {
|
||||
String timeString = jsonParser.getValueAsString();
|
||||
if (StrUtil.isEmpty(timeString)) {
|
||||
return null;
|
||||
}
|
||||
if (timeString.contains(DateConsts.DATE_KEY_T)) {
|
||||
return LocalDateTime.parse(timeString, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
|
||||
} else if (timeString.contains(DateConsts.DATE_KEY_AM)
|
||||
|| timeString.contains(DateConsts.DATE_KEY_PM)) {
|
||||
return LocalDateTime.parse(timeString,
|
||||
DateTimeFormatter.ofPattern(DateConsts.DATE_TIMESTAMP_LINUX, Locale.ENGLISH));
|
||||
} else if (timeString.endsWith(DateConsts.DATE_KEY_Z)) {
|
||||
return LocalDateTime.parse(timeString, DateTimeFormatter.ISO_INSTANT);
|
||||
} else if (timeString.contains(DateConsts.SLASH)) {
|
||||
return LocalDateTime.parse(timeString, DateTimeFormatter.ofPattern(DateConsts.DATE_TIMESTAMP));
|
||||
} else {
|
||||
return LocalDateTime.parse(timeString,
|
||||
DateTimeFormatter.ofPattern(DateConsts.DATE_YYYY_MM_DD_HH_MM_SS));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.yexuejc.base.converter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
|
||||
/**
|
||||
* LocalDateTime转json
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2022/10/08
|
||||
*/
|
||||
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
|
||||
@Override
|
||||
public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator,
|
||||
SerializerProvider serializerProvider) throws IOException {
|
||||
jsonGenerator.writeString(localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.yexuejc.base.converter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* json中的“”转String对象时值为null
|
||||
* 例子:{str:""} ->
|
||||
* JsonBean{
|
||||
* public String str;
|
||||
* }
|
||||
* str的值为null [不使用{@link StringDeserializer},str的值为“”]
|
||||
* </pre>
|
||||
*
|
||||
* <pre>
|
||||
* 使用方式:
|
||||
* jsonMapper.registerModule(new SimpleModule().addDeserializer(String.class, new StringDeserializer()));
|
||||
* </pre>
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2022/10/08
|
||||
*/
|
||||
public class StringDeserializer extends JsonDeserializer<String> {
|
||||
|
||||
@Override
|
||||
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
|
||||
throws IOException {
|
||||
String timeString = jsonParser.getValueAsString();
|
||||
if ("".equals(timeString)) {
|
||||
return null;
|
||||
}
|
||||
return timeString;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.yexuejc.base.converter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.yexuejc.base.constant.DateConsts;
|
||||
import com.yexuejc.base.util.StrUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* json转LocalDateTime
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2022/10/08
|
||||
*/
|
||||
public class TimestampDeserializer extends JsonDeserializer<Timestamp> {
|
||||
@Override
|
||||
public Timestamp deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
|
||||
throws IOException {
|
||||
String timeString = jsonParser.getValueAsString();
|
||||
if (StrUtil.isEmpty(timeString)) {
|
||||
return null;
|
||||
}
|
||||
if (timeString.contains(DateConsts.DATE_KEY_T)) {
|
||||
return Timestamp.valueOf(LocalDateTime.parse(timeString, DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
} else if (timeString.contains(DateConsts.DATE_KEY_AM)
|
||||
|| timeString.contains(DateConsts.DATE_KEY_PM)) {
|
||||
return Timestamp.valueOf(LocalDateTime.parse(timeString,
|
||||
DateTimeFormatter.ofPattern(DateConsts.DATE_TIMESTAMP_LINUX, Locale.ENGLISH)));
|
||||
} else if (timeString.endsWith(DateConsts.DATE_KEY_Z)) {
|
||||
return Timestamp.valueOf(LocalDateTime.parse(timeString, DateTimeFormatter.ISO_INSTANT));
|
||||
} else if (timeString.contains(DateConsts.SLASH)) {
|
||||
return Timestamp.valueOf(
|
||||
LocalDateTime.parse(timeString, DateTimeFormatter.ofPattern(DateConsts.DATE_TIMESTAMP)));
|
||||
} else {
|
||||
return Timestamp.valueOf(LocalDateTime.parse(timeString,
|
||||
DateTimeFormatter.ofPattern(DateConsts.DATE_YYYY_MM_DD_HH_MM_SS)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.yexuejc.base.converter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.yexuejc.base.constant.DateConsts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* Timestamp转json
|
||||
*
|
||||
* @author yexuejc
|
||||
* @date 2022/10/08
|
||||
*/
|
||||
public class TimestampSerializer extends JsonSerializer<Timestamp> {
|
||||
@Override
|
||||
public void serialize(Timestamp timestamp, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
|
||||
throws IOException {
|
||||
SimpleDateFormat df = new SimpleDateFormat(DateConsts.DATE_TIMESTAMP);
|
||||
jsonGenerator.writeString(df.format(timestamp));
|
||||
}
|
||||
}
|
||||
173
src/main/java/com/yexuejc/base/encrypt/AES.java
Normal file
173
src/main/java/com/yexuejc/base/encrypt/AES.java
Normal file
@@ -0,0 +1,173 @@
|
||||
package com.yexuejc.base.encrypt;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* AES加解密
|
||||
*
|
||||
* @author maxf
|
||||
* @class-name AES
|
||||
* @description
|
||||
* @date 2022/11/11 15:36
|
||||
*/
|
||||
public class AES {
|
||||
public static AES builder() {
|
||||
return Instace.aes;
|
||||
}
|
||||
|
||||
private static class Instace {
|
||||
private static AES aes = new AES();
|
||||
}
|
||||
|
||||
public static final String AES_ALGORITHM = "AES";
|
||||
|
||||
/**
|
||||
* 加密模式
|
||||
*/
|
||||
public static enum ALGORITHM {
|
||||
//算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
|
||||
//AES/CBC/NoPadding 16 不支持
|
||||
AES_CBC_NoPadding("AES/CBC/NoPadding"),
|
||||
//AES/CBC/PKCS5Padding 32 16
|
||||
AES_CBC_PKCS5Padding("AES/CBC/PKCS5Padding"),
|
||||
//AES/CBC/ISO10126Padding 32 16
|
||||
AES_CBC_ISO10126Padding("AES/CBC/ISO10126Padding"),
|
||||
//AES/CFB/NoPadding 16 原始数据长度
|
||||
AES_CFB_NoPadding("AES/CFB/NoPadding"),
|
||||
//AES/CFB/PKCS5Padding 32 16
|
||||
AES_CFB_PKCS5Padding("AES/CFB/PKCS5Padding"),
|
||||
//AES/CFB/ISO10126Padding 32 16
|
||||
AES_CFB_ISO10126Padding("AES/CFB/ISO10126Padding"),
|
||||
//AES/ECB/NoPadding 16 不支持
|
||||
AES_ECB_NoPadding("AES/ECB/NoPadding"),
|
||||
//AES/ECB/PKCS5Padding 32 16
|
||||
AES_ECB_PKCS5Padding("AES/ECB/PKCS5Padding"),
|
||||
//AES/ECB/ISO10126Padding 32 16
|
||||
AES_ECB_ISO10126Padding("AES/ECB/ISO10126Padding"),
|
||||
//AES/OFB/NoPadding 16 原始数据长度
|
||||
AES_OFB_NoPadding("AES/OFB/NoPadding"),
|
||||
//AES/OFB/PKCS5Padding 32 16
|
||||
AES_OFB_PKCS5Padding("AES/OFB/PKCS5Padding"),
|
||||
//AES/OFB/ISO10126Padding 32 16
|
||||
AES_OFB_ISO10126Padding("AES/OFB/ISO10126Padding"),
|
||||
//AES/PCBC/NoPadding 16 不支持
|
||||
AES_PCBC_NoPadding("AES/PCBC/NoPadding"),
|
||||
//AES/PCBC/PKCS5Padding 32 16
|
||||
AES_PCBC_PKCS5Padding("AES/PCBC/PKCS5Padding"),
|
||||
//AES/PCBC/ISO10126Padding 32 16
|
||||
AES_PCBC_ISO10126Padding("AES/PCBC/ISO10126Padding");
|
||||
public String name;
|
||||
|
||||
ALGORITHM(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
private ALGORITHM algorithm = ALGORITHM.AES_CBC_NoPadding;
|
||||
private String key = "hj7x89H$yuBI0456";
|
||||
private String iv = "NIfb&95GUY86Gfgh";
|
||||
private Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*
|
||||
* @param data 明文
|
||||
* @return 密文
|
||||
* @Description AES算法加密明文
|
||||
*/
|
||||
public String encrypt(String data) throws Exception {
|
||||
try {
|
||||
|
||||
Cipher cipher = Cipher.getInstance(algorithm.name);
|
||||
int blockSize = cipher.getBlockSize();
|
||||
byte[] dataBytes = data.getBytes(charset);
|
||||
int plaintextLength = dataBytes.length;
|
||||
if (plaintextLength % blockSize != 0) {
|
||||
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
|
||||
}
|
||||
byte[] plaintext = new byte[plaintextLength];
|
||||
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
|
||||
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(charset), AES_ALGORITHM);
|
||||
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes(charset));
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
|
||||
byte[] encrypted = cipher.doFinal(plaintext);
|
||||
return Base64.getEncoder().encodeToString(encrypted);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*
|
||||
* @param data 密文
|
||||
* @return 明文
|
||||
* @Description AES算法解密密文
|
||||
*/
|
||||
public String decrypt(String data) throws Exception {
|
||||
try {
|
||||
byte[] encrypted = Base64.getDecoder().decode(data);
|
||||
Cipher cipher = Cipher.getInstance(algorithm.name);
|
||||
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(charset), AES_ALGORITHM);
|
||||
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes(charset));
|
||||
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
|
||||
byte[] original = cipher.doFinal(encrypted);
|
||||
return new String(original, charset).trim();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
//
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// String str = " 奥萨蒂 asd8阿斯顿8asd ";
|
||||
// AES.builder().setAlgorithm(ALGORITHM.AES_CBC_ISO10126Padding);
|
||||
// AES.builder().setKey("DEsx89H$yuBI0456");
|
||||
// String encrypt = AES.builder().encrypt(str);
|
||||
// System.out.println(encrypt);
|
||||
// String decrypt = AES.builder().decrypt(encrypt);
|
||||
// System.out.println(">>>" + decrypt + "<<<");
|
||||
// }
|
||||
|
||||
public ALGORITHM getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public AES setAlgorithm(ALGORITHM algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public AES setKey(String key) {
|
||||
this.key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getIv() {
|
||||
return iv;
|
||||
}
|
||||
|
||||
public AES setIv(String iv) {
|
||||
this.iv = iv;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Charset getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
public AES setCharset(Charset charset) {
|
||||
this.charset = charset;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
90
src/main/java/com/yexuejc/base/pojo/CreateZipFileBean.java
Normal file
90
src/main/java/com/yexuejc/base/pojo/CreateZipFileBean.java
Normal file
@@ -0,0 +1,90 @@
|
||||
package com.yexuejc.base.pojo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 压缩文件的参数设定
|
||||
*
|
||||
* @author maxf
|
||||
* @class-name CreateZipFileBean
|
||||
* @description 压缩文件参考 {@link com.yexuejc.base.util.ZipUtil}
|
||||
* @date 2022/11/11 10:30
|
||||
*/
|
||||
public class CreateZipFileBean {
|
||||
/**
|
||||
* 压缩的源文件列表,为空表示压缩整个目录
|
||||
*/
|
||||
private List<String> sourceFileName;
|
||||
/**
|
||||
* 当压缩文件夹时,需要排除的文件。压缩文件时(该参数无效)
|
||||
*/
|
||||
private List<String> excludeFileName;
|
||||
/**
|
||||
* 压缩源文件的目录
|
||||
*/
|
||||
private String sourcePath;
|
||||
/**
|
||||
* 生成压缩文件路径(全路径+压缩文件名)
|
||||
*/
|
||||
private String zipFile;
|
||||
/**
|
||||
* 加密密码
|
||||
*/
|
||||
private String encryptPwd;
|
||||
|
||||
private String writeCharsetName = "UTF-8";
|
||||
|
||||
public List<String> getSourceFileName() {
|
||||
return sourceFileName;
|
||||
}
|
||||
|
||||
public String getEncryptPwd() {
|
||||
return encryptPwd;
|
||||
}
|
||||
|
||||
public CreateZipFileBean setEncryptPwd(String encryptPwd) {
|
||||
this.encryptPwd = encryptPwd;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateZipFileBean setSourceFileName(List<String> sourceFileName) {
|
||||
this.sourceFileName = sourceFileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSourcePath() {
|
||||
return sourcePath;
|
||||
}
|
||||
|
||||
public CreateZipFileBean setSourcePath(String sourcePath) {
|
||||
this.sourcePath = sourcePath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getZipFile() {
|
||||
return zipFile;
|
||||
}
|
||||
|
||||
public CreateZipFileBean setZipFile(String zipFile) {
|
||||
this.zipFile = zipFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getWriteCharsetName() {
|
||||
return writeCharsetName;
|
||||
}
|
||||
|
||||
public CreateZipFileBean setWriteCharsetName(String writeCharsetName) {
|
||||
this.writeCharsetName = writeCharsetName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getExcludeFileName() {
|
||||
return excludeFileName;
|
||||
}
|
||||
|
||||
public CreateZipFileBean setExcludeFileName(List<String> excludeFileName) {
|
||||
this.excludeFileName = excludeFileName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
61
src/main/java/com/yexuejc/base/pojo/CsvToBean.java
Normal file
61
src/main/java/com/yexuejc/base/pojo/CsvToBean.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package com.yexuejc.base.pojo;
|
||||
|
||||
/**
|
||||
* {@link com.yexuejc.base.annotation.CsvToBean}
|
||||
* 读取csv文件用
|
||||
* @author yexuejc
|
||||
* @class-name CsvToBean
|
||||
* @description
|
||||
* @date 2023/6/6 18:15
|
||||
*/
|
||||
public class CsvToBean {
|
||||
|
||||
/**
|
||||
* 在类头上设置csv格式的header
|
||||
* csv文件和java bean的映射
|
||||
*/
|
||||
private String header;
|
||||
|
||||
/**
|
||||
* csv文件的分割符号
|
||||
*/
|
||||
private char delimiter;
|
||||
|
||||
/**
|
||||
* CSV文件是否有header
|
||||
*/
|
||||
private boolean hasHeader;
|
||||
|
||||
public CsvToBean(String header, char delimiter, boolean hasHeader) {
|
||||
this.header = header;
|
||||
this.delimiter = delimiter;
|
||||
this.hasHeader = hasHeader;
|
||||
}
|
||||
|
||||
public String getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public CsvToBean setHeader(String header) {
|
||||
this.header = header;
|
||||
return this;
|
||||
}
|
||||
|
||||
public char getDelimiter() {
|
||||
return delimiter;
|
||||
}
|
||||
|
||||
public CsvToBean setDelimiter(char delimiter) {
|
||||
this.delimiter = delimiter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isHasHeader() {
|
||||
return hasHeader;
|
||||
}
|
||||
|
||||
public CsvToBean setHasHeader(boolean hasHeader) {
|
||||
this.hasHeader = hasHeader;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import com.yexuejc.base.util.JsonUtil;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* 分页 VO
|
||||
*
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package com.yexuejc.base.pojo;
|
||||
|
||||
import org.checkerframework.checker.units.qual.C;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author maxf
|
||||
@@ -34,7 +39,18 @@ public class ReadFileBean<T> {
|
||||
* 文件的length
|
||||
*/
|
||||
private long fileLength;
|
||||
/**
|
||||
* csv文件存在header
|
||||
*/
|
||||
private String header;
|
||||
private Charset readCharset = StandardCharsets.UTF_8;
|
||||
public Function<String, String> lineScavenger = t -> t;
|
||||
|
||||
public ReadFileBean() {
|
||||
this.readRowNum = Integer.MAX_VALUE;
|
||||
this.startRowNum = 1;
|
||||
this.endRowNum = 0;
|
||||
}
|
||||
|
||||
public ReadFileBean(int readRow) {
|
||||
this.readRowNum = readRow;
|
||||
@@ -42,6 +58,24 @@ public class ReadFileBean<T> {
|
||||
this.endRowNum = 0;
|
||||
}
|
||||
|
||||
public Charset getReadCharset() {
|
||||
return readCharset;
|
||||
}
|
||||
|
||||
public ReadFileBean<T> setReadCharset(Charset readCharset) {
|
||||
this.readCharset = readCharset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public ReadFileBean<T> setHeader(String header) {
|
||||
this.header = header;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getReadRowNum() {
|
||||
return readRowNum;
|
||||
}
|
||||
@@ -82,4 +116,12 @@ public class ReadFileBean<T> {
|
||||
this.fileLength = fileLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String lineScavenge(String lineData) {
|
||||
return this.lineScavenger.apply(lineData);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return this.fileLength > this.pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.yexuejc.base.util;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 新版时间日期出来 工具
|
||||
*
|
||||
@@ -258,9 +260,19 @@ public class DateTimeUtil {
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime parseLocalDateTime13(long timestamp) {
|
||||
return parseLocalDateTime13(timestamp, ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Long 转 LocalDateTime
|
||||
*
|
||||
* @param timestamp 13位(毫秒)
|
||||
* @param zoneId 时区
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime parseLocalDateTime13(long timestamp, ZoneId zoneId) {
|
||||
Instant instant = Instant.ofEpochMilli(timestamp);
|
||||
ZoneId zone = ZoneId.systemDefault();
|
||||
return LocalDateTime.ofInstant(instant, zone);
|
||||
return LocalDateTime.ofInstant(instant, zoneId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,9 +282,32 @@ public class DateTimeUtil {
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime parseLocalDateTime10(long timestamp) {
|
||||
return parseLocalDateTime10(timestamp, ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Long 转 LocalDateTime
|
||||
*
|
||||
* @param timestamp 10位(秒)
|
||||
* @param zoneId 时区
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime parseLocalDateTime10(long timestamp, ZoneId zoneId) {
|
||||
Instant instant = Instant.ofEpochMilli(timestamp * 1000);
|
||||
ZoneId zone = ZoneId.systemDefault();
|
||||
return LocalDateTime.ofInstant(instant, zone);
|
||||
return LocalDateTime.ofInstant(instant, zoneId);
|
||||
}
|
||||
|
||||
/**
|
||||
* UTC(格林威治,标准)时间
|
||||
*
|
||||
* @param timestamp 13位(毫秒)/ 10位(秒)
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime parserUTC(Long timestamp) {
|
||||
if (String.valueOf(timestamp).length() == 10) {
|
||||
timestamp = timestamp * 1000;
|
||||
}
|
||||
return parseLocalDateTime13(timestamp, ZoneId.of("UTC"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,6 +334,7 @@ public class DateTimeUtil {
|
||||
return instant.toEpochMilli();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 格式化时间 <br/>
|
||||
* 格式 yyyy-MM-dd HH:mm:ss
|
||||
@@ -351,11 +387,57 @@ public class DateTimeUtil {
|
||||
return df.format(dateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取UTC(格林威治,标准)时间
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime convertUTC(LocalDateTime date) {
|
||||
return convertTimezone(date, null, "UTC");
|
||||
}
|
||||
|
||||
/** public static void main(String[] args) {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
System.out.println(df.format(zonedDateTime2Date(ZonedDateTime.now())));
|
||||
System.out.println(df2.format(date2ZonedDateTime(new Date())));
|
||||
/**
|
||||
* 时区转换(当前时区)
|
||||
*
|
||||
* @param date 时间
|
||||
* @param zoneId 转换时区
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime convertTimezone(LocalDateTime date, String zoneId) {
|
||||
return convertTimezone(date, null, zoneId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 时区转换
|
||||
*
|
||||
* @param date 时间
|
||||
* @param currentZoneId 当前时间的时区
|
||||
* @param targetZoneId 转换时区
|
||||
* @return
|
||||
*/
|
||||
public static LocalDateTime convertTimezone(LocalDateTime date, String currentZoneId, String targetZoneId) {
|
||||
ZoneId currentZone;
|
||||
if (currentZoneId == null) {
|
||||
currentZone = ZoneId.systemDefault();
|
||||
} else {
|
||||
currentZone = ZoneId.of(currentZoneId);
|
||||
}
|
||||
ZoneId targetZone = ZoneId.of(targetZoneId);
|
||||
return date.atZone(currentZone).withZoneSameInstant(targetZone).toLocalDateTime();
|
||||
}
|
||||
|
||||
|
||||
/*public static void main(String[] args) throws ParseException {
|
||||
System.out.println(parserUTC(1684140338161L));
|
||||
System.out.println(convertUTC(LocalDateTime.now()));
|
||||
Date date = DateUtil.str2dateTime("2023-05-15 08:28:05.327");
|
||||
LocalDateTime localDateTime = parseLocalDateTime(date);
|
||||
System.out.println(date);
|
||||
System.out.println(localDateTime);
|
||||
LocalDateTime utc = convertTimezone(localDateTime, "UTC", "Asia/Shanghai");
|
||||
System.out.println(utc);
|
||||
|
||||
System.out.println(getWeek4First());
|
||||
System.out.println(format(getWeek4First(LocalDate.parse("2018-02-10")).atTime(LocalTime.MIN)));
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.yexuejc.base.util;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
@@ -191,4 +192,44 @@ public class DateUtil {
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取UTC(格林威治,标准)时间
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static Date convertUTC(Date date) {
|
||||
return convertTimezone(date, null, "UTC");
|
||||
}
|
||||
|
||||
/**
|
||||
* 时区转换(当前时区)
|
||||
*
|
||||
* @param date 时间
|
||||
* @param zoneId 转换时区
|
||||
* @return
|
||||
*/
|
||||
public static Date convertTimezone(Date date, String zoneId) {
|
||||
return convertTimezone(date, null, zoneId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时区转换
|
||||
*
|
||||
* @param date 时间
|
||||
* @param currentZoneId 当前时间的时区
|
||||
* @param targetZoneId 转换时区
|
||||
* @return
|
||||
*/
|
||||
public static Date convertTimezone(Date date, String currentZoneId, String targetZoneId) {
|
||||
ZoneId currentZone;
|
||||
if (currentZoneId == null) {
|
||||
currentZone = ZoneId.systemDefault();
|
||||
} else {
|
||||
currentZone = ZoneId.of(currentZoneId);
|
||||
}
|
||||
ZoneId targetZone = ZoneId.of(targetZoneId);
|
||||
return Date.from(date.toInstant().atZone(currentZone).withZoneSameInstant(targetZone).toInstant());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,17 +5,31 @@ import com.fasterxml.jackson.dataformat.csv.CsvMapper;
|
||||
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.yexuejc.base.annotation.CsvHeader;
|
||||
import com.yexuejc.base.annotation.CsvToBean;
|
||||
import com.yexuejc.base.pojo.ReadFileBean;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
@@ -37,7 +51,7 @@ import java.util.zip.CRC32;
|
||||
public class FileUtil {
|
||||
static Logger logger = Logger.getLogger(FileUtil.class.getName());
|
||||
|
||||
private FileUtil() {
|
||||
public FileUtil() {
|
||||
}
|
||||
|
||||
private static final String TYPE_TAR_GZ = ".tar.gz";
|
||||
@@ -159,7 +173,6 @@ public class FileUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* 计算SHA1码
|
||||
*
|
||||
@@ -303,41 +316,24 @@ public class FileUtil {
|
||||
* @return
|
||||
*/
|
||||
public static String base64ToStr(File file) {
|
||||
return new String(base64(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件base64
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
public static byte[] base64(File file) {
|
||||
FileInputStream fileInputStream = null;
|
||||
byte[] data = null;
|
||||
// 读取图片字节数组
|
||||
try {
|
||||
fileInputStream = new FileInputStream(file);
|
||||
data = new byte[fileInputStream.available()];
|
||||
fileInputStream.read(data);
|
||||
fileInputStream.close();
|
||||
byte[] bytes = Files.readAllBytes(Path.of(file.getPath()));
|
||||
return Base64.getEncoder().encodeToString(bytes);
|
||||
} catch (IOException e) {
|
||||
logger.severe("The operation file is an IO exception.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 对字节数组Base64编码
|
||||
return Base64.getEncoder().encode(data);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* base64转文件
|
||||
* <p>
|
||||
* <i>
|
||||
* 文件转base64请使用 {@link FileUtil#base64(File)}
|
||||
* 文件转base64请使用 {@link FileUtil#base64ToStr(File)}
|
||||
* </i>
|
||||
*
|
||||
* @param decode {@link FileUtil#base64ToStr(File)} 的结果
|
||||
* @param fileName 文件名称(包含路径)
|
||||
* @param fileName 保存文件名称(包含路径)
|
||||
* @return 返回保存地址
|
||||
*/
|
||||
public static String base64ToFile(String decode, String fileName) {
|
||||
@@ -348,7 +344,7 @@ public class FileUtil {
|
||||
* base64转文件
|
||||
* <p>
|
||||
* <i>
|
||||
* 文件转base64请使用 {@link FileUtil#base64(File)}
|
||||
* 文件转base64请使用 {@link FileUtil#base64ToStr(File)}
|
||||
* </i>
|
||||
*
|
||||
* @param decode baseByte
|
||||
@@ -494,24 +490,48 @@ public class FileUtil {
|
||||
* @param <T> 读取结果类型bean
|
||||
* @return
|
||||
*/
|
||||
public <T> ReadFileBean<T> readBigFile(String path, ReadFileBean<T> readFileBean, Class<T> readCls) {
|
||||
public <T> ReadFileBean<T> readBigFile(String path, ReadFileBean<T> readFileBean, Class<T> readCls) throws FileNotFoundException {
|
||||
File file = new File(path);
|
||||
judeFileExists(file);
|
||||
try {
|
||||
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
|
||||
if (!file.exists() || file.isDirectory()) {
|
||||
throw new FileNotFoundException("file:" + path + " is not found.");
|
||||
}
|
||||
try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) {
|
||||
if (readFileBean.getPointer() < 0) {
|
||||
readFileBean.setPointer(0);
|
||||
}
|
||||
randomAccessFile.seek(readFileBean.getPointer());
|
||||
readFileBean.setFileLength(randomAccessFile.length());
|
||||
List<String> datas = new ArrayList<>();
|
||||
for (int i = 0; i < readFileBean.getReadRowNum(); i++) {
|
||||
String s = randomAccessFile.readLine();
|
||||
datas.add(charsetDecode(s, StandardCharsets.UTF_8));
|
||||
int row = 1;
|
||||
String line;
|
||||
while ((line = randomAccessFile.readLine()) != null && row <= readFileBean.getReadRowNum()) {
|
||||
row++;
|
||||
readFileBean.setPointer(randomAccessFile.getFilePointer());
|
||||
datas.add(readFileBean.lineScavenge(charsetDecode(line, readFileBean.getReadCharset()))); }
|
||||
|
||||
if (StrUtil.isEmpty(datas)) {
|
||||
//无数据
|
||||
return readFileBean.setDatas(List.of());
|
||||
}
|
||||
randomAccessFile.close();
|
||||
if (path.contains(TYPE_CSV)) {
|
||||
//csv文件处理
|
||||
datas.add(0, getCsvHeader(readCls));
|
||||
List<T> dataList = readCsv(String.join("\n", datas), readCls, ',');
|
||||
com.yexuejc.base.pojo.CsvToBean csvToBean = getCsvToBean(readCls);
|
||||
readFileBean.setHeader(csvToBean.getHeader());
|
||||
if (csvToBean.isHasHeader()) {
|
||||
//文件存在header,设置header优先,没设置使用文件的
|
||||
if (StrUtil.isNotEmpty(csvToBean.getHeader())) {
|
||||
//替换header
|
||||
datas.remove(0);
|
||||
datas.add(0, csvToBean.getHeader());
|
||||
} else {
|
||||
readFileBean.setHeader(datas.get(0));
|
||||
}
|
||||
} else {
|
||||
//文件不存在header,使用设置的
|
||||
datas.add(0, csvToBean.getHeader());
|
||||
}
|
||||
|
||||
List<T> dataList = readCsv(String.join("\n", datas), readCls, csvToBean.getDelimiter());
|
||||
readFileBean.setDatas(dataList);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
@@ -523,18 +543,18 @@ public class FileUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取csv的header,使用注解{@link CsvHeader}
|
||||
* 获取csv的header,使用注解{@link CsvToBean}
|
||||
*
|
||||
* @param cls
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> String getCsvHeader(Class<T> cls) {
|
||||
CsvHeader annotation = cls.getAnnotation(CsvHeader.class);
|
||||
Assert.notNull(annotation, cls.toString() + "类上需要添加注解@CsvHeader,并指定header。");
|
||||
String header = annotation.header();
|
||||
Assert.notNull(header, cls.toString() + "类上需要添加注解@CsvHeader,并指定header。");
|
||||
return header;
|
||||
public static <T> com.yexuejc.base.pojo.CsvToBean getCsvToBean(Class<T> cls) {
|
||||
CsvToBean annotation = cls.getAnnotation(CsvToBean.class);
|
||||
Assert.notNull(annotation, cls.toString() + "类上需要添加注解@CsvToBean,并指定header。");
|
||||
com.yexuejc.base.pojo.CsvToBean csvToBean = new com.yexuejc.base.pojo.CsvToBean(
|
||||
annotation.header(), annotation.delimiter(), annotation.hasHeader());
|
||||
return csvToBean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,7 +573,6 @@ public class FileUtil {
|
||||
return new String(result, charset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提供读取IO流方法合集
|
||||
* <p>读取速度快慢顺序:</p>
|
||||
@@ -614,7 +633,6 @@ public class FileUtil {
|
||||
.collect(Collectors.joining(lineSeparator == null ? System.lineSeparator() : lineSeparator));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 读取IO流内容:Scanner A方式
|
||||
*
|
||||
@@ -637,7 +655,6 @@ public class FileUtil {
|
||||
return new Scanner(inputStream).useDelimiter("\\Z").next();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 读取IO流内容:StringBuilder方式
|
||||
*
|
||||
@@ -741,6 +758,7 @@ public class FileUtil {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*public static void main(String[] args) {
|
||||
long size = FileUtil.size(new File("E:\\OS\\deepin-15.6-amd64\\DeepinCloudPrintServerInstaller_1.0.0.1.exe"));
|
||||
System.out.println(size);
|
||||
|
||||
@@ -1,16 +1,34 @@
|
||||
package com.yexuejc.base.util;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.fasterxml.jackson.databind.type.MapType;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.yexuejc.base.converter.LocalDateDeserializer;
|
||||
import com.yexuejc.base.converter.LocalDateSerializer;
|
||||
import com.yexuejc.base.converter.LocalDateTimeDeserializer;
|
||||
import com.yexuejc.base.converter.LocalDateTimeSerializer;
|
||||
import com.yexuejc.base.converter.TimestampDeserializer;
|
||||
import com.yexuejc.base.converter.TimestampSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Logger;
|
||||
@@ -32,32 +50,102 @@ public class JsonUtil {
|
||||
/**
|
||||
* 作为单例全局使用
|
||||
*/
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
private static JsonMapper jsonMapper = new JsonMapper();
|
||||
|
||||
static {
|
||||
JsonUtil.initDefaultObjectMapper(JsonUtil.objectMapper);
|
||||
JsonUtil.setJavaTimeModule(JsonUtil.jsonMapper);
|
||||
JsonUtil.initDefaultObjectMapper(JsonUtil.jsonMapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对时间的支持
|
||||
*
|
||||
* @param jsonMapper
|
||||
*/
|
||||
private static void setJavaTimeModule(ObjectMapper jsonMapper) {
|
||||
//设置一下时区,可以和程序同步避免时区问题
|
||||
jsonMapper.setTimeZone(TimeZone.getDefault());
|
||||
jsonMapper.setDateFormat(DateUtil.DATE_TIME_FORMAT);
|
||||
|
||||
JavaTimeModule javaTime = new JavaTimeModule();
|
||||
//java time 特殊处理
|
||||
javaTime.addSerializer(LocalDate.class, new LocalDateSerializer());
|
||||
javaTime.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
|
||||
javaTime.addSerializer(Timestamp.class, new TimestampSerializer());
|
||||
|
||||
javaTime.addDeserializer(LocalDate.class, new LocalDateDeserializer());
|
||||
javaTime.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
|
||||
javaTime.addDeserializer(Timestamp.class, new TimestampDeserializer());
|
||||
jsonMapper.registerModule(javaTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化ObjectMapper为默认属性
|
||||
* <pre>
|
||||
* 1.序列化值为空时,NON_NULL:舍去字段
|
||||
* 2.JsonParser.Feature.ALLOW_SINGLE_QUOTES:解析JSON时允许使用单引号(')作为字符串的引号(true)
|
||||
* 例子:{'localDateTime':'2023-05-29T15:32:03.9770447'}
|
||||
* 3.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES:解析JSON时允许不使用引号作为字符串的引号(true)
|
||||
* 例子:{age:12};适用于基本数据类型
|
||||
* 4.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES:json对应java Bean,数据字段对不齐的情况下不报错(false)
|
||||
* 5.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS(false):用于指定是否将日期类型序列化为时间戳格式。如果启用该特性,则日期类型将被序列化为Unix时间戳(即从1970年1月1日00:00:00 GMT开始的毫秒数)。如果禁用该特性,则日期类型将以其原始格式进行序列化。
|
||||
* 例子(false):"timestamp": "2020-07-08T02:02:55.000+00:00"
|
||||
* 例子(true):"timestamp": 1594236175000
|
||||
* </pre>
|
||||
*
|
||||
* @param objectMapper
|
||||
* @param jsonMapper
|
||||
*/
|
||||
private static void initDefaultObjectMapper(ObjectMapper objectMapper) {
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
|
||||
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||
//设置一下时区,可以和程序同步避免时区问题
|
||||
objectMapper.setTimeZone(TimeZone.getDefault());
|
||||
objectMapper.setDateFormat(DateUtil.DATE_TIME_FORMAT);
|
||||
private static void initDefaultObjectMapper(ObjectMapper jsonMapper) {
|
||||
//值为空时,NON_NULL:舍去字段;ALWAYS:保留字段
|
||||
jsonMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
jsonMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
|
||||
jsonMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
||||
jsonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
jsonMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化ObjectMapper的默认属性
|
||||
* <pre>
|
||||
* 1.序列化值为空时,ALWAYS:保留字段,值为“”
|
||||
* 2.JsonParser.Feature.ALLOW_SINGLE_QUOTES:解析JSON时允许使用单引号(')作为字符串的引号(true)
|
||||
* 例子:{'localDateTime':'2023-05-29T15:32:03.9770447'}
|
||||
* 3.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES:解析JSON时允许不使用引号作为字符串的引号(true)
|
||||
* 例子:{age:12};适用于基本数据类型
|
||||
* 4.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES:json对应java Bean,数据字段对不齐的情况下不报错(false)
|
||||
* 5.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS(false):用于指定是否将日期类型序列化为时间戳格式。如果启用该特性,则日期类型将被序列化为Unix时间戳(即从1970年1月1日00:00:00 GMT开始的毫秒数)。如果禁用该特性,则日期类型将以其原始格式进行序列化。
|
||||
* 例子(false):"timestamp": "2020-07-08T02:02:55.000+00:00"
|
||||
* 例子(true):"timestamp": 1594236175000
|
||||
* 6.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT:反序列化值为空时,映射到java Bean 非字符串类型,值为:null
|
||||
* </pre>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ObjectMapper acceptEmptyStringAsNullObject() {
|
||||
JsonMapper jsonMapper = new JsonMapper();
|
||||
setJavaTimeModule(jsonMapper);
|
||||
//值为空时,ALWAYS:保留字段,默认字符串值为“”,对象值为null
|
||||
jsonMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
|
||||
jsonMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
|
||||
jsonMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
||||
jsonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
jsonMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||
jsonMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
|
||||
|
||||
//值为空时,序列化所有值为“”
|
||||
jsonMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<>() {
|
||||
@Override
|
||||
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
|
||||
jsonGenerator.writeString("");
|
||||
}
|
||||
});
|
||||
return jsonMapper;
|
||||
}
|
||||
|
||||
//TODO 待优化
|
||||
public static void initSnakeCase() {
|
||||
//驼峰下划线互转
|
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
|
||||
jsonMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,8 +174,8 @@ public class JsonUtil {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ObjectMapper getObjectMapper() {
|
||||
return objectMapper;
|
||||
public static ObjectMapper getJsonMapper() {
|
||||
return jsonMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,13 +189,13 @@ public class JsonUtil {
|
||||
T pojo = null;
|
||||
|
||||
try {
|
||||
pojo = objectMapper.readValue(json, cls);
|
||||
pojo = jsonMapper.readValue(json, cls);
|
||||
} catch (JsonParseException e) {
|
||||
log.warning("json to Object JsonParseException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonParseException.\n" + e);
|
||||
} catch (JsonMappingException e) {
|
||||
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (IOException e) {
|
||||
log.warning("json to Object IOException.\n" + e.getMessage());
|
||||
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
|
||||
return pojo;
|
||||
@@ -123,15 +211,15 @@ public class JsonUtil {
|
||||
public static <T> T json2Obj(String json, Class<T> cls) {
|
||||
T pojo = null;
|
||||
try {
|
||||
pojo = objectMapper.readValue(json, cls);
|
||||
pojo = jsonMapper.readValue(json, cls);
|
||||
} catch (JsonParseException e) {
|
||||
log.warning("json to Object JsonParseException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (JsonMappingException e) {
|
||||
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (IOException e) {
|
||||
log.warning("json to Object IOException.\n" + e.getMessage());
|
||||
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.warning("json to Object Exception.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
|
||||
return pojo;
|
||||
@@ -147,15 +235,15 @@ public class JsonUtil {
|
||||
*/
|
||||
public static <T> T json2Obj(String json, Class<T> parametrized, Class<?>... parameterClasses) {
|
||||
T pojo = null;
|
||||
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(parametrized, parameterClasses);
|
||||
JavaType javaType = jsonMapper.getTypeFactory().constructParametricType(parametrized, parameterClasses);
|
||||
try {
|
||||
pojo = objectMapper.readValue(json, javaType);
|
||||
pojo = jsonMapper.readValue(json, javaType);
|
||||
} catch (JsonParseException e) {
|
||||
log.warning("json to Object JsonParseException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (JsonMappingException e) {
|
||||
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (IOException e) {
|
||||
log.warning("json to Object IOException.\n" + e.getMessage());
|
||||
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
return pojo;
|
||||
}
|
||||
@@ -172,15 +260,15 @@ public class JsonUtil {
|
||||
*/
|
||||
public static <T> T json2Obj(String json, Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) {
|
||||
T pojo = null;
|
||||
MapType mapType = objectMapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass);
|
||||
MapType mapType = jsonMapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass);
|
||||
try {
|
||||
pojo = objectMapper.readValue(json, mapType);
|
||||
pojo = jsonMapper.readValue(json, mapType);
|
||||
} catch (JsonParseException e) {
|
||||
log.warning("json to Object JsonParseException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (JsonMappingException e) {
|
||||
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (IOException e) {
|
||||
log.warning("json to Object IOException.\n" + e.getMessage());
|
||||
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
return pojo;
|
||||
}
|
||||
@@ -195,9 +283,9 @@ public class JsonUtil {
|
||||
*/
|
||||
public static <T extends Object> T json2Obj(String json, TypeReference<T> javaType) {
|
||||
try {
|
||||
return objectMapper.readValue(json, javaType);
|
||||
return jsonMapper.readValue(json, javaType);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.warning("json to Object JsonParseException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -212,16 +300,16 @@ public class JsonUtil {
|
||||
*/
|
||||
public static <T> T json2Obj(InputStream json, Class<T> parametrized, Class<?>... parameterClasses) {
|
||||
T pojo = null;
|
||||
JavaType javaType = objectMapper.getTypeFactory().constructParametrizedType(parametrized, parametrized,
|
||||
JavaType javaType = jsonMapper.getTypeFactory().constructParametrizedType(parametrized, parametrized,
|
||||
parameterClasses);
|
||||
try {
|
||||
pojo = objectMapper.readValue(json, javaType);
|
||||
pojo = jsonMapper.readValue(json, javaType);
|
||||
} catch (JsonParseException e) {
|
||||
log.warning("json to Object JsonParseException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (JsonMappingException e) {
|
||||
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
|
||||
} catch (IOException e) {
|
||||
log.warning("json to Object IOException.\n" + e.getMessage());
|
||||
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
return pojo;
|
||||
}
|
||||
@@ -235,9 +323,9 @@ public class JsonUtil {
|
||||
public static String obj2Json(Object pojo) {
|
||||
String json = null;
|
||||
try {
|
||||
json = objectMapper.writeValueAsString(pojo);
|
||||
json = jsonMapper.writeValueAsString(pojo);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.warning("json to Object JsonProcessingException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonProcessingException.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
return json;
|
||||
}
|
||||
@@ -251,10 +339,11 @@ public class JsonUtil {
|
||||
public static String formatPrinter(Object obj) {
|
||||
String json = null;
|
||||
try {
|
||||
json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
|
||||
json = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.warning("json to Object JsonProcessingException.\n" + e.getMessage());
|
||||
log.warning("json to Object JsonProcessingException.\n" + StrUtil.printStackTrace(e));
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,9 +4,13 @@ import com.yexuejc.base.annotation.ToUeProperty;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 对象工具:对类的操作
|
||||
@@ -18,6 +22,8 @@ import java.util.*;
|
||||
* @date 2018/12/28 15:54
|
||||
*/
|
||||
public class ObjUtil {
|
||||
private static Logger log = Logger.getLogger(ObjUtil.class.getName());
|
||||
|
||||
private ObjUtil() {
|
||||
}
|
||||
|
||||
@@ -260,4 +266,150 @@ public class ObjUtil {
|
||||
return outer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制对象属性值,包含父类 (不需要getter和setter)
|
||||
* <p>includeField和excludeField同时传入,走包含逻辑,</p>
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param targetClass 目标对象class
|
||||
* @param includeField 包含对象
|
||||
* @param excludeField 排除对象
|
||||
* @param <I>
|
||||
* @param <O>
|
||||
* @return 目标对象
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <I, O> O copy(I source, Class<O> targetClass, List<String> includeField, List<String> excludeField) throws Exception {
|
||||
List<Field> allFields = getAllFields(source.getClass());
|
||||
O o = targetClass.getDeclaredConstructor().newInstance();
|
||||
if (StrUtil.isNotEmpty(excludeField) && StrUtil.isEmpty(includeField)) {
|
||||
allFields = allFields.stream().filter(f -> !excludeField.contains(f.getName())).collect(Collectors.toList());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(includeField)) {
|
||||
allFields = allFields.stream().filter(f -> includeField.contains(f.getName())).collect(Collectors.toList());
|
||||
}
|
||||
allFields.forEach(f -> {
|
||||
try {
|
||||
try {
|
||||
Field field = targetClass.getDeclaredField(f.getName());
|
||||
if (field != null) {
|
||||
f.setAccessible(true);
|
||||
Object v = f.get(source);
|
||||
f.setAccessible(false);
|
||||
field.setAccessible(true);
|
||||
field.set(o, v);
|
||||
field.setAccessible(false);
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warning(lowerCaseFirstChar(f.getName()) + " field copy failed. " + e);
|
||||
log.log(Level.FINER, lowerCaseFirstChar(f.getName()) +
|
||||
" field copy failed. The exception information is as follows:", e);
|
||||
}
|
||||
});
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* 深度复制对象
|
||||
* <p>获取source的所有getXxx。xxx作为属性,且包含父类的getXxx</p>
|
||||
* <p>查找target的xxx属性,进行反射设值</p>
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param targetClass 目标对象class
|
||||
* @param invokeSetter 设置target属性值时,是否使用setter方法设置
|
||||
* @param <I>
|
||||
* @param <O>
|
||||
* @return 目标对象
|
||||
*/
|
||||
public static <I, O> O copy(I source, Class<O> targetClass, boolean invokeSetter) throws Exception {
|
||||
List<Method> getterMethods = getAllGetterMethods(source.getClass(), "get");
|
||||
O o = targetClass.getDeclaredConstructor().newInstance();
|
||||
getterMethods.forEach(method -> {
|
||||
|
||||
String fieldName = method.getName().replace("get", "");
|
||||
try {
|
||||
Object v = method.invoke(source);
|
||||
if (invokeSetter) {
|
||||
try {
|
||||
Method setterMethod = targetClass.getDeclaredMethod("set" + fieldName, method.getReturnType());
|
||||
if (null != setterMethod) {
|
||||
setterMethod.invoke(o, v);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Field field = targetClass.getDeclaredField(lowerCaseFirstChar(fieldName));
|
||||
if (field != null) {
|
||||
field.setAccessible(true);
|
||||
field.set(o, v);
|
||||
field.setAccessible(false);
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warning(lowerCaseFirstChar(fieldName) + " field copy failed. " + e);
|
||||
log.log(Level.FINER, lowerCaseFirstChar(fieldName) +
|
||||
" field copy failed. The exception information is as follows:\n", e);
|
||||
}
|
||||
});
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有方法,包含父类
|
||||
*
|
||||
* @param beanClass
|
||||
* @param startsWith 方法的开头匹配(空,返回所有)
|
||||
* @return
|
||||
*/
|
||||
public static List<Method> getAllGetterMethods(Class<?> beanClass, String startsWith) {
|
||||
List<Method> methodList = new ArrayList<>();
|
||||
Method[] methods = beanClass.getDeclaredMethods();
|
||||
if (StrUtil.isNotEmpty(startsWith)) {
|
||||
methodList.addAll(Arrays.stream(methods)
|
||||
.filter(method -> method.getName().startsWith(startsWith))
|
||||
.collect(Collectors.toList()));
|
||||
} else {
|
||||
methodList.addAll(Arrays.asList(methods));
|
||||
}
|
||||
Class<?> superclass = beanClass.getSuperclass();
|
||||
if (superclass != null) {
|
||||
methodList.addAll(getAllGetterMethods(superclass, startsWith));
|
||||
}
|
||||
return methodList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有属性,包含父类
|
||||
*
|
||||
* @param beanClass
|
||||
* @return
|
||||
*/
|
||||
public static List<Field> getAllFields(Class<?> beanClass) {
|
||||
List<Field> fieldList = new ArrayList<>();
|
||||
while (beanClass != null) {
|
||||
fieldList.addAll(Arrays.asList(beanClass.getDeclaredFields()));
|
||||
beanClass = beanClass.getSuperclass();
|
||||
}
|
||||
return fieldList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 首字母小写
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String lowerCaseFirstChar(String str) {
|
||||
if (str == null || str.length() == 0) {
|
||||
return str;
|
||||
} else {
|
||||
return str.substring(0, 1).toLowerCase() + str.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
package com.yexuejc.base.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -19,7 +30,7 @@ public final class StrUtil {
|
||||
private StrUtil() {
|
||||
}
|
||||
|
||||
public static char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
private static char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
/**
|
||||
* 判断字符串,数组,集合 是否为空
|
||||
@@ -111,40 +122,6 @@ public final class StrUtil {
|
||||
return num.append(String.format("%010d", hashCode)).toString().substring(0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析aa=bb&cc=dd&ee=ff格式的字符串,返回HashMap
|
||||
*
|
||||
* @param urlencoded
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, String> parseUrlencoded(String urlencoded) {
|
||||
if (isEmpty(urlencoded)) {
|
||||
return null;
|
||||
}
|
||||
String[] entrys = urlencoded.split("&");
|
||||
if (isEmpty(entrys)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, String> map = new HashMap<String, String>(16);
|
||||
String[] kv = null;
|
||||
for (String entry : entrys) {
|
||||
if (isEmpty(entry)) {
|
||||
continue;
|
||||
}
|
||||
kv = entry.split("=");
|
||||
if (isEmpty(kv)) {
|
||||
continue;
|
||||
}
|
||||
if (kv.length > 1) {
|
||||
map.put(kv[0], kv[1]);
|
||||
} else {
|
||||
map.put(kv[0], null);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转换方法 把字节数组转换成16进制字符串
|
||||
*
|
||||
@@ -254,8 +231,8 @@ public final class StrUtil {
|
||||
/**
|
||||
* 对ID(32位)进行编码
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
* @param id 32位ID
|
||||
* @return 编码后的64位ID
|
||||
*/
|
||||
public static String codeId(String id) {
|
||||
if (id == null || id.length() != 32) {
|
||||
@@ -282,8 +259,8 @@ public final class StrUtil {
|
||||
/**
|
||||
* 对ID(32位)进行解码
|
||||
*
|
||||
* @param coded
|
||||
* @return
|
||||
* @param coded 编码后的64位ID
|
||||
* @return 解码后的32位ID
|
||||
*/
|
||||
public static String decodeId(String coded) {
|
||||
if (coded == null || coded.length() != 64) {
|
||||
@@ -297,6 +274,40 @@ public final class StrUtil {
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析aa=bb&cc=dd&ee=ff格式的字符串,返回HashMap
|
||||
*
|
||||
* @param urlencoded
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, String> parseUrlencoded(String urlencoded) {
|
||||
if (isEmpty(urlencoded)) {
|
||||
return null;
|
||||
}
|
||||
String[] entrys = urlencoded.split("&");
|
||||
if (isEmpty(entrys)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, String> map = new HashMap<String, String>(16);
|
||||
String[] kv = null;
|
||||
for (String entry : entrys) {
|
||||
if (isEmpty(entry)) {
|
||||
continue;
|
||||
}
|
||||
kv = entry.split("=");
|
||||
if (isEmpty(kv)) {
|
||||
continue;
|
||||
}
|
||||
if (kv.length > 1) {
|
||||
map.put(kv[0], kv[1]);
|
||||
} else {
|
||||
map.put(kv[0], null);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* map parameters 转url parameters
|
||||
*
|
||||
@@ -370,7 +381,7 @@ public final class StrUtil {
|
||||
/**
|
||||
* 下划线字符
|
||||
*/
|
||||
public static final char UNDERLINE = '_';
|
||||
private static final char UNDERLINE = '_';
|
||||
|
||||
/**
|
||||
* 字符串下划线转驼峰格式
|
||||
@@ -419,4 +430,69 @@ public final class StrUtil {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static final String NEW_LINE = "\n";
|
||||
private static final String ERROR_MESSAGE_FORMAT = "%s.%s(%s:%d)";
|
||||
|
||||
/**
|
||||
* 把异常堆栈信息转化为字符串,同时把所有的errorMessage用\n方式拼接到printStackTrace前面 -> 替代 e.printStackTrace()
|
||||
* <p>使用e.printStackTrace()不能作为字符串处理,本方法可以转换e.printStackTrace()为字符串</p>
|
||||
* <p><b>printStackTrace</b>信息从<i>Caused by:</i>C开始</p>
|
||||
*
|
||||
* @param cause
|
||||
* @return
|
||||
*/
|
||||
public static String printStackTraceAndMessage(Throwable cause) {
|
||||
if (cause != null) {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
if (isNotEmpty(cause.getMessage())) {
|
||||
msg.append(cause.getMessage()).append(NEW_LINE);
|
||||
}
|
||||
String causedMsg = printStackTrace(cause, (eMessage) -> {
|
||||
if (isNotEmpty(eMessage)) {
|
||||
msg.append(eMessage).append(NEW_LINE);
|
||||
}
|
||||
});
|
||||
return msg.append(causedMsg).toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 把异常堆栈信息转化为字符串 -> 替代 e.printStackTrace()
|
||||
* <p>使用e.printStackTrace()不能作为字符串处理,本方法可以转换e.printStackTrace()为字符串</p>
|
||||
*
|
||||
* @param cause
|
||||
* @return
|
||||
*/
|
||||
public static String printStackTrace(Throwable cause) {
|
||||
return printStackTrace(cause, (eMessage) -> {
|
||||
});
|
||||
}
|
||||
|
||||
private static String printStackTrace(Throwable cause, Consumer<String> consumer) {
|
||||
if (cause != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String cClass = cause.getClass().getName();
|
||||
String eMessage = cause.getMessage();
|
||||
StackTraceElement[] stackTrace = cause.getStackTrace();
|
||||
Throwable caused = cause.getCause();
|
||||
while (caused != null) {
|
||||
cClass = caused.getClass().getName();
|
||||
eMessage = caused.getMessage();
|
||||
stackTrace = caused.getStackTrace();
|
||||
caused = caused.getCause();
|
||||
consumer.accept(eMessage);
|
||||
}
|
||||
sb.append("Caused by: ").append(cClass).append(": ").append(eMessage).append(NEW_LINE);
|
||||
for (StackTraceElement element : stackTrace) {
|
||||
sb.append("\tat ");
|
||||
sb.append(String.format(ERROR_MESSAGE_FORMAT, element.getClassName(), element.getMethodName(),
|
||||
element.getFileName(), element.getLineNumber()));
|
||||
sb.append(NEW_LINE);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
65
src/main/java/com/yexuejc/base/util/ZipUtil.java
Normal file
65
src/main/java/com/yexuejc/base/util/ZipUtil.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package com.yexuejc.base.util;
|
||||
|
||||
import com.yexuejc.base.pojo.CreateZipFileBean;
|
||||
import net.lingala.zip4j.ZipFile;
|
||||
import net.lingala.zip4j.exception.ZipException;
|
||||
import net.lingala.zip4j.model.ExcludeFileFilter;
|
||||
import net.lingala.zip4j.model.ZipParameters;
|
||||
import net.lingala.zip4j.model.enums.CompressionMethod;
|
||||
import net.lingala.zip4j.model.enums.EncryptionMethod;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 压缩相关
|
||||
* <p>依赖于zip4j:<a href='https://github.com/srikanth-lingala/zip4j'>https://github.com/srikanth-lingala/zip4j</a></p>
|
||||
*
|
||||
* @author maxf
|
||||
* @class-name ZipUtil
|
||||
* @description 文件压缩
|
||||
* @date 2022/11/11 11:09
|
||||
*/
|
||||
public class ZipUtil {
|
||||
|
||||
/**
|
||||
* 创建压缩文件
|
||||
*
|
||||
* @param zipFileBean
|
||||
*/
|
||||
public static void createZipFile(CreateZipFileBean zipFileBean) throws ZipException {
|
||||
ZipParameters zipParameters = new ZipParameters();
|
||||
zipParameters.setCompressionMethod(CompressionMethod.STORE);
|
||||
|
||||
//加密
|
||||
zipParameters.setEncryptFiles(true);
|
||||
zipParameters.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
|
||||
ZipFile zipFile = new ZipFile(zipFileBean.getZipFile());
|
||||
if (StrUtil.isNotEmpty(zipFileBean.getEncryptPwd())) {
|
||||
zipFile = new ZipFile(zipFileBean.getZipFile(), zipFileBean.getEncryptPwd().toCharArray());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(zipFileBean.getSourceFileName())) {
|
||||
//压缩文件
|
||||
List<File> filesToAdd = new ArrayList<>(16);
|
||||
Map<String, String> fileNamesMap = new HashMap<>(16);
|
||||
zipFileBean.getSourceFileName().forEach(it -> {
|
||||
String file = zipFileBean.getSourcePath() + File.separator + it;
|
||||
filesToAdd.add(new File(file));
|
||||
fileNamesMap.put(file, it);
|
||||
});
|
||||
zipFile.renameFiles(fileNamesMap);
|
||||
zipFile.addFiles(filesToAdd, zipParameters);
|
||||
} else {
|
||||
//压缩目录
|
||||
ExcludeFileFilter excludeFileFilter = zipFileBean.getExcludeFileName()::contains;
|
||||
zipParameters.setExcludeFileFilter(excludeFileFilter);
|
||||
zipFile.addFolder(new File(zipFileBean.getSourcePath()), zipParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//checkemun key -> codeMst检索(缓存)
|
||||
//返回exception(message用区分分割文言和exp)
|
||||
Reference in New Issue
Block a user