21 Commits

Author SHA1 Message Date
601611a11f update README.md.
Signed-off-by: 夜雪剑辰 <1107047387@qq.com>
2024-02-22 11:48:36 +00:00
8d364b99f2 [update] jsonUtil优化
Signed-off-by: 夜雪剑辰 <1107047387@qq.com>
2024-02-22 11:39:48 +00:00
127c6902bf [update] 判断空优化
Signed-off-by: 夜雪剑辰 <1107047387@qq.com>
2024-02-22 11:39:23 +00:00
007d8d2f16 [update] SysUtil 增加JVM内存判断等待锁
Signed-off-by: 夜雪剑辰 <1107047387@qq.com>
2023-12-26 09:40:38 +00:00
41a9f1b507 Merge remote-tracking branch 'origin/jre11' into jre11
# Conflicts:
#	src/main/java/com/yexuejc/base/util/JsonUtil.java
2023-09-20 10:02:40 +08:00
bf731e753a 增加StrUtil.printStackTrace方法:把异常堆栈信息转化为字符串 -> 替代 e.printStackTrace() 2023-09-20 10:01:58 +08:00
8d5e653d2b 增加StrUtil.printStackTrace方法:把异常堆栈信息转化为字符串 -> 替代 e.printStackTrace() 2023-09-20 10:01:27 +08:00
c4fc4bd4f8 [update]FileUtil优化分页读取 2023-07-19 20:14:15 +08:00
yexuejc007
667ad26971 [update] ObjUtil.copy方法优化(即使copy不成功,也不报错,出警告日志)。PR:copy源和目标对象中的属性类型不一致,copy不成功 2023-06-15 14:24:05 +08:00
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
d25dee8fe4 Merge remote-tracking branch 'origin/master' 2022-08-26 11:36:15 +08:00
44eee0bbd2 [feat] 升级黑名单项目,变成一个task的集合项目 2022-08-26 11:35:17 +08:00
4dc1d9d767 add LICENSE. 2022-07-20 03:27:29 +00:00
9340edb0ef [feat] 增加读取大文件(csv) 2022-05-17 00:28:35 +08:00
28 changed files with 2133 additions and 179 deletions

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,11 +1,11 @@
yexuejc-base 基于jdk8常用工具包
yexuejc-base 基于jdk11常用工具包
----------------------
源码地址:<br>
github:https://github.com/yexuejc/yexuejc-base
gitee:https://gitee.com/jzsw-it/yexuejc-base
### 说明
1. 支持环境java81.5.0开始支持java11请使用`x.x.x-jre11`版本)
1. 支持环境java111.5.0开始支持java11请使用`1.5.x-jre11`版本)
2. 该工具包基于springboot提取按理说适用于所有java工程
3. 其中依赖jjwt相关、validation-api排除请使用
> ```
@@ -23,7 +23,7 @@ gitee:https://gitee.com/jzsw-it/yexuejc-base
7.`1.5.0`开始,版本分为`1.5.0-jre8``1.5.0-jre11`分别对于jre8和jre11使用
### 使用
>yexuejc.base.version=1.5.0-jre8
>yexuejc.base.version=1.5.1-jre11
pom.xml
```

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/>

43
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>${project.artifactId}</name>
<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>
@@ -40,17 +40,19 @@
<properties>
<repos.yexuejc.url>https://nexus.yexuejc.top/repository/</repos.yexuejc.url>
<repos.aliyun.url>http://maven.aliyun.com/nexus/content/groups/public</repos.aliyun.url>
<repos.aliyun.url>https://maven.aliyun.com/repository/public</repos.aliyun.url>
<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.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>
@@ -111,10 +113,27 @@
<artifactId>poi-ooxml</artifactId>
<version>${apache-poi.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<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>
@@ -129,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>
<!-- 打包源码 -->
@@ -196,12 +215,12 @@
</build>
<repositories>
<repository>
<id>yexuejc-nexus-public</id>
<id>yexuejc-maven</id>
<name>yexuejc-nexus-public</name>
<url>${repos.yexuejc.url}maven-public/</url>
</repository>
<repository>
<id>aliyun-nexus-public</id>
<id>aliyun-maven</id>
<name>aliyun-nexus-public</name>
<url>${repos.aliyun.url}</url>
</repository>

View File

@@ -0,0 +1,31 @@
package com.yexuejc.base.annotation;
import java.lang.annotation.*;
/**
* 设置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;
}

View File

@@ -1,4 +1,6 @@
package com.yexuejc.base.util;
package com.yexuejc.base.annotation;
import com.yexuejc.base.util.ObjUtil;
import java.lang.annotation.*;

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

@@ -0,0 +1,127 @@
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
* @class-name ReadFileBean
* @description 分段读取大文件
* @date 2022/5/16 21:53
*/
public class ReadFileBean<T> {
/**
* 开始行数
*/
private int startRowNum;
/**
* 结束行数
*/
private int endRowNum;
/**
* 每次读取的行数
*/
private int readRowNum;
/**
* 开始行到结束行的数据
*/
private List<T> datas;
/**
* 文件指针位置,默认0开始位置
*/
private long pointer = 0;
/**
* 文件的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;
this.startRowNum = 1;
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;
}
public int getStartRowNum() {
return startRowNum;
}
public int getEndRowNum() {
return endRowNum;
}
public List<T> getDatas() {
return datas;
}
public ReadFileBean<T> setDatas(List<T> datas) {
this.datas = datas;
this.startRowNum = this.endRowNum + 1;
this.endRowNum += this.readRowNum;
return this;
}
public long getPointer() {
return pointer;
}
public ReadFileBean<T> setPointer(long pointer) {
this.pointer = pointer;
return this;
}
public long getFileLength() {
return fileLength;
}
public ReadFileBean<T> setFileLength(long fileLength) {
this.fileLength = fileLength;
return this;
}
public String lineScavenge(String lineData) {
return this.lineScavenger.apply(lineData);
}
public boolean hasNext() {
return this.fileLength > this.pointer;
}
}

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

@@ -1,13 +1,43 @@
package com.yexuejc.base.util;
import java.io.*;
import com.fasterxml.jackson.databind.MappingIterator;
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.CsvToBean;
import com.yexuejc.base.pojo.ReadFileBean;
import io.jsonwebtoken.lang.Assert;
import org.apache.commons.io.IOUtils;
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.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.zip.CRC32;
/**
@@ -21,10 +51,11 @@ 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";
private static final String TYPE_CSV = ".csv";
private static final String TAR_GZ = "tar.gz";
/**
@@ -49,7 +80,7 @@ public class FileUtil {
}
/**
* 判断文件是否存在
* 判断文件是否存在,不存在就创建一个空的
*
* @param file
*/
@@ -142,7 +173,6 @@ public class FileUtil {
return null;
}
/***
* 计算SHA1码
*
@@ -286,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) {
@@ -331,7 +344,7 @@ public class FileUtil {
* base64转文件
* <p>
* <i>
* 文件转base64请使用 {@link FileUtil#base64(File)}
* 文件转base64请使用 {@link FileUtil#base64ToStr(File)}
* </i>
*
* @param decode baseByte
@@ -405,6 +418,347 @@ public class FileUtil {
return 0;
}
/**
* 字符串csv格式转 对象
*
* @param data 转换的字符串 如
* <p> ------------ </p>
* <p> id,name,age </p>
* <p> 1,zhangsan,18 </p>
* <p> 2,lisi,20 </p>
* <p> ------------ </p>
* @param cls 需要转换的对象,含有<b>id,name,age</b>字段
* @param delimiter 分隔符
* @param <I>
* @return
*/
public static <I> List<I> readCsv(String data, Class<I> cls, char delimiter) throws IOException {
CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = CsvSchema.emptySchema().withHeader().withColumnSeparator(delimiter);
MappingIterator<I> orderLines = csvMapper.readerFor(cls).with(csvSchema).readValues(data);
return orderLines.readAll();
}
/**
* 读取csv文件
*
* @param csvFilePath 文件地址
* @param cls 读取转化的对象
* @param hasHeader 是否存在header
* @param delimiter 分隔符.默认【,】
* @param <I>
* @return
*/
public static <I> List<I> readCsv(final String csvFilePath, Class<I> cls, boolean hasHeader, char delimiter) {
if (!isFileExist(csvFilePath)) {
throw new RuntimeException(String.format("解析用的csv\u0020[%s] 文件不存在。", csvFilePath));
}
if (StrUtil.isEmpty(delimiter)) {
delimiter = ',';
}
try {
File csvFile = new File(csvFilePath);
CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = csvMapper.typedSchemaFor(cls).withStrictHeaders(hasHeader).withColumnSeparator(delimiter).withComments();
MappingIterator<I> recordIterator = csvMapper.readerWithTypedSchemaFor(cls).with(csvSchema).readValues(csvFile);
return recordIterator.readAll();
} catch (IOException e) {
throw new RuntimeException("[" + csvFilePath + "] 文件解析失败。", e);
}
}
/**
* 判断文件是否存在
*
* @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 readFileBean 分段每次读取的bean 初始值需要设置每次读取的行数
* @param <T> 读取结果类型bean
* @return
*/
public <T> ReadFileBean<T> readBigFile(String path, ReadFileBean<T> readFileBean, Class<T> readCls) throws FileNotFoundException {
File file = new File(path);
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<>();
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());
}
if (path.contains(TYPE_CSV)) {
//csv文件处理
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) {
logger.severe("file exists." + e.getMessage());
} catch (IOException e) {
logger.severe("read file error." + e.getMessage());
}
return readFileBean;
}
/**
* 获取csv的header,使用注解{@link CsvToBean}
*
* @param cls
* @param <T>
* @return
*/
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;
}
/**
* 把字符串data按照指定编码解码
*
* @param data 解码字符串
* @param charset 字符编码
* @return
*/
public static String charsetDecode(String data, Charset charset) {
char[] chars = data.toCharArray();
byte[] result = new byte[chars.length];
for (int i = 0; i < chars.length; i++) {
result[i] = (byte) chars[i];
}
return new String(result, charset);
}
/**
* 提供读取IO流方法合集
* <p>读取速度快慢顺序:</p>
* 1. {@link #read4Buffer(InputStream, Charset)} <br>
* 2. {@link #read4IOUtilsCopy(InputStream, Charset)} <br>
* 3. {@link #read4ByteStreams(InputStream, Charset)} <br>
* 4. {@link #read4Byte(InputStream, Charset)} <br>
* 5. {@link #read4StringBuilder(InputStream, Charset)} <br>
* 6. {@link #read4BufferedReaderParallel(InputStream, Charset, String)}<br>
* 7. {@link #read4BufferedReader(InputStream, Charset, String)}<br>
* 8. {@link #read4ScannerA(InputStream)}<br>
* 9. {@link #read4BufferIO(InputStream, Charset)}<br>
* 10. {@link #read4IOUtils(InputStream, Charset)}<br>
* 11. {@link #read4ScannerZ(InputStream)}<br>
* 12. {@link #read4CharStreams(InputStream, Charset)}<br>
*/
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);

View File

@@ -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为默认属性
* <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
* @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的默认属性
* <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) {
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> T json2Obj(String json, Class<T> cls) {
T pojo = null;
try {
pojo = objectMapper.readValue(json, cls);
pojo = jsonMapper.readValue(json, cls);
} catch (JsonParseException e) {
log.warning("json to Object JsonParseException.\n" + e.getMessage());
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
} catch (JsonMappingException e) {
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
} catch (IOException e) {
log.warning("json to Object IOException.\n" + e.getMessage());
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
} catch (Exception e) {
e.printStackTrace();
log.warning("json to Object Exception.\n" + StrUtil.printStackTrace(e));
}
return pojo;
@@ -147,15 +236,15 @@ public class JsonUtil {
*/
public static <T> T json2Obj(String json, Class<T> parametrized, Class<?>... parameterClasses) {
T pojo = null;
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(parametrized, parameterClasses);
JavaType javaType = jsonMapper.getTypeFactory().constructParametricType(parametrized, parameterClasses);
try {
pojo = objectMapper.readValue(json, javaType);
pojo = jsonMapper.readValue(json, javaType);
} catch (JsonParseException e) {
log.warning("json to Object JsonParseException.\n" + e.getMessage());
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
} catch (JsonMappingException e) {
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
} catch (IOException e) {
log.warning("json to Object IOException.\n" + e.getMessage());
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
}
return pojo;
}
@@ -172,15 +261,15 @@ public class JsonUtil {
*/
public static <T> T json2Obj(String json, Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) {
T pojo = null;
MapType mapType = objectMapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass);
MapType mapType = jsonMapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass);
try {
pojo = objectMapper.readValue(json, mapType);
pojo = jsonMapper.readValue(json, mapType);
} catch (JsonParseException e) {
log.warning("json to Object JsonParseException.\n" + e.getMessage());
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
} catch (JsonMappingException e) {
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
} catch (IOException e) {
log.warning("json to Object IOException.\n" + e.getMessage());
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
}
return pojo;
}
@@ -195,9 +284,9 @@ public class JsonUtil {
*/
public static <T extends Object> T json2Obj(String json, TypeReference<T> javaType) {
try {
return objectMapper.readValue(json, javaType);
return jsonMapper.readValue(json, javaType);
} catch (JsonProcessingException e) {
log.warning("json to Object JsonParseException.\n" + e.getMessage());
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
}
return null;
}
@@ -212,16 +301,16 @@ public class JsonUtil {
*/
public static <T> T json2Obj(InputStream json, Class<T> parametrized, Class<?>... parameterClasses) {
T pojo = null;
JavaType javaType = objectMapper.getTypeFactory().constructParametrizedType(parametrized, parametrized,
JavaType javaType = jsonMapper.getTypeFactory().constructParametrizedType(parametrized, parametrized,
parameterClasses);
try {
pojo = objectMapper.readValue(json, javaType);
pojo = jsonMapper.readValue(json, javaType);
} catch (JsonParseException e) {
log.warning("json to Object JsonParseException.\n" + e.getMessage());
log.warning("json to Object JsonParseException.\n" + StrUtil.printStackTrace(e));
} catch (JsonMappingException e) {
log.warning("json to Object JsonMappingException.\n" + e.getMessage());
log.warning("json to Object JsonMappingException.\n" + StrUtil.printStackTrace(e));
} catch (IOException e) {
log.warning("json to Object IOException.\n" + e.getMessage());
log.warning("json to Object IOException.\n" + StrUtil.printStackTrace(e));
}
return pojo;
}
@@ -235,9 +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;
}
}

View File

@@ -1,10 +1,16 @@
package com.yexuejc.base.util;
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;
/**
* 对象工具:对类的操作
@@ -16,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() {
}
@@ -258,4 +266,150 @@ public class ObjUtil {
return outer;
}
/**
* 复制对象属性值,包含父类 (不需要getter和setter)
* <p>includeField和excludeField同时传入走包含逻辑</p>
*
* @param source 源对象
* @param targetClass 目标对象class
* @param includeField 包含对象
* @param excludeField 排除对象
* @param <I>
* @param <O>
* @return 目标对象
* @throws Exception
*/
public static <I, O> O copy(I source, Class<O> targetClass, List<String> includeField, List<String> excludeField) throws Exception {
List<Field> allFields = getAllFields(source.getClass());
O o = targetClass.getDeclaredConstructor().newInstance();
if (StrUtil.isNotEmpty(excludeField) && StrUtil.isEmpty(includeField)) {
allFields = allFields.stream().filter(f -> !excludeField.contains(f.getName())).collect(Collectors.toList());
}
if (StrUtil.isNotEmpty(includeField)) {
allFields = allFields.stream().filter(f -> includeField.contains(f.getName())).collect(Collectors.toList());
}
allFields.forEach(f -> {
try {
try {
Field field = targetClass.getDeclaredField(f.getName());
if (field != null) {
f.setAccessible(true);
Object v = f.get(source);
f.setAccessible(false);
field.setAccessible(true);
field.set(o, v);
field.setAccessible(false);
}
} catch (NoSuchFieldException e) {
}
} catch (Exception e) {
log.warning(lowerCaseFirstChar(f.getName()) + " field copy failed. " + e);
log.log(Level.FINER, lowerCaseFirstChar(f.getName()) +
" field copy failed. The exception information is as follows:", e);
}
});
return o;
}
/**
* 深度复制对象
* <p>获取source的所有getXxx。xxx作为属性且包含父类的getXxx</p>
* <p>查找target的xxx属性进行反射设值</p>
*
* @param source 源对象
* @param targetClass 目标对象class
* @param invokeSetter 设置target属性值时是否使用setter方法设置
* @param <I>
* @param <O>
* @return 目标对象
*/
public static <I, O> O copy(I source, Class<O> targetClass, boolean invokeSetter) throws Exception {
List<Method> getterMethods = getAllGetterMethods(source.getClass(), "get");
O o = targetClass.getDeclaredConstructor().newInstance();
getterMethods.forEach(method -> {
String fieldName = method.getName().replace("get", "");
try {
Object v = method.invoke(source);
if (invokeSetter) {
try {
Method setterMethod = targetClass.getDeclaredMethod("set" + fieldName, method.getReturnType());
if (null != setterMethod) {
setterMethod.invoke(o, v);
}
} catch (NoSuchMethodException e) {
}
} else {
try {
Field field = targetClass.getDeclaredField(lowerCaseFirstChar(fieldName));
if (field != null) {
field.setAccessible(true);
field.set(o, v);
field.setAccessible(false);
}
} catch (NoSuchFieldException e) {
}
}
} catch (Exception e) {
log.warning(lowerCaseFirstChar(fieldName) + " field copy failed. " + e);
log.log(Level.FINER, lowerCaseFirstChar(fieldName) +
" field copy failed. The exception information is as follows:\n", e);
}
});
return o;
}
/**
* 获取所有方法,包含父类
*
* @param beanClass
* @param startsWith 方法的开头匹配(空,返回所有)
* @return
*/
public static List<Method> getAllGetterMethods(Class<?> beanClass, String startsWith) {
List<Method> methodList = new ArrayList<>();
Method[] methods = beanClass.getDeclaredMethods();
if (StrUtil.isNotEmpty(startsWith)) {
methodList.addAll(Arrays.stream(methods)
.filter(method -> method.getName().startsWith(startsWith))
.collect(Collectors.toList()));
} else {
methodList.addAll(Arrays.asList(methods));
}
Class<?> superclass = beanClass.getSuperclass();
if (superclass != null) {
methodList.addAll(getAllGetterMethods(superclass, startsWith));
}
return methodList;
}
/**
* 获取所有属性,包含父类
*
* @param beanClass
* @return
*/
public static List<Field> getAllFields(Class<?> beanClass) {
List<Field> fieldList = new ArrayList<>();
while (beanClass != null) {
fieldList.addAll(Arrays.asList(beanClass.getDeclaredFields()));
beanClass = beanClass.getSuperclass();
}
return fieldList;
}
/**
* 首字母小写
*
* @param str
* @return
*/
public static String lowerCaseFirstChar(String str) {
if (str == null || str.length() == 0) {
return str;
} else {
return str.substring(0, 1).toLowerCase() + str.substring(1);
}
}
}

View File

@@ -1,9 +1,19 @@
package com.yexuejc.base.util;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
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 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).isEmpty();
} 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();
}
}
@@ -111,40 +110,6 @@ public final class StrUtil {
return num.append(String.format("%010d", hashCode)).toString().substring(0, 8);
}
/**
* 解析aa=bb&cc=dd&ee=ff格式的字符串返回HashMap
*
* @param urlencoded
* @return
*/
public static Map<String, String> parseUrlencoded(String urlencoded) {
if (isEmpty(urlencoded)) {
return null;
}
String[] entrys = urlencoded.split("&");
if (isEmpty(entrys)) {
return null;
}
Map<String, String> map = new HashMap<String, String>(16);
String[] kv = null;
for (String entry : entrys) {
if (isEmpty(entry)) {
continue;
}
kv = entry.split("=");
if (isEmpty(kv)) {
continue;
}
if (kv.length > 1) {
map.put(kv[0], kv[1]);
} else {
map.put(kv[0], null);
}
}
return map;
}
/**
* 字符串转换方法 把字节数组转换成16进制字符串
*
@@ -254,8 +219,8 @@ public final class StrUtil {
/**
* 对ID32位进行编码
*
* @param id
* @return
* @param id 32位ID
* @return 编码后的64位ID
*/
public static String codeId(String id) {
if (id == null || id.length() != 32) {
@@ -282,8 +247,8 @@ public final class StrUtil {
/**
* 对ID32位进行解码
*
* @param coded
* @return
* @param coded 编码后的64位ID
* @return 解码后的32位ID
*/
public static String decodeId(String coded) {
if (coded == null || coded.length() != 64) {
@@ -297,6 +262,40 @@ public final class StrUtil {
return id.toString();
}
/**
* 解析aa=bb&cc=dd&ee=ff格式的字符串返回HashMap
*
* @param urlencoded
* @return
*/
public static Map<String, String> parseUrlencoded(String urlencoded) {
if (isEmpty(urlencoded)) {
return null;
}
String[] entrys = urlencoded.split("&");
if (isEmpty(entrys)) {
return null;
}
Map<String, String> map = new HashMap<String, String>(16);
String[] kv = null;
for (String entry : entrys) {
if (isEmpty(entry)) {
continue;
}
kv = entry.split("=");
if (isEmpty(kv)) {
continue;
}
if (kv.length > 1) {
map.put(kv[0], kv[1]);
} else {
map.put(kv[0], null);
}
}
return map;
}
/**
* map parameters 转url parameters
*
@@ -370,7 +369,7 @@ public final class StrUtil {
/**
* 下划线字符
*/
public static final char UNDERLINE = '_';
private static final char UNDERLINE = '_';
/**
* 字符串下划线转驼峰格式
@@ -419,4 +418,69 @@ public final class StrUtil {
}
return sb.toString();
}
private static final String NEW_LINE = "\n";
private static final String ERROR_MESSAGE_FORMAT = "%s.%s(%s:%d)";
/**
* 把异常堆栈信息转化为字符串,同时把所有的errorMessage用\n方式拼接到printStackTrace前面 -> 替代 e.printStackTrace()
* <p>使用e.printStackTrace()不能作为字符串处理本方法可以转换e.printStackTrace()为字符串</p>
* <p><b>printStackTrace</b>信息从<i>Caused by:</i>C开始</p>
*
* @param cause
* @return
*/
public static String printStackTraceAndMessage(Throwable cause) {
if (cause != null) {
StringBuilder msg = new StringBuilder();
if (isNotEmpty(cause.getMessage())) {
msg.append(cause.getMessage()).append(NEW_LINE);
}
String causedMsg = printStackTrace(cause, (eMessage) -> {
if (isNotEmpty(eMessage)) {
msg.append(eMessage).append(NEW_LINE);
}
});
return msg.append(causedMsg).toString();
}
return "";
}
/**
* 把异常堆栈信息转化为字符串 -> 替代 e.printStackTrace()
* <p>使用e.printStackTrace()不能作为字符串处理本方法可以转换e.printStackTrace()为字符串</p>
*
* @param cause
* @return
*/
public static String printStackTrace(Throwable cause) {
return printStackTrace(cause, (eMessage) -> {
});
}
private static String printStackTrace(Throwable cause, Consumer<String> consumer) {
if (cause != null) {
StringBuilder sb = new StringBuilder();
String cClass = cause.getClass().getName();
String eMessage = cause.getMessage();
StackTraceElement[] stackTrace = cause.getStackTrace();
Throwable caused = cause.getCause();
while (caused != null) {
cClass = caused.getClass().getName();
eMessage = caused.getMessage();
stackTrace = caused.getStackTrace();
caused = caused.getCause();
consumer.accept(eMessage);
}
sb.append("Caused by: ").append(cClass).append(": ").append(eMessage).append(NEW_LINE);
for (StackTraceElement element : stackTrace) {
sb.append("\tat ");
sb.append(String.format(ERROR_MESSAGE_FORMAT, element.getClassName(), element.getMethodName(),
element.getFileName(), element.getLineNumber()));
sb.append(NEW_LINE);
}
return sb.toString();
}
return "";
}
}

View File

@@ -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 Logger logger = Logger.getLogger(SysUtil.class.getName());
private static final String PROJECT_ROOT_PATH = "java.io.tmpdir";
private SysUtil() {
@@ -79,4 +88,116 @@ public class SysUtil {
*/
void execute();
}
/**
* 获取当前JVM所有线程
*
* @return
*/
public static List<Thread> getThreadList() {
List<Thread> 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);
}
}

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)

View File

@@ -1,5 +1,7 @@
package com.yexuejc.base.util;
import com.yexuejc.base.annotation.ToUeProperty;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;