diff --git a/README.md b/README.md index 20d3bb0..02294fe 100644 --- a/README.md +++ b/README.md @@ -7,23 +7,9 @@ gitee:https://gitee.com/jzsw-it/yexuejc-base ### 说明 1. 支持环境:java8(1.5.0开始支持java11,请使用`x.x.x-jre11`版本) 2. 该工具包基于springboot提取,按理说适用于所有java工程 -3. 其中依赖jjwt相关、validation-api,排除请使用 -> ``` -> -> -> xxx -> xxxx -> -> -> ``` -> -4. `1.1.9` 升级JWT为单例类 -5. `1.2.3` 修复RSA加密(签名)Base64Url 问题,如需使用RSA请使用1.2.3+ -6. 从`1.3.0`开始,变更组织`groupId`为`top.yexuejc`。使用者请尽快升级到`1.3.0`以上(1.3.0代码向下兼容) -7. 从`1.5.0`开始,版本分为`1.5.0-jre8`和`1.5.0-jre11`,分别对于jre8和jre11使用 +3. 从`1.5.0`开始,版本分为`1.5.0-jre8`和`1.5.0-jre11`,分别对于jre8和jre11使用 ### 使用 ->yexuejc.base.version=1.5.0-jre8 pom.xml ``` @@ -31,30 +17,10 @@ pom.xml top.yexuejc yexuejc-base - ${yexuejc.base.version} + 1.5.2-jre8 ``` - -#### 附:1.3.0之前的使用方式 -pom.xml -``` - - - com.yexuejc.base - yexuejc-base - 1.3.0以下 - - - - - yexuejc-nexus-public - yexuejc-nexus-public - https://nexus.yexuejc.club/repository/maven-public/ - - -``` - ### 工具文档 [Wiki](WIKI.md) diff --git a/UPDATE.md b/UPDATE.md index 9a818eb..8263feb 100644 --- a/UPDATE.md +++ b/UPDATE.md @@ -1,5 +1,26 @@ yexuejc-base 更新记录 ------------------ +#### version :1.5.2-jre8 +**time:2024-4-7 14:34:33**
+**branch:** jre8
+**update:**
+1. 升级相关依赖 +2. 依赖工具读取文件[FileInput.java](src/main/java/com/yexuejc/base/file/FileInput.java)从[FileUtil.java](src/main/java/com/yexuejc/base/util/FileUtil.java)中提取出来 +3. 优化[FileUtil.java](src/main/java/com/yexuejc/base/util/FileUtil.java) +4. 优化[JwtUtil.java](src/main/java/com/yexuejc/base/util/JwtUtil.java) + +--- + +#### version :1.5.1-jre8 +**time:2023-6-8 16:02:56**
+**branch:** jre11
+**update:**
+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**
diff --git a/pom.xml b/pom.xml index b84065c..62b2325 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ top.yexuejc yexuejc-base - 1.5.0-jre8 + 1.5.2-jre8 yexuejc-base https://github.com/yexuejc/yexuejc-base @@ -15,7 +15,7 @@ The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt + https://www.apache.org/licenses/LICENSE-2.0.txt @@ -42,16 +42,17 @@ https://nexus.yexuejc.top/repository/ https://maven.aliyun.com/repository/public https://jitpack.io - 0.11.5 + 0.12.5 true 1.8 - 3.0.1 + 3.0.2 2.11.0 - 1.70 - 31.1-jre - 5.2.2 - 2.13.2 + 1.78 + 33.1.0-jre + 5.2.5 + 2.17.0 + 2.11.4 UTF-8 UTF-8 @@ -92,14 +93,15 @@ org.bouncycastle - bcprov-jdk15on - ${bcprov-jdk15on.version} + bcprov-jdk18on + ${bcprov-jdk18on.version} - + com.google.guava guava ${guava.version} + true @@ -111,17 +113,34 @@ org.apache.poi poi-ooxml ${apache-poi.version} + + + org.apache.commons + commons-compress + + com.fasterxml.jackson.dataformat jackson-dataformat-csv ${jackson.version} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + + net.lingala.zip4j + zip4j + ${zip4j.version} + org.junit.jupiter junit-jupiter-api - 5.8.1 + 5.9.2 test @@ -133,7 +152,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.13.0 UTF-8 8 @@ -144,7 +163,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 attach-sources diff --git a/src/main/java/com/yexuejc/base/annotation/CsvHeader.java b/src/main/java/com/yexuejc/base/annotation/CsvHeader.java deleted file mode 100644 index 30ff72c..0000000 --- a/src/main/java/com/yexuejc/base/annotation/CsvHeader.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.yexuejc.base.annotation; - -import java.lang.annotation.*; - -/** - * 设置csv header - * - * @author MAXF-MAC - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -public @interface CsvHeader { - - /** - * 在类头上设置csv格式的header - * @return - */ - String header(); -} diff --git a/src/main/java/com/yexuejc/base/annotation/CsvToBean.java b/src/main/java/com/yexuejc/base/annotation/CsvToBean.java new file mode 100644 index 0000000..548ec44 --- /dev/null +++ b/src/main/java/com/yexuejc/base/annotation/CsvToBean.java @@ -0,0 +1,36 @@ +package com.yexuejc.base.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 设置csv header + * + * @author MAXF-MAC + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface CsvToBean { + + /** + * 在类头上设置csv格式的header + * csv文件和java bean的映射 + */ + String header(); + + /** + * csv文件的分割符号 + */ + char delimiter() default ','; + + /** + * CSV文件是否有header + */ + boolean hasHeader() default false; +} diff --git a/src/main/java/com/yexuejc/base/constant/DateConsts.java b/src/main/java/com/yexuejc/base/constant/DateConsts.java new file mode 100644 index 0000000..57509d1 --- /dev/null +++ b/src/main/java/com/yexuejc/base/constant/DateConsts.java @@ -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"; +} diff --git a/src/main/java/com/yexuejc/base/converter/LocalDateDeserializer.java b/src/main/java/com/yexuejc/base/converter/LocalDateDeserializer.java new file mode 100644 index 0000000..72be746 --- /dev/null +++ b/src/main/java/com/yexuejc/base/converter/LocalDateDeserializer.java @@ -0,0 +1,44 @@ +package com.yexuejc.base.converter; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +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; + +/** + * json转LocalDate + * + * @author yexuejc + * @date 2022/10/08 + */ +public class LocalDateDeserializer extends JsonDeserializer { + + @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); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/yexuejc/base/converter/LocalDateSerializer.java b/src/main/java/com/yexuejc/base/converter/LocalDateSerializer.java new file mode 100644 index 0000000..3312429 --- /dev/null +++ b/src/main/java/com/yexuejc/base/converter/LocalDateSerializer.java @@ -0,0 +1,23 @@ +package com.yexuejc.base.converter; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +/** + * localDate转json + * + * @author yexuejc + * @date 2022/10/08 + */ +public class LocalDateSerializer extends JsonSerializer { + @Override + public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException { + jsonGenerator.writeString(localDate.format(DateTimeFormatter.ISO_DATE)); + } +} \ No newline at end of file diff --git a/src/main/java/com/yexuejc/base/converter/LocalDateTimeDeserializer.java b/src/main/java/com/yexuejc/base/converter/LocalDateTimeDeserializer.java new file mode 100644 index 0000000..e1bd9a2 --- /dev/null +++ b/src/main/java/com/yexuejc/base/converter/LocalDateTimeDeserializer.java @@ -0,0 +1,44 @@ +package com.yexuejc.base.converter; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +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; + +/** + * json转LocalDateTime + * + * @author yexuejc + * @date 2022/10/08 + */ +public class LocalDateTimeDeserializer extends JsonDeserializer { + @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)); + } + } + +} diff --git a/src/main/java/com/yexuejc/base/converter/LocalDateTimeSerializer.java b/src/main/java/com/yexuejc/base/converter/LocalDateTimeSerializer.java new file mode 100644 index 0000000..fc3c497 --- /dev/null +++ b/src/main/java/com/yexuejc/base/converter/LocalDateTimeSerializer.java @@ -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 { + @Override + public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, + SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeString(localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); + } +} \ No newline at end of file diff --git a/src/main/java/com/yexuejc/base/converter/StringDeserializer.java b/src/main/java/com/yexuejc/base/converter/StringDeserializer.java new file mode 100644 index 0000000..f3e5483 --- /dev/null +++ b/src/main/java/com/yexuejc/base/converter/StringDeserializer.java @@ -0,0 +1,38 @@ +package com.yexuejc.base.converter; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +/** + *
+ * json中的“”转String对象时值为null
+ * 例子:{str:""} ->
+ * JsonBean{
+ *  public String str;
+ * }
+ * str的值为null [不使用{@link StringDeserializer},str的值为“”]
+ * 
+ * + *
+ *     使用方式:
+ *     jsonMapper.registerModule(new SimpleModule().addDeserializer(String.class, new StringDeserializer()));
+ * 
+ * + * @author yexuejc + * @date 2022/10/08 + */ +public class StringDeserializer extends JsonDeserializer { + + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + String timeString = jsonParser.getValueAsString(); + if ("".equals(timeString)) { + return null; + } + return timeString; + } +} \ No newline at end of file diff --git a/src/main/java/com/yexuejc/base/converter/TimestampDeserializer.java b/src/main/java/com/yexuejc/base/converter/TimestampDeserializer.java new file mode 100644 index 0000000..4a2e8b7 --- /dev/null +++ b/src/main/java/com/yexuejc/base/converter/TimestampDeserializer.java @@ -0,0 +1,46 @@ +package com.yexuejc.base.converter; + +import java.io.IOException; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +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; + +/** + * json转LocalDateTime + * + * @author yexuejc + * @date 2022/10/08 + */ +public class TimestampDeserializer extends JsonDeserializer { + @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))); + } + } + +} diff --git a/src/main/java/com/yexuejc/base/converter/TimestampSerializer.java b/src/main/java/com/yexuejc/base/converter/TimestampSerializer.java new file mode 100644 index 0000000..a2e37f6 --- /dev/null +++ b/src/main/java/com/yexuejc/base/converter/TimestampSerializer.java @@ -0,0 +1,25 @@ +package com.yexuejc.base.converter; + +import java.io.IOException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.yexuejc.base.constant.DateConsts; + +/** + * Timestamp转json + * + * @author yexuejc + * @date 2022/10/08 + */ +public class TimestampSerializer extends JsonSerializer { + @Override + public void serialize(Timestamp timestamp, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException { + SimpleDateFormat df = new SimpleDateFormat(DateConsts.DATE_TIMESTAMP); + jsonGenerator.writeString(df.format(timestamp)); + } +} \ No newline at end of file diff --git a/src/main/java/com/yexuejc/base/pojo/CsvToBean.java b/src/main/java/com/yexuejc/base/pojo/CsvToBean.java new file mode 100644 index 0000000..7787026 --- /dev/null +++ b/src/main/java/com/yexuejc/base/pojo/CsvToBean.java @@ -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 hasHeader() { + return hasHeader; + } + + public CsvToBean setHasHeader(boolean hasHeader) { + this.hasHeader = hasHeader; + return this; + } +} diff --git a/src/main/java/com/yexuejc/base/pojo/PagerVO.java b/src/main/java/com/yexuejc/base/pojo/PagerVO.java index e23aeda..bf441e4 100644 --- a/src/main/java/com/yexuejc/base/pojo/PagerVO.java +++ b/src/main/java/com/yexuejc/base/pojo/PagerVO.java @@ -4,7 +4,6 @@ import com.yexuejc.base.util.JsonUtil; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; - /** * 分页 VO * diff --git a/src/main/java/com/yexuejc/base/pojo/ReadFileBean.java b/src/main/java/com/yexuejc/base/pojo/ReadFileBean.java index 314a96c..0e5c4d4 100644 --- a/src/main/java/com/yexuejc/base/pojo/ReadFileBean.java +++ b/src/main/java/com/yexuejc/base/pojo/ReadFileBean.java @@ -1,6 +1,9 @@ package com.yexuejc.base.pojo; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.function.Function; /** * @author maxf @@ -34,7 +37,18 @@ public class ReadFileBean { * 文件的length */ private long fileLength; + /** + * csv文件存在header + */ + private String header; + private Charset readCharset = StandardCharsets.UTF_8; + public Function 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 +56,24 @@ public class ReadFileBean { this.endRowNum = 0; } + public Charset getReadCharset() { + return readCharset; + } + + public ReadFileBean setReadCharset(Charset readCharset) { + this.readCharset = readCharset; + return this; + } + + public String getHeader() { + return header; + } + + public ReadFileBean setHeader(String header) { + this.header = header; + return this; + } + public int getReadRowNum() { return readRowNum; } @@ -82,4 +114,12 @@ public class ReadFileBean { this.fileLength = fileLength; return this; } + + public String lineScavenge(String lineData) { + return this.lineScavenger.apply(lineData); + } + + public boolean hasNext() { + return this.fileLength > this.pointer; + } } diff --git a/src/main/java/com/yexuejc/base/util/DateTimeUtil.java b/src/main/java/com/yexuejc/base/util/DateTimeUtil.java index 97041fe..95924e4 100644 --- a/src/main/java/com/yexuejc/base/util/DateTimeUtil.java +++ b/src/main/java/com/yexuejc/base/util/DateTimeUtil.java @@ -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(); } + /** * 格式化时间
* 格式 yyyy-MM-dd HH:mm:ss @@ -351,23 +387,71 @@ 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))); + System.out.println(parseLocalDateTime10(System.currentTimeMillis() / 1000)); + System.out.println(parseLocalDateTime13(System.currentTimeMillis())); + + }*/ } diff --git a/src/main/java/com/yexuejc/base/util/DateUtil.java b/src/main/java/com/yexuejc/base/util/DateUtil.java index 7cd93fe..5bdcdd3 100644 --- a/src/main/java/com/yexuejc/base/util/DateUtil.java +++ b/src/main/java/com/yexuejc/base/util/DateUtil.java @@ -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; @@ -58,8 +59,8 @@ public class DateUtil { /** * 比较两个日期大小 * - * @param date1 - * @param date2 + * @param date1 格式 yyyy-MM-dd + * @param date2 格式 yyyy-MM-dd * @return date1>date2返回1;date1=date2返回0;date1 0) { - digest.update(buffer, 0, len); - } - String sha1 = new BigInteger(1, digest.digest()).toString(16); - int length = 40 - sha1.length(); - if (length > 0) { - for (int i = 0; i < length; i++) { - sha1 = "0" + sha1; - } - } - return sha1; - } catch (NoSuchAlgorithmException e) { - logger.severe("system algorithm error."); - e.printStackTrace(); - } catch (FileNotFoundException e) { - logger.severe("file doesn't exist or is not a file"); - e.printStackTrace(); - } catch (IOException e) { - logger.severe("The operation file is an IO exception."); - e.printStackTrace(); - } finally { - try { - if (in != null) { - in.close(); - } - } catch (IOException e) { - logger.severe("close FileInputStream IO exception."); - } - } - return null; + return getDigest(file, "SHA-1"); } - /*** - * 计算SHA1码 - * - * @return String 适用于上G大的文件 - * @throws NoSuchAlgorithmException - * */ - public static String sha1ByBigFile(File file) { - MessageDigest messagedigest = null; - try { - messagedigest = MessageDigest.getInstance("SHA-1"); - FileInputStream in = new FileInputStream(file); - FileChannel ch = in.getChannel(); - MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); - messagedigest.update(byteBuffer); - return StrUtil.toHex(messagedigest.digest()); - } catch (NoSuchAlgorithmException e) { - logger.severe("system algorithm error."); - e.printStackTrace(); - } catch (FileNotFoundException e) { - logger.severe("file doesn't exist or is not a file"); - e.printStackTrace(); - } catch (IOException e) { - logger.severe("The operation file is an IO exception."); - e.printStackTrace(); - } - return null; - } - /** * 文件md5 * @@ -195,66 +150,40 @@ public class FileUtil { * @return */ public static String md5(File file) { - FileInputStream in = null; - try { - in = new FileInputStream(file); - MessageDigest digest = MessageDigest.getInstance("MD5"); - byte[] buffer = new byte[1024 * 1024 * 10]; - - int len = 0; - while ((len = in.read(buffer)) > 0) { - digest.update(buffer, 0, len); - } - String md5 = new BigInteger(1, digest.digest()).toString(16); - int length = 32 - md5.length(); - if (length > 0) { - for (int i = 0; i < length; i++) { - md5 = "0" + md5; - } - } - return md5; - } catch (IOException e) { - logger.severe("The operation file is an IO exception."); - } catch (NoSuchAlgorithmException e) { - logger.severe("system algorithm error."); - } finally { - try { - if (in != null) { - in.close(); - } - } catch (IOException e) { - logger.severe("close FileInputStream IO exception."); - } - } - return null; + return getDigest(file, "MD5"); } /** - * 对一个文件获取md5值 - * - * @return md5串 - * @throws NoSuchAlgorithmException + * 获取文件的散列值 + * @param file + * @param digestCode + * @return */ - public static String md5ByBigFile(File file) { - - MessageDigest messagedigest = null; - try { - messagedigest = MessageDigest.getInstance("MD5"); - FileInputStream in = new FileInputStream(file); - FileChannel ch = in.getChannel(); - MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, - file.length()); - messagedigest.update(byteBuffer); - return StrUtil.toHex(messagedigest.digest()); + private static String getDigest(File file, String digestCode) { + try (FileInputStream in = new FileInputStream(file)) { + MessageDigest digest = MessageDigest.getInstance(digestCode); + FileChannel channel = in.getChannel(); + ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); // 1MB 缓冲区 + // 读取文件内容并更新 MessageDigest + while (channel.read(buffer) != -1) { + buffer.flip(); // 将 Buffer 从写模式切换到读模式 + digest.update(buffer); // 更新 MessageDigest + buffer.clear(); // 清空 Buffer + } + // 计算最终的 SHA-1 散列值 + byte[] sha1Bytes = digest.digest(); + // 将字节数组转换为十六进制字符串 + StringBuilder sha1Builder = new StringBuilder(); + for (byte b : sha1Bytes) { + sha1Builder.append(String.format("%02x", b)); + } + return sha1Builder.toString(); } catch (NoSuchAlgorithmException e) { - logger.severe("system algorithm error."); - e.printStackTrace(); + logger.log(Level.SEVERE, "system algorithm error.", e); } catch (FileNotFoundException e) { - logger.severe("file doesn't exist or is not a file"); - e.printStackTrace(); + logger.log(Level.SEVERE, "file doesn't exist or is not a file", e); } catch (IOException e) { - logger.severe("The operation file is an IO exception."); - e.printStackTrace(); + logger.log(Level.SEVERE, "The operation file is an IO exception.", e); } return null; } @@ -262,37 +191,24 @@ public class FileUtil { /** * 获取文件CRC32码 * - * @return String + * @return 获取失败返回-1 */ - public static String crc32(File file) { + public static long crc32(File file) { CRC32 crc32 = new CRC32(); // MessageDigest.get - FileInputStream fileInputStream = null; - try { - fileInputStream = new FileInputStream(file); - byte[] buffer = new byte[8192]; + try (FileInputStream fileInputStream = new FileInputStream(file);) { + byte[] buffer = new byte[1024 * 1024]; int length; while ((length = fileInputStream.read(buffer)) != -1) { crc32.update(buffer, 0, length); } - return crc32.getValue() + ""; + return crc32.getValue(); } catch (FileNotFoundException e) { - logger.severe("file doesn't exist or is not a file"); - e.printStackTrace(); - return null; + logger.log(Level.SEVERE, "file doesn't exist or is not a file", e); + return -1; } catch (IOException e) { - logger.severe("The operation file is an IO exception."); - e.printStackTrace(); - return null; - } finally { - try { - if (fileInputStream != null) { - fileInputStream.close(); - } - } catch (IOException e) { - logger.severe("close FileInputStream IO exception."); - e.printStackTrace(); - } + logger.log(Level.SEVERE, "The operation file is an IO exception.", e); + return -1; } } @@ -303,44 +219,27 @@ 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(Paths.get(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转文件 *

* - * 文件转base64请使用 {@link FileUtil#base64(File)} + * 文件转base64请使用 {@link FileUtil#base64ToStr(File)} * * * @param decode {@link FileUtil#base64ToStr(File)} 的结果 * @param fileName 文件名称(包含路径) * @return 返回保存地址 */ - public static String base64ToFile(String decode, String fileName) { + public static String base64ToFile(String decode, String fileName) throws IOException { return base64ToFile(Base64.getDecoder().decode(decode.getBytes()), fileName); } @@ -348,29 +247,16 @@ public class FileUtil { * base64转文件 *

* - * 文件转base64请使用 {@link FileUtil#base64(File)} + * 文件转base64请使用 {@link FileUtil#base64ToStr(File)}} * * * @param decode baseByte * @param fileName 文件名称(包含路径) * @return 返回保存地址 */ - public static String base64ToFile(byte[] decode, String fileName) { - - FileOutputStream out = null; - try { - out = new FileOutputStream(fileName); + public static String base64ToFile(byte[] decode, String fileName) throws IOException { + try (FileOutputStream out = new FileOutputStream(fileName)) { out.write(decode); - } catch (IOException ioe) { - ioe.printStackTrace(); - } finally { - try { - if (out != null) { - out.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } } return fileName; } @@ -378,50 +264,18 @@ public class FileUtil { /** * 获取文件大小 :直接返回大小 * - * @param f + * @param path 文件地址 * @return f.length() */ - public static long size(File f) { - if (f.exists() && f.isFile()) { - return f.length(); + public static long size(Path path) throws IOException { + if (Files.exists(path) && Files.isRegularFile(path)) { + return Files.size(path); } else { logger.info("file doesn't exist or is not a file"); } return 0; } - /** - * 获取文件大小 : 用流的方式获取 - * - * @param f - * @return - */ - public static long size4Stream(File f) { - FileChannel fc = null; - try { - if (f.exists() && f.isFile()) { - FileInputStream fis = new FileInputStream(f); - fc = fis.getChannel(); - return fc.size(); - } else { - logger.info("file doesn't exist or is not a file"); - } - } catch (FileNotFoundException e) { - logger.severe("file doesn't exist or is not a file"); - } catch (IOException e) { - logger.severe("The operation file is an IO exception."); - } finally { - if (null != fc) { - try { - fc.close(); - } catch (IOException e) { - logger.severe("close FileInputStream IO exception."); - } - } - } - return 0; - } - /** * 字符串(csv格式)转 对象 * @@ -448,14 +302,15 @@ public class FileUtil { * * @param csvFilePath 文件地址 * @param cls 读取转化的对象 - * @param hasHeader 是否存在header + * @param header 解析列对应的java字段;用delimiter分割 + * @param hasHeader csv文件中第一行是否是header * @param delimiter 分隔符.默认【,】 * @param * @return */ - public static List readCsv(final String csvFilePath, Class cls, boolean hasHeader, char delimiter) { + public static List readCsv(final String csvFilePath, Class cls, boolean hasHeader, String header, char delimiter) { if (!isFileExist(csvFilePath)) { - throw new RuntimeException(String.format("解析用的csv:\u0020[%s] 文件不存在。", csvFilePath)); + throw new RuntimeException(String.format("解析用的csv: [%s] 文件不存在。", csvFilePath)); } if (StrUtil.isEmpty(delimiter)) { delimiter = ','; @@ -463,7 +318,12 @@ public class FileUtil { try { File csvFile = new File(csvFilePath); CsvMapper csvMapper = new CsvMapper(); - CsvSchema csvSchema = csvMapper.typedSchemaFor(cls).withStrictHeaders(hasHeader).withColumnSeparator(delimiter).withComments(); + CsvSchema.Builder builder = CsvSchema.builder(); + if (StrUtil.isNotEmpty(header)) { + builder.addColumns(Arrays.asList(header.split(String.valueOf(delimiter))), CsvSchema.ColumnType.STRING); + } + CsvSchema csvSchema = builder.build().withColumnSeparator(delimiter).withSkipFirstDataRow(hasHeader).withStrictHeaders(hasHeader).withComments(); + MappingIterator recordIterator = csvMapper.readerWithTypedSchemaFor(cls).with(csvSchema).readValues(csvFile); return recordIterator.readAll(); } catch (IOException e) { @@ -471,70 +331,74 @@ public class FileUtil { } } - /** - * 判断文件是否存在 - * - * @param filePath - * @return - */ - public static boolean isFileExist(String filePath) { - if (StrUtil.isEmpty(filePath)) { - return false; - } - - File file = new File(filePath); - return file.exists() && !file.isDirectory(); - } - /** * 分段读取大文件 * - * @param path 文件路径 + * @param csvFilePath 文件路径 * @param readFileBean 分段每次读取的bean 初始值需要设置每次读取的行数 * @param 读取结果类型bean * @return */ - public ReadFileBean readBigFile(String path, ReadFileBean readFileBean, Class readCls) { - File file = new File(path); - judeFileExists(file); - try { - RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r"); + public static ReadFileBean readBigFile(String csvFilePath, ReadFileBean readFileBean, Class readCls) throws IOException { + if (!isFileExist(csvFilePath)) { + throw new FileNotFoundException(String.format("解析用的csv: [%s] 文件不存在。", csvFilePath)); + } + if (!csvFilePath.endsWith(TYPE_CSV)) { + throw new IOException(String.format("解析用的csv: [%s] 文件不是CSV文件格式。", csvFilePath)); + } + List datas = new ArrayList<>(); + try (RandomAccessFile randomAccessFile = new RandomAccessFile(new File(csvFilePath), "r")) { + if (readFileBean.getPointer() < 0) { + readFileBean.setPointer(0); + } randomAccessFile.seek(readFileBean.getPointer()); readFileBean.setFileLength(randomAccessFile.length()); - List datas = new ArrayList<>(); - for (int i = 0; i < readFileBean.getReadRowNum(); i++) { - String s = randomAccessFile.readLine(); - datas.add(charsetDecode(s, StandardCharsets.UTF_8)); + int row = 0; + String line; + while ((line = randomAccessFile.readLine()) != null && row <= readFileBean.getReadRowNum()) { + row++; readFileBean.setPointer(randomAccessFile.getFilePointer()); + datas.add(readFileBean.lineScavenge(charsetDecode(line, readFileBean.getReadCharset()))); } - randomAccessFile.close(); - if (path.contains(TYPE_CSV)) { - //csv文件处理 - datas.add(0, getCsvHeader(readCls)); - List dataList = readCsv(String.join("\n", datas), readCls, ','); - readFileBean.setDatas(dataList); - } - } catch (FileNotFoundException e) { - logger.severe("file exists." + e.getMessage()); - } catch (IOException e) { - logger.severe("read file error." + e.getMessage()); } + if (StrUtil.isEmpty(datas)) { + //无数据 + return readFileBean.setDatas(new ArrayList<>()); + } + + //csv文件处理 + com.yexuejc.base.pojo.CsvToBean csvToBean = getCsvToBean(readCls); + readFileBean.setHeader(csvToBean.getHeader()); + if (csvToBean.hasHeader()) { + //文件存在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 dataList = readCsv(String.join("\n", datas), readCls, csvToBean.getDelimiter()); + readFileBean.setDatas(dataList); return readFileBean; } /** - * 获取csv的header,使用注解{@link CsvHeader} + * 获取csv的header,使用注解{@link CsvToBean} * * @param cls * @param * @return */ - public static String getCsvHeader(Class 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 com.yexuejc.base.pojo.CsvToBean getCsvToBean(Class cls) { + CsvToBean annotation = cls.getAnnotation(CsvToBean.class); + Assert.notNull(annotation, cls + "类上需要添加注解@CsvToBean,并指定header。"); + return new com.yexuejc.base.pojo.CsvToBean(annotation.header(), annotation.delimiter(), annotation.hasHeader()); } /** @@ -552,225 +416,4 @@ public class FileUtil { } return new String(result, charset); } - - - /** - * 提供读取IO流方法合集 - *

读取速度快慢顺序:

- * 1. {@link #read4Buffer(InputStream, Charset)}
- * 2. {@link #read4IOUtilsCopy(InputStream, Charset)}
- * 3. {@link #read4ByteStreams(InputStream, Charset)}
- * 4. {@link #read4Byte(InputStream, Charset)}
- * 5. {@link #read4StringBuilder(InputStream, Charset)}
- * 6. {@link #read4BufferedReaderParallel(InputStream, Charset, String)}
- * 7. {@link #read4BufferedReader(InputStream, Charset, String)}
- * 8. {@link #read4ScannerA(InputStream)}
- * 9. {@link #read4BufferIO(InputStream, Charset)}
- * 10. {@link #read4IOUtils(InputStream, Charset)}
- * 11. {@link #read4ScannerZ(InputStream)}
- * 12. {@link #read4CharStreams(InputStream, Charset)}
- */ - public static class FileInput { - /** - * 读取IO流内容:byte方式 - * - * @param inputStream - * @param charset 编码:默认 {@link Charset#defaultCharset()} - * @return - * @throws IOException - */ - public static String read4Byte(InputStream inputStream, Charset charset) throws IOException { - byte[] bytes = new byte[inputStream.available()]; - inputStream.read(bytes); - return new String(bytes, charset == null ? Charset.defaultCharset() : charset); - } - - /** - * 读取IO流内容:BufferedReader方式 - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @param lineSeparator 换行方式:默认跟随系统 {@link System#lineSeparator()} - * @return - */ - public static String read4BufferedReader(InputStream inputStream, Charset charset, String lineSeparator) { - return new BufferedReader( - new InputStreamReader(inputStream, charset == null ? Charset.defaultCharset() : charset) - ).lines().collect(Collectors.joining(lineSeparator == null ? System.lineSeparator() : lineSeparator)); - } - - /** - * 读取IO流内容:BufferedReader 并行方式 - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @param lineSeparator 换行方式:默认跟随系统 {@link System#lineSeparator()} - * @return - */ - public static String read4BufferedReaderParallel(InputStream inputStream, Charset charset, String lineSeparator) { - return new BufferedReader( - new InputStreamReader(inputStream, charset == null ? Charset.defaultCharset() : charset) - ).lines().parallel() - .collect(Collectors.joining(lineSeparator == null ? System.lineSeparator() : lineSeparator)); - } - - - /** - * 读取IO流内容:Scanner A方式 - * - * @param inputStream - * @return - */ - public static String read4ScannerA(InputStream inputStream) { - Scanner s = new Scanner(inputStream).useDelimiter("\\A"); - String str = s.hasNext() ? s.next() : ""; - return str; - } - - /** - * 读取IO流内容:Scanner Z方式 - * - * @param inputStream - * @return - */ - public static String read4ScannerZ(InputStream inputStream) { - return new Scanner(inputStream).useDelimiter("\\Z").next(); - } - - - /** - * 读取IO流内容:StringBuilder方式 - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @return - */ - public static String read4StringBuilder(InputStream inputStream, Charset charset) throws IOException { - StringBuilder sb = new StringBuilder(); - String line; - BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, charset == null ? Charset.defaultCharset() : charset)); - while ((line = br.readLine()) != null) { - sb.append(line); - } - return sb.toString(); - } - - /** - * 读取IO流内容:ByteArrayOutputStream方式 - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @return - */ - public static String read4Buffer(InputStream inputStream, Charset charset) throws IOException { - ByteArrayOutputStream result = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int length; - while ((length = inputStream.read(buffer)) != -1) { - result.write(buffer, 0, length); - } - return result.toString(charset == null ? Charset.defaultCharset().name() : charset.name()); - } - - /** - * 读取IO流内容:BufferedInputStream+ByteArrayOutputStream方式 - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @return - */ - public static String read4BufferIO(InputStream inputStream, Charset charset) throws IOException { - BufferedInputStream bis = new BufferedInputStream(inputStream); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - int result = bis.read(); - while (result != -1) { - buf.write((byte) result); - result = bis.read(); - } - return buf.toString(charset == null ? Charset.defaultCharset().name() : charset.name()); - } - - /** - * 读取IO流内容: 依赖于commons-io:commons-io {@link IOUtils#copy(Reader, OutputStream, Charset)} - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @return - * @throws IOException - */ - public static String read4IOUtilsCopy(InputStream inputStream, Charset charset) throws IOException { - StringWriter writer = new StringWriter(); - IOUtils.copy(inputStream, writer, charset == null ? Charset.defaultCharset() : charset); - return writer.toString(); - } - - /** - * 读取IO流内容: 依赖于commons-io:commons-io {@link IOUtils#toString(InputStream, Charset)} - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @return - * @throws IOException - */ - public static String read4IOUtils(InputStream inputStream, Charset charset) throws IOException { - return IOUtils.toString(inputStream, charset == null ? Charset.defaultCharset() : charset); - } - - /** - * 读取IO流内容: 依赖于com.google.guava:guava {@link CharStreams#toString(Readable)} - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @return - * @throws IOException - */ - public static String read4CharStreams(InputStream inputStream, Charset charset) throws IOException { - return CharStreams.toString(new InputStreamReader(inputStream, charset == null ? Charset.defaultCharset() : charset)); - } - - /** - * 读取IO流内容: 依赖于com.google.guava:guava {@link ByteStreams#toByteArray(InputStream)} - * - * @param inputStream - * @param charset 编码:默认跟随系统 {@link Charset#defaultCharset()} - * @return - * @throws IOException - */ - public static String read4ByteStreams(InputStream inputStream, Charset charset) throws IOException { - return new String(ByteStreams.toByteArray(inputStream), charset == null ? Charset.defaultCharset() : charset); - } - } - - /*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); - System.out.println(1024 * 1024 * 5); - if (size > 1024 * 1024 * 5) { - System.out.println("文件最大5M"); - return; - } - - long s1 = fileSize(new File("E:\\OS\\cn_windows_10_consumer_editions_version_1803_updated_march_2018_x64_dvd_12063766.iso")); - System.out.println(s1); - long s2 = fileSize4Stream(new File("E:\\OS\\cn_windows_10_consumer_editions_version_1803_updated_march_2018_x64_dvd_12063766.iso")); - System.out.println(s2); - - String s1 = base64(new File("C:\\Users\\Administrator\\Desktop\\a.html")); - System.out.println(s1); - - String s = sha1(new File("C:\\Users\\Administrator\\Desktop\\a.html")); - String s2 = sha1ByBigFile(new File("C:\\Users\\Administrator\\Desktop\\a.html")); - System.out.println(s); - System.out.println(s2); - - - String md5 = md5(new File("C:\\Users\\Administrator\\Desktop\\a.html")); - String md52 = md5ByBigFile(new File("C:\\Users\\Administrator\\Desktop\\a.html")); - System.out.println(md5); - System.out.println(md52); - - - String crc32 = crc32(new File("C:\\Users\\Administrator\\Desktop\\a.html")); - System.out.println(crc32); - }*/ } diff --git a/src/main/java/com/yexuejc/base/util/JsonUtil.java b/src/main/java/com/yexuejc/base/util/JsonUtil.java index faa5fe8..bea3786 100644 --- a/src/main/java/com/yexuejc/base/util/JsonUtil.java +++ b/src/main/java/com/yexuejc/base/util/JsonUtil.java @@ -1,19 +1,37 @@ package com.yexuejc.base.util; +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; 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 java.io.IOException; -import java.io.InputStream; -import java.util.Map; -import java.util.TimeZone; -import java.util.logging.Logger; +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; /** * json工具类,基于jackson @@ -24,7 +42,7 @@ import java.util.logging.Logger; * @date 2018/9/3 15:28 */ public class JsonUtil { - private static Logger log = Logger.getLogger(JsonUtil.class.getName()); + private static final Logger log = Logger.getLogger(JsonUtil.class.getName()); private JsonUtil() { } @@ -32,32 +50,103 @@ public class JsonUtil { /** * 作为单例全局使用 */ - private static ObjectMapper objectMapper = new ObjectMapper(); + private static final JsonMapper jsonMapper = new JsonMapper(); static { - JsonUtil.initDefaultObjectMapper(JsonUtil.objectMapper); + 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为默认属性 + *
+     *     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
+     * 
* - * @param objectMapper + * @param jsonMapper + * @return */ - 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 ObjectMapper initDefaultObjectMapper(ObjectMapper jsonMapper) { + JsonUtil.setJavaTimeModule(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); + return jsonMapper; + } + + /** + * 初始化ObjectMapper的默认属性 + *
+     *     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
+     * 
+ * + * @return + */ + public static ObjectMapper acceptEmptyStringAsNullObject(JsonMapper 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 +175,8 @@ public class JsonUtil { * * @return */ - public static ObjectMapper getObjectMapper() { - return objectMapper; + public static ObjectMapper getJsonMapper() { + return jsonMapper; } /** @@ -101,13 +190,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 +212,15 @@ public class JsonUtil { public static T json2Obj(String json, Class 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 +236,15 @@ public class JsonUtil { */ public static T json2Obj(String json, Class 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 +261,15 @@ public class JsonUtil { */ public static T json2Obj(String json, Class 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 +284,9 @@ public class JsonUtil { */ public static T json2Obj(String json, TypeReference 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 +301,16 @@ public class JsonUtil { */ public static T json2Obj(InputStream json, Class 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 +324,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 +340,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; } + } \ No newline at end of file diff --git a/src/main/java/com/yexuejc/base/util/JwtUtil.java b/src/main/java/com/yexuejc/base/util/JwtUtil.java index 0fa4172..88b195c 100644 --- a/src/main/java/com/yexuejc/base/util/JwtUtil.java +++ b/src/main/java/com/yexuejc/base/util/JwtUtil.java @@ -1,10 +1,12 @@ package com.yexuejc.base.util; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; - import java.util.Date; import java.util.Map; +import javax.crypto.SecretKey; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; /** * jwt工具类 @@ -34,7 +36,7 @@ public class JwtUtil { * * @param key 加密key 默认:h%OG8Y3WgA5AN7&6Ke7I#C1XvneW0N8a * @param type 加密类型:默认JWT - * @param iss token发行商: 默认yexuejc.com + * @param iss token发行商: 默认yexuejc.top * @return */ public static JwtUtil config(String key, String type, String iss) { @@ -60,7 +62,7 @@ public class JwtUtil { /** * token发行商 */ - private String JWT_CLAIMS_ISS = "yexuejc.com"; + private String JWT_CLAIMS_ISS = "yexuejc.top"; /** * 加密内容生成token @@ -76,22 +78,22 @@ public class JwtUtil { subject = JsonUtil.obj2Json(subjectObj); } Date now = new Date(); - String token = Jwts.builder() + return Jwts.builder() // 设置token的唯一标识ID(claims.jti) - .setId(StrUtil.genUUID()) + .id(StrUtil.genUUID()) // 设置token类型(header.typ) - .setHeaderParam("typ", JWT_HEADER_TYP) + .header().add("typ", JWT_HEADER_TYP) + .and() // 设置token发行时间为当前时间(claims.iat) - .setIssuedAt(now) + .issuedAt(now) // 设置token发行商/发行者(claims.iss) - .setIssuer(JWT_CLAIMS_ISS) + .issuer(JWT_CLAIMS_ISS) // 设置token用户定义主体(claims.sub) - .setSubject(subject) - // 设置签名算法和KEY(signature) - .signWith(SignatureAlgorithm.HS512, JWT_SIGNATURE_KEY) + .subject(subject) + // 设置算法签名,(密钥,加密算法) + .signWith(getSecretKey(), Jwts.SIG.HS512) // 生成token .compact(); - return token; } /** @@ -112,18 +114,8 @@ public class JwtUtil { * @return */ public T parse(String token, Class cls) { - String subject = null; - try { - subject = Jwts.parser().setSigningKey(JWT_SIGNATURE_KEY).parseClaimsJws(token).getBody().getSubject(); - } catch (Exception e) { - e.printStackTrace(); + return JsonUtil.json2Obj(parseStr(token), cls); } - if (subject == null) { - return null; - } - return JsonUtil.json2Obj(subject, cls); - } - /** * 解密token为字符串 * @@ -131,12 +123,11 @@ public class JwtUtil { * @return */ public String parseStr(String token) { - String subject = null; - try { - subject = Jwts.parser().setSigningKey(JWT_SIGNATURE_KEY).parseClaimsJws(token).getBody().getSubject(); - } catch (Exception e) { - e.printStackTrace(); + return Jwts.parser().verifyWith(getSecretKey()).build().parseSignedClaims(token).getPayload().getSubject(); } - return subject; + + private SecretKey getSecretKey() { + byte[] bytes = Decoders.BASE64.decode(JWT_SIGNATURE_KEY); + return Keys.hmacShaKeyFor(bytes); } } diff --git a/src/main/java/com/yexuejc/base/util/ObjUtil.java b/src/main/java/com/yexuejc/base/util/ObjUtil.java index 51f70fa..a5d96b2 100644 --- a/src/main/java/com/yexuejc/base/util/ObjUtil.java +++ b/src/main/java/com/yexuejc/base/util/ObjUtil.java @@ -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) + *

includeField和excludeField同时传入,走包含逻辑,

+ * + * @param source 源对象 + * @param targetClass 目标对象class + * @param includeField 包含对象 + * @param excludeField 排除对象 + * @param + * @param + * @return 目标对象 + * @throws Exception + */ + public static O copy(I source, Class targetClass, List includeField, List excludeField) throws Exception { + List 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; + } + + /** + * 深度复制对象 + *

获取source的所有getXxx。xxx作为属性,且包含父类的getXxx

+ *

查找target的xxx属性,进行反射设值

+ * + * @param source 源对象 + * @param targetClass 目标对象class + * @param invokeSetter 设置target属性值时,是否使用setter方法设置 + * @param + * @param + * @return 目标对象 + */ + public static O copy(I source, Class targetClass, boolean invokeSetter) throws Exception { + List 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 getAllGetterMethods(Class beanClass, String startsWith) { + List 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 getAllFields(Class beanClass) { + List 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); + } + } + } diff --git a/src/main/java/com/yexuejc/base/util/StrUtil.java b/src/main/java/com/yexuejc/base/util/StrUtil.java index 6cf384d..269620a 100644 --- a/src/main/java/com/yexuejc/base/util/StrUtil.java +++ b/src/main/java/com/yexuejc/base/util/StrUtil.java @@ -1,9 +1,19 @@ package com.yexuejc.base.util; -import java.io.UnsupportedEncodingException; +import java.lang.reflect.Array; +import java.nio.charset.StandardCharsets; 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.Optional; +import java.util.Random; +import java.util.UUID; +import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -19,39 +29,28 @@ 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 final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** - * 判断字符串,数组,集合 是否为空 + * 判断字符串,数组,集合 是否为空(null,"",[],{}) * - * @param obj + * @param obj 対象 + * @return true:空;false:非空 * @return */ public static boolean isEmpty(Object obj) { - if (obj instanceof String) { - if (obj == null || "".equals((String) obj)) { - return true; - } else { - return false; - } - } else if (obj instanceof Object[]) { - if (obj == null || ((Object[]) obj).length == 0) { - return true; - } else { - return false; - } - } else if (obj instanceof Collection) { - if (obj == null || ((Collection) obj).size() == 0) { - return true; - } else { - return false; - } + if (obj == null) { + return true; + } else if (obj instanceof Optional) { + return !((Optional) obj).isPresent(); + } else if (obj instanceof CharSequence) { + return ((CharSequence) obj).length() == 0; + } else if (obj.getClass().isArray()) { + return Array.getLength(obj) == 0; + } else if (obj instanceof Collection) { + return ((Collection) obj).isEmpty(); } else { - if (obj == null) { - return true; - } else { - return false; - } + return obj instanceof Map && ((Map) obj).isEmpty(); } } @@ -80,12 +79,12 @@ public final class StrUtil { } else if (length < 1) { return ""; } else { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < length / 32; i++) { sb.append(genUUID()); } if (length % 32 > 0) { - sb.append(genUUID().substring(0, length % 32)); + sb.append(genUUID(), 0, length % 32); } return sb.toString(); } @@ -101,48 +100,14 @@ public final class StrUtil { */ public static String genNum() { int hashCode = UUID.randomUUID().toString().hashCode(); - StringBuffer num = new StringBuffer(); + StringBuilder num = new StringBuilder(); if (hashCode < 0) { - hashCode = 0 - hashCode; + hashCode = -hashCode; num.append("0"); } else { num.append("1"); } - return num.append(String.format("%010d", hashCode)).toString().substring(0, 8); - } - - /** - * 解析aa=bb&cc=dd&ee=ff格式的字符串,返回HashMap - * - * @param urlencoded - * @return - */ - public static Map parseUrlencoded(String urlencoded) { - if (isEmpty(urlencoded)) { - return null; - } - String[] entrys = urlencoded.split("&"); - if (isEmpty(entrys)) { - return null; - } - - Map map = new HashMap(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; + return num.append(String.format("%010d", hashCode)).substring(0, 8); } /** @@ -152,15 +117,15 @@ public final class StrUtil { * @return 转换后字符串 */ public static String toHex(byte[] buf) { - StringBuffer strbuf = new StringBuffer(buf.length * 2); + StringBuilder sb = new StringBuilder(buf.length * 2); int i; for (i = 0; i < buf.length; i++) { if (((int) buf[i] & 0xff) < 0x10) { - strbuf.append("0"); + sb.append("0"); } - strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); + sb.append(Long.toString((int) buf[i] & 0xff, 16)); } - return strbuf.toString(); + return sb.toString(); } /** @@ -227,11 +192,7 @@ public final class StrUtil { */ public static String iso2utf(String str) { String utfStr = null; - try { - utfStr = new String(str.getBytes("ISO-8859-1"), "utf-8"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + utfStr = new String(str.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); return utfStr; } @@ -241,21 +202,18 @@ public final class StrUtil { * @param str * @return */ - private static Pattern pattern = Pattern.compile("[0-9]*"); + private static final Pattern pattern = Pattern.compile("[0-9]*"); public static boolean isNumeric(String str) { Matcher isNum = pattern.matcher(str); - if (!isNum.matches()) { - return false; - } - return true; + return isNum.matches(); } /** * 对ID(32位)进行编码 * - * @param id - * @return + * @param id 32位ID + * @return 编码后的64位ID */ public static String codeId(String id) { if (id == null || id.length() != 32) { @@ -267,7 +225,7 @@ public final class StrUtil { for (int i = 0; i < 13; i++) { coded.append(HEX_CHAR[random.nextInt(16)]); } - coded.append(id.substring(0, 11)); + coded.append(id, 0, 11); for (int i = 0; i < 7; i++) { coded.append(HEX_CHAR[random.nextInt(16)]); } @@ -282,8 +240,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) { @@ -291,12 +249,46 @@ public final class StrUtil { } StringBuilder id = new StringBuilder(); - id.append(coded.substring(13, 24)); - id.append(coded.substring(31, 52)); + id.append(coded, 13, 24); + id.append(coded, 31, 52); return id.toString(); } + /** + * 解析aa=bb&cc=dd&ee=ff格式的字符串,返回HashMap + * + * @param urlencoded + * @return + */ + public static Map parseUrlencoded(String urlencoded) { + if (isEmpty(urlencoded)) { + return null; + } + String[] entrys = urlencoded.split("&"); + if (isEmpty(entrys)) { + return null; + } + + Map map = new HashMap<>(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 * @@ -304,16 +296,15 @@ public final class StrUtil { * @return */ public static String getSignContent(Map sortedParams) { - StringBuffer content = new StringBuffer(); + StringBuilder content = new StringBuilder(); List keys = new ArrayList<>(sortedParams.keySet()); Collections.sort(keys); int index = 0; - for (int i = 0; i < keys.size(); ++i) { - String key = keys.get(i); + for (String key : keys) { Object value = sortedParams.get(key); if (isNotEmpty(key) && isNotEmpty(value)) { - content.append((index == 0 ? "" : "&") + key + "=" + value); + content.append(index == 0 ? "" : "&").append(key).append("=").append(value); ++index; } } @@ -344,8 +335,7 @@ public final class StrUtil { List keys = new ArrayList<>(sortedParams.keySet()); Collections.sort(keys); int index = 0; - for (int i = 0; i < keys.size(); ++i) { - String key = keys.get(i); + for (String key : keys) { Object value = sortedParams.get(key); map.put(key, value); ++index; @@ -370,7 +360,7 @@ public final class StrUtil { /** * 下划线字符 */ - public static final char UNDERLINE = '_'; + private static final char UNDERLINE = '_'; /** * 字符串下划线转驼峰格式 @@ -419,4 +409,68 @@ 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() + *

使用e.printStackTrace()不能作为字符串处理,本方法可以转换e.printStackTrace()为字符串

+ *

printStackTrace信息从Caused by:C开始

+ * + * @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() + *

使用e.printStackTrace()不能作为字符串处理,本方法可以转换e.printStackTrace()为字符串

+ * + * @param cause + * @return + */ + public static String printStackTrace(Throwable cause) { + return printStackTrace(cause, (eMessage) -> { + }); + } + + private static String printStackTrace(Throwable cause, Consumer 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 ""; + } } diff --git a/src/main/java/com/yexuejc/base/util/SysUtil.java b/src/main/java/com/yexuejc/base/util/SysUtil.java index 4b0758f..b42044d 100644 --- a/src/main/java/com/yexuejc/base/util/SysUtil.java +++ b/src/main/java/com/yexuejc/base/util/SysUtil.java @@ -3,7 +3,15 @@ package com.yexuejc.base.util; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.net.URL; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; /** * 系统工具类 @@ -14,6 +22,7 @@ import java.util.concurrent.*; * @date: 2017/12/28 16:12 */ public class SysUtil { + private static final Logger logger = Logger.getLogger(SysUtil.class.getName()); private static final String PROJECT_ROOT_PATH = "java.io.tmpdir"; private SysUtil() { @@ -34,8 +43,8 @@ public class SysUtil { * @param clazz * @return */ - public static URL getRootPath(Class clazz, String filePath) { - return clazz.getClass().getResource(StrUtil.setStr(filePath, "/")); + public static URL getRootPath(Class clazz, String filePath) { + return clazz.getResource(StrUtil.setStr(filePath, "/")); } /** @@ -64,9 +73,7 @@ public class SysUtil { 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); - singleThreadPool.execute(() -> { - threadRun.execute(); - }); + singleThreadPool.execute(threadRun::execute); singleThreadPool.shutdown(); } @@ -79,4 +86,116 @@ public class SysUtil { */ void execute(); } + + + /** + * 获取当前JVM所有线程 + * + * @return + */ + public static List getThreadList() { + List threadList = new ArrayList<>(); + ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); + while (currentGroup.getParent() != null) { + currentGroup = currentGroup.getParent(); + } + int activeCount = currentGroup.activeCount(); + Thread[] threads = new Thread[activeCount]; + currentGroup.enumerate(threads); + for (Thread thread : threads) { + threadList.add(thread); + } + return threadList; + } + + /** 线程锁 */ + private static final Lock THREAD_LOCK = new ReentrantLock(); + /** 已经等待的时间 */ + private static final AtomicInteger SLEEP_TIME = new AtomicInteger(0); + /** 最大等待3分钟 */ + private static final int MAX_SLEEP_TIME = 180; + + /** + * 通过锁的方式判断jvm的内存,如果超80%就等待(最大3分钟)JVM内存降低到80%再执行 + */ + public static void checkJvmMemory() { + THREAD_LOCK.lock(); + try { + while (jvmMemoryIsNotExecutable()) { + //jvm内存使用率达到80%,阻塞所有线程,最大等待3分钟后放开 + if (SLEEP_TIME.incrementAndGet() < MAX_SLEEP_TIME) { + TimeUnit.SECONDS.sleep(1); + } else { + break; + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + THREAD_LOCK.unlock(); + SLEEP_TIME.set(0); + } + } + + /** + * jvm内存是否大于80%(不能继续执行) + * + * @return true:是,false:不是 + */ + public static boolean jvmMemoryIsNotExecutable() { + Runtime runtime = Runtime.getRuntime(); + //jvm总内存 + long jvmTotalMemoryByte = runtime.totalMemory(); + //jvm最大可申请 + long jvmMaxMemoryByte = runtime.maxMemory(); + //空闲空间 + long freeMemoryByte = runtime.freeMemory(); + + double rate = (jvmTotalMemoryByte - freeMemoryByte) * 1.0 / jvmTotalMemoryByte; + if (rate >= 0.8) { + rate = (jvmTotalMemoryByte - freeMemoryByte) * 1.0 / jvmMaxMemoryByte; + if (rate >= 0.8) { + //jvm内存使用率达到80% + print(jvmTotalMemoryByte, jvmMaxMemoryByte, freeMemoryByte); + return true; + } + } + return false; + } + + private static final DecimalFormat RATE_DECIMAL_FORMAT = new DecimalFormat("#.##%"); + + private static void print(long jvmTotalMemoryByte, long jvmMaxMemoryByte, long freeMemoryByte) { + if (logger.isLoggable(Level.WARNING)) { + String sb = "\n=========================================================" + + "\nThread Name = " + Thread.currentThread().getName() + + "\nJVM Memory = " + formatByte(jvmTotalMemoryByte) + + "\nJVM Max Memory = " + formatByte(jvmMaxMemoryByte) + + "\nJVM Used Memory = " + formatByte(jvmTotalMemoryByte - freeMemoryByte) + + "\nJVM Free Memory = " + formatByte(freeMemoryByte) + + "\nJVM Memory Rate = " + RATE_DECIMAL_FORMAT.format((jvmTotalMemoryByte - freeMemoryByte) * 1.0 / jvmTotalMemoryByte) + + "\n========================================================="; + logger.warning(sb); + } + } + + private static String formatByte(long byteNumber) { + //换算单位 + double format = 1024.0; + double kbNumber = byteNumber / format; + if (kbNumber < format) { + return new DecimalFormat("#.##KB").format(kbNumber); + } + double mbNumber = kbNumber / format; + if (mbNumber < format) { + return new DecimalFormat("#.##MB").format(mbNumber); + } + double gbNumber = mbNumber / format; + if (gbNumber < format) { + return new DecimalFormat("#.##GB").format(gbNumber); + } + double tbNumber = gbNumber / format; + return new DecimalFormat("#.##TB").format(tbNumber); + } + } diff --git a/src/test/java/com/yexuejc/base/util/FileUtilTest.java b/src/test/java/com/yexuejc/base/util/FileUtilTest.java new file mode 100644 index 0000000..e376e46 --- /dev/null +++ b/src/test/java/com/yexuejc/base/util/FileUtilTest.java @@ -0,0 +1,72 @@ +package com.yexuejc.base.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.List; + +import com.yexuejc.base.pojo.ReadFileBean; +import com.yexuejc.base.util.bean.AppnodeCertCsvBean; + +/** + * + * @author: yexuejc + * @date: 2024/4/8 11:33 + */ +public class FileUtilTest { + public static void main(String[] args) throws IOException { + readCsvFile(); +// other(); + } + + private static void other() throws IOException { + System.out.println(FileUtil.getFileType("C:\\Users\\Administrator\\Desktop\\test.txt")); + boolean b = FileUtil.judeDirExists(new File("F:\\coding\\yexuejc-base2\\src\\test\\java\\com\\yexuejc\\base\\util\\test\\a")); + File file = new File("F:\\coding\\yexuejc-base2\\src\\test\\java\\com\\yexuejc\\base\\util\\test\\a\\test.txt"); + FileUtil.judeFileExists(file); + System.out.println("创建文件夹:" + b); + System.out.println("SHA1:" + FileUtil.sha1(file)); + //超大文件sha1 + long l = System.currentTimeMillis(); + System.out.println("SHA1:" + FileUtil.sha1(Paths.get("F:\\Docker\\win\\win10x64.iso").toFile()) + " 花费时间:" + (System.currentTimeMillis() - l)); + + System.out.println("MD5:" + FileUtil.md5(file)); + //超大文件MD5 + long l2 = System.currentTimeMillis(); + System.out.println("MD5:" + FileUtil.md5(Paths.get("F:\\Docker\\win\\win10x64.iso").toFile()) + " 花费时间:" + (System.currentTimeMillis() - l2)); + //超大文件MD5 + long l3 = System.currentTimeMillis(); + System.out.println("CRC32:" + FileUtil.crc32(Paths.get("F:\\Docker\\win\\win10x64.iso").toFile()) + " 花费时间:" + (System.currentTimeMillis() - l3)); + + String base64ToStr = FileUtil.base64ToStr(file); + System.out.println(base64ToStr); + String fileName = "F:\\coding\\yexuejc-base2\\src\\test\\java\\com\\yexuejc\\base\\util\\test\\a\\test2.txt"; + System.out.println(FileUtil.base64ToFile(base64ToStr, fileName)); + File file2 = Paths.get(fileName).toFile(); + System.out.println("SHA1:" + FileUtil.sha1(file2)); + System.out.println("MD5:" + FileUtil.md5(file2)); + + + System.out.println(FileUtil.size(file2.toPath())); + long l4 = System.currentTimeMillis(); + System.out.println(FileUtil.size(Paths.get("F:\\Docker\\win\\win10x64.iso")) + " 花费时间:" + (System.currentTimeMillis() - l4)); + + } + + private static void readCsvFile() throws IOException { + String path = "F:\\coding\\yexuejc-base2\\src\\test\\java\\com\\yexuejc\\base\\util\\test.csv"; + + List list = FileUtil.readCsv(path, AppnodeCertCsvBean.class, true, "enable,domain,protocol,deployHost,deployPath,uname,pwd,appnodeId", ','); + System.out.println("***********************************************"); + System.out.println(JsonUtil.formatPrinter(list)); + System.out.println("条数:" + list.size()); + + ReadFileBean readFileBean = new ReadFileBean<>(2); + do { + ReadFileBean bean = FileUtil.readBigFile(path, readFileBean, AppnodeCertCsvBean.class); + System.out.println("============================================"); + System.out.println(JsonUtil.formatPrinter(bean)); + } while (readFileBean.hasNext()); + + } +} diff --git a/src/test/java/com/yexuejc/base/util/SysUtilTest.java b/src/test/java/com/yexuejc/base/util/SysUtilTest.java new file mode 100644 index 0000000..adc7ae7 --- /dev/null +++ b/src/test/java/com/yexuejc/base/util/SysUtilTest.java @@ -0,0 +1,24 @@ +package com.yexuejc.base.util; + +import java.util.Arrays; + +/** + * + * @author: yexuejc + * @date: 2024/4/8 11:22 + */ +public class SysUtilTest { + public static void main(String[] args) { + System.out.println(SysUtil.getCachePath()); + System.out.println(SysUtil.getRootPath(SysUtilTest.class, null)); + SysUtil.threadRun("test", () -> { + String threadName = Thread.currentThread().getName(); + System.out.println("当前线程的名称是:" + threadName); + }); + SysUtil.getThreadList().forEach(t -> { + System.out.println("线程名称:" + t.getName()); + }); + SysUtil.checkJvmMemory(); + System.out.println(SysUtil.jvmMemoryIsNotExecutable()); + } +} diff --git a/src/test/java/com/yexuejc/base/util/bean/AppnodeCertCsvBean.java b/src/test/java/com/yexuejc/base/util/bean/AppnodeCertCsvBean.java new file mode 100644 index 0000000..32ad4e5 --- /dev/null +++ b/src/test/java/com/yexuejc/base/util/bean/AppnodeCertCsvBean.java @@ -0,0 +1,104 @@ +package com.yexuejc.base.util.bean; + +import java.io.Serializable; + +import com.yexuejc.base.annotation.CsvToBean; + +/** + * + * @author: yexuejc + * @date: 2024/2/27 10:40 + */ +public class AppnodeCertCsvBean implements Serializable { + /**是否生效:Y/N*/ + private String enable; + /**域名*/ + private String domain; + /** + * 部署协议 + * appnode + * ssh + * */ + private String protocol; + /** + * 部署服务器 + * 部署协议appnode: local 本机部署 + * 部署协议appnode: 域名 部署的远程appnode域名 + * 部署协议ssh : IP + * */ + private String deployHost; + /**部署证书位置*/ + private String deployPath; + /**服务器账号*/ + private String uname; + /**服务器密码*/ + private String pwd; + /** + * appnode协议时:且远程部署时,对应的远程appnode的ApiNodeId + */ + private Integer appnodeId; + + public String getEnable() { + return enable; + } + + public void setEnable(String enable) { + this.enable = enable; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getDeployHost() { + return deployHost; + } + + public void setDeployHost(String deployHost) { + this.deployHost = deployHost; + } + + public String getDeployPath() { + return deployPath; + } + + public void setDeployPath(String deployPath) { + this.deployPath = deployPath; + } + + public String getUname() { + return uname; + } + + public void setUname(String uname) { + this.uname = uname; + } + + public String getPwd() { + return pwd; + } + + public void setPwd(String pwd) { + this.pwd = pwd; + } + + public Integer getAppnodeId() { + return appnodeId; + } + + public void setAppnodeId(Integer appnodeId) { + this.appnodeId = appnodeId; + } +} diff --git a/src/test/java/com/yexuejc/base/util/test.csv b/src/test/java/com/yexuejc/base/util/test.csv new file mode 100644 index 0000000..e211e74 --- /dev/null +++ b/src/test/java/com/yexuejc/base/util/test.csv @@ -0,0 +1,10 @@ +是否生效,域名,部署协议,部署服务器,部署证书位置,服务器账号,服务器密码,appnodeId +N,kasm.mx.yexuejc.top,appnode,http://192.168.56.101:8888,,admin,admin,1 +N,kasm.mx.yexuejc.top,appnode,local,,,, +N,shop.mx.yexuejc.top,appnode,local,,,, +Y,cloud.yexuejc.top,ssh,118.126.109.109:10371,/home/frpuser/http/cert/,frpuser,yexuejc1, +Y,blog.yexuejc.top,ssh,118.126.109.109:10371,/home/frpuser/http/cert/,frpuser,yexuejc1, +Y,yexuejc.top,ssh,118.126.109.109:10371,/home/frpuser/http/cert/,frpuser,yexuejc1, +Y,jenkins.yexuejc.top,ssh,118.126.109.109:10371,/home/frpuser/http/cert/,frpuser,yexuejc1, +Y,git.yexuejc.top,ssh,118.126.109.109:10371,/home/frpuser/http/cert/,frpuser,yexuejc1, +Y,nexus.yexuejc.top,ssh,118.126.109.109:10371,/home/frpuser/http/cert/,frpuser,yexuejc1,