8 Commits

Author SHA1 Message Date
yexuejc007
a260b41fae Merge remote-tracking branch 'origin/jre11' into jre11 2023-06-13 17:56:08 +08:00
yexuejc007
0754660c45 [feat] ObjUtil 增加对象的深度copy 2023-06-13 17:55:37 +08:00
0dc13a6aa1 1.5.1-jre11 2023-06-08 16:11:04 +08:00
yexuejc007
3ddd11f9c9 [update] JsonUtil 升级优化,增加特殊需求String的反序列化 2023-05-29 17:30:07 +08:00
yexuejc007
a05bb00123 [update] JsonUtil 升级优化,提供不同序列化反序列化的jsonmapper,处理反序列化时间值为空时的优化 2023-05-29 16:59:53 +08:00
yexuejc007
77a0e29916 [feat] 增加json化时对LocalDateTime,LocalDate,Timestamp时间的优化;
[version] 1.5.2-jdk11(未发布)
2023-05-17 14:02:28 +08:00
yexuejc007
b0b8cbc7ab [update] 日期时间工具丰富 2023-05-15 16:47:57 +08:00
4c77c4ebe8 AES加解密
文件压缩
FileUtil.base64ToStr 优化
兼容jdk11
2022-11-11 19:25:46 +08:00
22 changed files with 1189 additions and 103 deletions

View File

@@ -1,6 +1,20 @@
yexuejc-base 更新记录
------------------
#### version 1.5.1-jre11
**time2023-6-8 16:02:56** <br/>
**branch** jre11 <br/>
**update** <br/>
1. FileUtil 增加读取csv文件分页读取
提供读取IO流方法合集
2. 增加AES加解密
3. 增加文件压缩ZipUtil
4. DateUtilDateTimeUtil 时间操作工具优化
5. JsonUtil [feat] 增加json化时对LocalDateTime,LocalDate,Timestamp时间的优化,增加特殊场景序列化反序列化
---
#### version 1.5.0-jre8
**time2022-5-9 13:37:31** <br/>
**branch** master <br/>

30
pom.xml
View File

@@ -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>
<!-- 打包源码 -->

View File

@@ -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;
}

View 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";
}

View File

@@ -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);
}
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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)));
}
}
}

View File

@@ -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));
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -4,7 +4,6 @@ import com.yexuejc.base.util.JsonUtil;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
/**
* 分页 VO
*

View File

@@ -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,8 @@ public class ReadFileBean<T> {
this.fileLength = fileLength;
return this;
}
public String lineScavenge(String lineData) {
return this.lineScavenger.apply(lineData);
}
}

View File

@@ -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,23 +387,69 @@ 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);
}
System.out.println(getWeek4First());
System.out.println(format(getWeek4First(LocalDate.parse("2018-02-10")).atTime(LocalTime.MIN)));
System.out.println(format(getWeek4Last(LocalDate.parse("2018-02-10")).atTime(LocalTime.MAX)));
System.out.println(format(getMonth4First().atTime(LocalTime.MIN)));
System.out.println(format(getMonth4Last().atTime(LocalTime.MAX)));
/**
* 时区转换
*
* @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();
}
System.out.println(format(getYear4First().atTime(LocalTime.MIN)));
System.out.println(format(getYear4Last().atTime(LocalTime.MAX)));
}*/
/*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)));
System.out.println(format(getWeek4Last(LocalDate.parse("2018-02-10")).atTime(LocalTime.MAX)));
System.out.println(format(getMonth4First().atTime(LocalTime.MIN)));
System.out.println(format(getMonth4Last().atTime(LocalTime.MAX)));
System.out.println(format(getYear4First().atTime(LocalTime.MIN)));
System.out.println(format(getYear4Last().atTime(LocalTime.MAX)));
}*/
}

View File

@@ -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());
}
}

View File

@@ -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);

View File

@@ -1,16 +1,22 @@
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.json.JsonMapper;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.yexuejc.base.converter.*;
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 +38,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_PROPERTIESjson对应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_PROPERTIESjson对应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 +162,8 @@ public class JsonUtil {
*
* @return
*/
public static ObjectMapper getObjectMapper() {
return objectMapper;
public static ObjectMapper getJsonMapper() {
return jsonMapper;
}
/**
@@ -101,7 +177,7 @@ 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());
} catch (JsonMappingException e) {
@@ -123,7 +199,7 @@ 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());
} catch (JsonMappingException e) {
@@ -147,9 +223,9 @@ 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());
} catch (JsonMappingException e) {
@@ -172,9 +248,9 @@ 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());
} catch (JsonMappingException e) {
@@ -195,7 +271,7 @@ 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());
}
@@ -212,10 +288,10 @@ 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());
} catch (JsonMappingException e) {
@@ -235,7 +311,7 @@ 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());
}
@@ -251,7 +327,7 @@ 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());
}

View File

@@ -4,9 +4,11 @@ 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.stream.Collectors;
/**
* 对象工具:对类的操作
@@ -260,4 +262,145 @@ 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) {
throw new RuntimeException(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 -> {
try {
String fieldName = method.getName().replace("get", "");
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) {
throw new RuntimeException(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);
}
}
}

View 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)