diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..d571740
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..10da52f
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..cd706f1
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..868906c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..797acea
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/README.md b/README.md
index 8a437d6..b10e569 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,24 @@
-# utils202108
+# utils
+工具集合
-utils202108
\ No newline at end of file
+# jpa
+jpa工具
+
+#myJs
+js 常用函数
+js 常用功能封装
+
+# okhttp3util
+对okhttp3进行轻量级封装
+
+# spring-util
+spring工具类 引入后自动将自己注入到程序中
+
+#test
+测试工具
+
+# util
+个人编程过程中经常用的工具集合
+
+# web
+web编程工具
\ No newline at end of file
diff --git a/jpa/pom.xml b/jpa/pom.xml
new file mode 100644
index 0000000..a70d9b9
--- /dev/null
+++ b/jpa/pom.xml
@@ -0,0 +1,116 @@
+
+
+
+ 4.0.0
+
+ com.liuhuiyu
+ jpa
+ 2.0-SNAPSHOT
+
+ jpa
+ http://www.liuhuiyu.com
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.6.RELEASE
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.16
+ provided
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.jetbrains
+ annotations
+ 19.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+ maven-releases
+ Nexus Releases Repository Pro
+ http://47.242.184.139:8081/repository/maven-releases/
+
+
+ maven-snapshots
+ Nexus Snapshots Repository Pro
+ http://47.242.184.139:8081/repository/maven-snapshots/
+
+
+
+
+
+
+
+ maven-clean-plugin
+ 3.1.0
+
+
+
+ maven-resources-plugin
+ 3.0.2
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+
+ maven-surefire-plugin
+ 2.22.1
+
+
+ maven-jar-plugin
+ 3.0.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+ maven-site-plugin
+ 3.7.1
+
+
+ maven-project-info-reports-plugin
+ 3.0.0
+
+
+
+
+
diff --git a/jpa/src/main/java/com/liuhuiyu/jpa/BaseView.java b/jpa/src/main/java/com/liuhuiyu/jpa/BaseView.java
new file mode 100644
index 0000000..ba3f42b
--- /dev/null
+++ b/jpa/src/main/java/com/liuhuiyu/jpa/BaseView.java
@@ -0,0 +1,203 @@
+package com.liuhuiyu.jpa;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.data.jpa.repository.query.Jpa21Utils;
+
+import javax.sql.DataSource;
+import java.sql.*;
+import java.util.*;
+import java.util.function.Consumer;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-22 9:12
+ */
+public abstract class BaseView {
+ private final DataSource dataSource;
+
+ public BaseView(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ /**
+ * 连接获取
+ *
+ * @param callFunctions 调用函数
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-25 10:42
+ */
+ protected void actionConnection(Consumer callFunctions) {
+ try (Connection connection = this.dataSource.getConnection()) {
+ callFunctions.accept(connection);
+ }
+ catch (SQLException throwable) {
+ throw new RuntimeException("获取连接异常。", throwable);
+ }
+ }
+
+ /**
+ * 获取 PreparedStatement
+ *
+ * @param sql 基础语句
+ * @param callFunctions 回调
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-25 10:45
+ */
+ protected void actionPreparedStatement(String sql, Consumer callFunctions) {
+ actionConnection(connection -> {
+ try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
+ callFunctions.accept(preparedStatement);
+ }
+ catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+// PreparedStatement preparedStatement;
+// try {
+// preparedStatement = connection.prepareStatement(sql);
+// }
+// catch (SQLException throwable) {
+// throw new RuntimeException("创建PreparedStatement异常", throwable);
+// }
+// callFunctions.accept(preparedStatement);
+// try {
+// connection.close();
+// }
+// catch (SQLException e) {
+// throw new RuntimeException(e);
+// }
+ });
+ }
+
+ /**
+ * 执行sql回调ResultSet
+ *
+ * @param sql 基础语句
+ * @param parameterMap 参数Map
+ * @param callFunctions 回调
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-25 10:46
+ */
+ protected void fullResultSet(String sql, Map parameterMap, Consumer callFunctions) {
+ NamedParameterStatement namedParameterStatement = new NamedParameterStatement(sql);
+ this.actionPreparedStatement(namedParameterStatement.getSql(), preparedStatement -> {
+ if (parameterMap != null) {
+ namedParameterStatement.fillParameters(preparedStatement, parameterMap);
+ }
+ Log.i(namedParameterStatement.getSql());
+ ResultSet resultSet;
+ try {
+ resultSet = preparedStatement.executeQuery();
+ }
+ catch (SQLException throwable) {
+ throw new RuntimeException("执行sql语句异常。", throwable);
+ }
+ callFunctions.accept(resultSet);
+ });
+ }
+
+ /**
+ * 对象列表获取
+ *
+ * @param sql 基本语句
+ * @param parameterMap 参数表
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-22 14:05
+ */
+ protected List getResultList(String sql, Map parameterMap) {
+ return getResultList(sql, parameterMap, false);
+ }
+
+ /**
+ * 对象列表获取
+ *
+ * @param sql 基本语句
+ * @param parameterMap 参数表
+ * @param onlyFirst 仅第一行数据
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-22 14:05
+ */
+ protected List getResultList(String sql, Map parameterMap, boolean onlyFirst) {
+ ArrayList resList = new ArrayList<>();
+ this.fullResultSet(sql, parameterMap, (resultSet) -> {
+ try {
+ int columnCount = resultSet.getMetaData().getColumnCount();
+ while (resultSet.next()) {
+ Object[] objs = new Object[columnCount];
+ for (int i = 1; i <= columnCount; i++) {
+ objs[i - 1] = (resultSet.getObject(i));
+ }
+ resList.add(objs);
+ if (onlyFirst) {
+ return;
+ }
+ }
+ }
+ catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ });
+ return resList;
+ }
+
+ /**
+ * 对象列表获取
+ *
+ * @param b DaoOperator
+ * @param sql 基本语句
+ * @param parameterMap 参数表
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-22 14:04
+ */
+ protected List getResultList(DaoOperator b, String sql, Map parameterMap) {
+ List> list = this.getResultList(sql, parameterMap);
+ List resList = new ArrayList<>();
+ for (Object obj : list) {
+ resList.add(b.objectToT(obj));
+ }
+ return resList;
+ }
+
+ /**
+ * 返回第一行信息
+ *
+ * @param b DaoOperator
+ * @param sql 执行语句
+ * @param parameterMap 参数表
+ * @return java.util.Optional
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-22 14:02
+ */
+ protected Optional getFirstResult(DaoOperator b, String sql, Map parameterMap) {
+ List> list = this.getResultList(sql, parameterMap, true);
+ if (list.size() == 0) {
+ return Optional.empty();
+ }
+ else {
+ T t = b.objectToT(list.get(0));
+ return Optional.of(t);
+ }
+ }
+
+ /**
+ * 第一行第一列信息获取
+ *
+ * @param sql 语句
+ * @param parameterMap 参数表
+ * @return java.util.Optional
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-22 13:46
+ */
+ protected Optional getSingleResult(String sql, Map parameterMap) {
+ List list = this.getResultList(sql, parameterMap, true);
+ if (list.size() == 0 || list.get(0).length == 0) {
+ return Optional.empty();
+ }
+ else {
+ return Optional.of(list.get(0)[0]);
+ }
+ }
+}
diff --git a/jpa/src/main/java/com/liuhuiyu/jpa/DaoOperator.java b/jpa/src/main/java/com/liuhuiyu/jpa/DaoOperator.java
new file mode 100644
index 0000000..145e8e0
--- /dev/null
+++ b/jpa/src/main/java/com/liuhuiyu/jpa/DaoOperator.java
@@ -0,0 +1,17 @@
+package com.liuhuiyu.jpa;
+
+/**
+ * 函数式(obj->T)
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-01-22 9:10
+ */
+@FunctionalInterface
+public interface DaoOperator {
+ /**
+ * Object 转换成 类型 T
+ * @param o Object
+ * @return T
+ */
+ T objectToT(Object o);
+}
\ No newline at end of file
diff --git a/jpa/src/main/java/com/liuhuiyu/jpa/Log.java b/jpa/src/main/java/com/liuhuiyu/jpa/Log.java
new file mode 100644
index 0000000..84c3826
--- /dev/null
+++ b/jpa/src/main/java/com/liuhuiyu/jpa/Log.java
@@ -0,0 +1,25 @@
+package com.liuhuiyu.jpa;
+
+import lombok.extern.log4j.Log4j2;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-07-31 16:54
+ */
+@Log4j2
+public class Log {
+ public static boolean outLog = false;
+
+ public static void i(String info) {
+ if (outLog) {
+ log.info(info);
+ }
+ }
+
+ public static void d(String info) {
+ if (outLog) {
+ log.debug(info);
+ }
+ }
+}
diff --git a/jpa/src/main/java/com/liuhuiyu/jpa/NamedParameterStatement.java b/jpa/src/main/java/com/liuhuiyu/jpa/NamedParameterStatement.java
new file mode 100644
index 0000000..652c41b
--- /dev/null
+++ b/jpa/src/main/java/com/liuhuiyu/jpa/NamedParameterStatement.java
@@ -0,0 +1,83 @@
+package com.liuhuiyu.jpa;
+
+import lombok.extern.log4j.Log4j2;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-22 11:01
+ */
+public class NamedParameterStatement {
+ private final Map paramsMap = new HashMap<>();
+ private String sql = "";
+
+ public Map getParamsMap() {
+ return paramsMap;
+ }
+
+ public String getSql() {
+ return this.sql;
+ }
+
+ private void emptyMap() {
+ paramsMap.clear();
+ }
+
+ public NamedParameterStatement(String sql) {
+ this.parseSql(sql);
+ }
+
+ /**
+ * 分析处理带命名参数的SQL语句。使用Map存储参数,然后将参数替换成?
+ *
+ * @param sql 基本语句
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-22 14:10
+ */
+ private void parseSql(String sql) {
+ String regex = "(:(\\w+))";
+ Pattern p = Pattern.compile(regex);
+ Matcher m = p.matcher(sql);
+ emptyMap();
+ int idx = 1;
+ while (m.find()) {
+ //参数名称可能有重复,使用序号来做Key
+ paramsMap.put(idx++, m.group(2));
+ }
+ this.sql = sql.replaceAll(regex, "?");
+ Log.i("分析前:" + sql);
+ Log.d("分析后:" + this.sql);
+ }
+
+ /**
+ * 使用参数值Map,填充pStat
+ *
+ * @param pStat PreparedStatement
+ * @param pMap 命名参数的值表,其中的值可以比较所需的参数多。
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-22 14:10
+ */
+ public void fillParameters(PreparedStatement pStat, Map pMap) {
+ this.paramsMap.forEach((idKey, valueKey) -> {
+ if (pMap.containsKey(valueKey)) {
+ Object value = pMap.get(valueKey);
+ try {
+ pStat.setObject(idKey, value);
+ }
+ catch (SQLException throwables) {
+ throw new RuntimeException("填充参数出错,原因:", throwables);
+ }
+ }
+ else {
+ throw new RuntimeException("语句中参数‘" + valueKey + "’不存在列表中");
+ }
+ });
+ }
+}
diff --git a/jpa/src/main/java/com/liuhuiyu/view/ObjectArray.java b/jpa/src/main/java/com/liuhuiyu/view/ObjectArray.java
new file mode 100644
index 0000000..6de5bea
--- /dev/null
+++ b/jpa/src/main/java/com/liuhuiyu/view/ObjectArray.java
@@ -0,0 +1,165 @@
+package com.liuhuiyu.view;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import java.util.function.Function;
+
+/**
+ * 顺序获取对象序列
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-09 17:30
+ */
+public class ObjectArray {
+ private final Object[] objects;
+ private int index = 0;
+
+ public ObjectArray(Object obj) {
+ this.objects = (Object[]) obj;
+ }
+
+ public void reset() {
+ this.index = 0;
+ }
+
+ public Object get() {
+ if (this.index >= objects.length) {
+ throw new RuntimeException("获取的数据数量" + this.index + "超出了原始数据长度" + this.objects.length);
+ }
+ return objects[this.index++];
+ }
+
+ public String getString() {
+ return getString("");
+ }
+
+ public String getString(String defValue) {
+ return getT((obj) -> {
+ if (obj instanceof String) {
+ return (String) obj;
+ }
+ else {
+ return obj.toString();
+ }
+ }, defValue);
+ }
+
+ public Integer getInteger() {
+ return getInteger(0);
+ }
+
+ public Integer getInteger(Integer defValue) {
+ return getT((obj) -> {
+ if (obj instanceof Number) {
+ return ((Number) obj).intValue();
+ }
+ else {
+ return Integer.parseInt(obj.toString());
+ }
+ }, defValue);
+ }
+
+ public Long getLong() {
+ return getLong(0L);
+ }
+
+ public Long getLong(Long defValue) {
+ return getT((obj) -> {
+ if (obj instanceof Number) {
+ return ((Number) obj).longValue();
+ }
+ else {
+ return Long.parseLong(obj.toString());
+ }
+ }, defValue);
+ }
+
+ public Boolean getBoolean() {
+ return getBoolean(false);
+ }
+
+ public Boolean getBoolean(Boolean defValue) {
+ return getT((obj) -> {
+ if (obj instanceof Boolean) {
+ return (Boolean) obj;
+ }
+ else if (obj instanceof Number) {
+ return ((Number) obj).intValue() == 1;
+ }
+ else {
+ return Boolean.parseBoolean(obj.toString());
+ }
+ }, defValue);
+ }
+
+ public BigDecimal getBigDecimal() {
+ return getBigDecimal(new BigDecimal("0"));
+ }
+
+ public BigDecimal getBigDecimal(BigDecimal defValue) {
+ return getT((obj) -> {
+ if (obj instanceof BigDecimal) {
+ return (BigDecimal) obj;
+ }
+ else if (obj instanceof Number) {
+ return new BigDecimal(((Number) obj).toString());
+ }
+ else {
+ return new BigDecimal(obj.toString());
+ }
+ }, defValue);
+ }
+
+
+ public Timestamp getTimestamp() {
+ return getTimestamp(Timestamp.valueOf(LocalDateTime.MIN));
+ }
+
+ public Timestamp getTimestamp(Timestamp defValue) {
+ return getT((obj) -> {
+ if (obj instanceof Timestamp) {
+ return (Timestamp) obj;
+ }
+ else {
+ return defValue;
+ }
+ }, defValue);
+ }
+
+
+ public BigInteger getBigInteger() {
+ return getBigInteger(BigInteger.ZERO);
+ }
+
+ public BigInteger getBigInteger(BigInteger defValue) {
+ return getT((obj) -> {
+ if (obj instanceof BigInteger) {
+ return (BigInteger) obj;
+ }
+ if (obj instanceof Number) {
+ return BigInteger.valueOf(((Number) obj).longValue());
+ }
+ else {
+ return defValue;
+ }
+ }, defValue);
+ }
+
+ private T getT(Function function, T defValue) {
+ Object obj = this.get();
+ if (obj == null) {
+ return defValue;
+ }
+ else {
+ try {
+ return function.apply(obj);
+ }
+ catch (Exception ex) {
+ return defValue;
+ }
+ }
+ }
+}
diff --git a/jpa/src/main/resources/META-INF/spring.factories b/jpa/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..8c0b562
--- /dev/null
+++ b/jpa/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+#org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+#com.liuhuiyu.jpa.BaseView
\ No newline at end of file
diff --git a/jpa/src/test/java/com/liuhuiyu/AppTest.java b/jpa/src/test/java/com/liuhuiyu/AppTest.java
new file mode 100644
index 0000000..1a3a3f1
--- /dev/null
+++ b/jpa/src/test/java/com/liuhuiyu/AppTest.java
@@ -0,0 +1,39 @@
+package com.liuhuiyu;
+
+import static org.junit.Assert.assertTrue;
+
+import com.liuhuiyu.jpa.DaoOperator;
+import lombok.Data;
+import org.junit.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest {
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue() {
+ Object obj = new Object[]{1, "abc"};
+ Abc abc = new Abc(obj);
+ Abc def=objToClass(Abc::new,obj);
+ assertTrue(true);
+ }
+
+ private T objToClass(DaoOperator daoOperator,Object obj){
+ return daoOperator.objectToT(obj);
+ }
+
+ @Data
+ static class Abc {
+ int index;
+ String name;
+
+ public Abc(Object obj) {
+ Object[] objects = (Object[]) obj;
+ index = (int) objects[0];
+ name = objects[1].toString();
+ }
+ }
+}
diff --git a/jpa/src/test/java/com/liuhuiyu/view/ObjectArrayTest.java b/jpa/src/test/java/com/liuhuiyu/view/ObjectArrayTest.java
new file mode 100644
index 0000000..afac1ff
--- /dev/null
+++ b/jpa/src/test/java/com/liuhuiyu/view/ObjectArrayTest.java
@@ -0,0 +1,65 @@
+package com.liuhuiyu.view;
+
+import lombok.extern.log4j.Log4j2;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-04-02 8:19
+ */
+@Log4j2
+public class ObjectArrayTest {
+
+ @Test
+ public void get() {
+ Object object = new Object[]{1, 30_000_000_000L, "bbbb", true};
+ ObjectArray objectArray = new ObjectArray(object);
+ log.info("原始:i={};l={},s={},b={}", 1, 30_000_000_000L, "bbbb", true);
+ int i = objectArray.getInteger();
+ Long l = objectArray.getLong();
+ String s = objectArray.getString();
+ boolean b = objectArray.getBoolean();
+ log.info("i l s b;i={};l={},s={},b={}", i, l, s, b);
+ objectArray.reset();
+ b = objectArray.getBoolean(true);
+ i = objectArray.getInteger(18);
+ l = objectArray.getLong(100L);
+ s = objectArray.getString("NONE");
+ log.info("b i l s i={};l={},s={},b={}", i, l, s, b);
+ objectArray.reset();
+ s = objectArray.getString("NONE");
+ b = objectArray.getBoolean(true);
+ i = objectArray.getInteger(18);
+ l = objectArray.getLong(100L);
+ log.info("s b i l i={};l={},s={},b={}", i, l, s, b);
+ objectArray.reset();
+ s = objectArray.getString("NONE");
+ i = objectArray.getInteger(18);
+ b = objectArray.getBoolean(true);
+ l = objectArray.getLong(100L);
+ log.info("s i b l i={};l={},s={},b={}", i, l, s, b);
+ }
+
+ @Test
+ public void get2() {
+ int r1 = 1_000_000_000;
+ Object object = new Object[]{1, 30_000_000_000L, "bbbb", true};
+ ObjectArray objectArray = new ObjectArray(object);
+ int i = 0;
+ Long l = 0L;
+ String s = "";
+ boolean b = false;
+ for (int r = 0; r <= r1; r++) {
+ objectArray.reset();
+ i = objectArray.getInteger();
+ l = objectArray.getLong();
+ s = objectArray.getString();
+ b = objectArray.getBoolean();
+ }
+ log.info("s i b l i={};l={},s={},b={}", i, l, s, b);
+ }
+}
\ No newline at end of file
diff --git a/myJs/js/demo.js b/myJs/js/demo.js
new file mode 100644
index 0000000..e6ccb00
--- /dev/null
+++ b/myJs/js/demo.js
@@ -0,0 +1,3 @@
+//分页
+let paging=new ProgPaging({});
+paging.showPage(10,5,6);
\ No newline at end of file
diff --git a/myJs/js/progFunction.js b/myJs/js/progFunction.js
new file mode 100644
index 0000000..4b15cde
--- /dev/null
+++ b/myJs/js/progFunction.js
@@ -0,0 +1,391 @@
+/**
+ * 程序通用函数
+ * @type {{assignObj: (function(*=, *=): *), exitFullScreen: progFunction.exitFullScreen, isFullScreen: (function(): boolean), getMaxZIndex: (function(): any), fullScreen: progFunction.fullScreen}}
+ */
+progFunction = {
+ /**
+ * 功能描述
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-15 9:00
+ * @param url
+ * @param data
+ * @param backFunction {success,error,complete}回调函数
+ * @return
+ */
+ ajax: function (url, data, backFunction) {
+ if (typeof (backFunction.beforeSend) === "undefined") {
+ backFunction.beforeSend = function (xhr) {
+ xhr.setRequestHeader("Authorization", "Basic " + btoa("test:test"));
+ };
+ }
+ $.ajax({
+ type: "POST",
+ url: url,
+ dataType: "json",
+ async: true,
+ data: data,
+ traditional: true,
+ beforeSend: function (xhr) {
+ backFunction.beforeSend(xhr);
+ },
+ success: function (res) {
+ if (res.success) {
+ progFunction.runFunc(backFunction.success, res.data);
+ }
+ else {
+ // debugger;
+ progFunction.runFunc(backFunction.error, res.msg);
+ }
+ },
+ error: function (res) {
+ // debugger;
+ progFunction.runFunc(backFunction.error, "错误码:" + res.status);
+ },
+ complete: function () {
+ progFunction.runFunc(backFunction.complete);
+ }
+ });
+ },
+ runFunc: function (runFunction, v1, v2, v3, v4, v5) {
+ if (typeof (runFunction) === "function") {
+ runFunction(v1, v2, v3, v4, v5);
+ }
+ },
+ /**
+ * 进入全屏
+ */
+ fullScreen: function () {
+ try {
+ let docElm = document.documentElement;
+ //W3C
+ if (docElm.requestFullscreen) {
+ docElm.requestFullscreen();
+ }
+ //FireFox
+ else if (docElm.mozRequestFullScreen) {
+ docElm.mozRequestFullScreen();
+ }
+ //Chrome等
+ else if (docElm.webkitRequestFullScreen) {
+ docElm.webkitRequestFullScreen();
+ }
+ //IE11
+ else if (docElm.msRequestFullscreen) {
+ docElm.msRequestFullscreen();
+ }
+ } catch (error) {
+ console.error("执行全屏失败:", error);
+ }
+ },
+ /**
+ * 节点全屏
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-05 15:01
+ * @param element 元素
+ * @return
+ */
+ launchFullScreen: function (element) {
+ if (element.requestFullscreen) {
+ element.requestFullscreen();
+ }
+ else if (element.mozRequestFullScreen) {
+ element.mozRequestFullScreen();//火狐
+ }
+ else if (element.msRequestFullscreen) {
+ element.msRequestFullscreen();//ie浏览器
+ document.getElementById("fullScreen").style.height = window.screen.height + "px";
+ document.getElementById("fullScreen").style.width = document.documentElement.clientWidth + "px";
+ }
+ else if (element.webkitRequestFullscreen) {
+ element.webkitRequestFullScreen();//谷歌浏览器
+ }
+ },
+ /**
+ * 退出全屏
+ */
+ exitFullScreen: function () {
+ if (document.exitFullscreen) {
+ document.exitFullscreen();
+ }
+ else if (document.mozCancelFullScreen) {
+ document.mozCancelFullScreen();
+ }
+ else if (document.webkitCancelFullScreen) {
+ document.webkitCancelFullScreen();
+ }
+ else if (document.msExitFullscreen) {
+ document.msExitFullscreen();
+ }
+ },
+ /**
+ * 当前是否全屏
+ * @returns {boolean, undefined}ie11检测不到是否全屏
+ */
+ isFullScreen: function () {
+ if (document.fullscreen !== undefined) {
+ return document.fullscreen;
+ }
+ else if (document.mozFullScreen !== undefined) {
+ return document.mozFullScreen;
+ }
+ else if (document.webkitIsFullScreen !== undefined) {
+ return document.webkitIsFullScreen;
+ }
+ else if (document.webkitFullScreen !== undefined) {
+ return document.webkitFullScreen;
+ }
+ else if (document.msFullScreen !== undefined) {
+ return document.msFullScreen;
+ }
+ else {
+ return undefined;
+ }
+ },
+ /**
+ * 最大的 zIndex 获取
+ * @returns {number}
+ */
+ getMaxZIndex: function () {
+ return Math.max.apply(null,
+ $.map($('body *'), function (e) {
+ if ($(e).css('position') !== 'static')
+ return parseInt($(e).css('z-index')) || -1;
+ }));
+ },
+ /**
+ * 对象合并
+ * @param target 原始对象
+ * @param sources 加入的合并数据
+ * @returns {*}
+ */
+ assignObj: function (target, sources) {
+ let obj = target;
+ if (typeof target != 'object' || typeof sources == 'function') {
+ if (typeof target == 'function' && typeof sources != 'function') {
+ return target;
+ }
+ return sources;
+ }
+ if (typeof sources != 'object') {
+ return target;
+ }
+ for (let key in sources) {
+ if (sources.hasOwnProperty(key)) {
+ // 如果target也存在 那就再次合并
+ obj[key] = target.hasOwnProperty(key) ? progFunction.assignObj(target[key], sources[key]) : sources[key];
+ }
+ }
+ return obj;
+ },
+ /**
+ * 深层复制
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-03 10:22
+ * @param obj
+ * @return
+ */
+ clone: function (obj) {
+ let o;
+ if (typeof obj == "object") {
+ if (obj === null) {
+ o = null;
+ }
+ else {
+ if (obj instanceof Array) {
+ o = [];
+ for (let i = 0, len = obj.length; i < len; i++) {
+ o.push(progFunction.clone(obj[i]));
+ }
+ }
+ else {
+ o = {};
+ for (let j in obj) {
+ if (obj.hasOwnProperty(j)) {
+ o[j] = progFunction.clone(obj[j]);
+ }
+ }
+ }
+ }
+ }
+ else {
+ o = obj;
+ }
+ return o;
+ },
+ stringIsEmpty: function (obj) {
+ return typeof (obj) == "string" && obj.trim() === "";
+ },
+ stringIsNotEmpty: function (obj) {
+ return typeof (obj) == "string" && obj.trim() !== "";
+ },
+ /**
+ * 默认赋值
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-16 9:56
+ * @param inputValue 传入值
+ * @param defValue 默认返回值(null)
+ * @param allowNull 允许null
+ * @return
+ */
+ defaultValue: function (inputValue, defValue, allowNull) {
+ if (allowNull === undefined) {
+ allowNull = false;
+ }
+ if (inputValue === undefined || (inputValue === null && !allowNull)) {
+ if (defValue === undefined) {
+ return null;
+ }
+ return defValue;
+ }
+ return inputValue;
+ },
+ /**
+ * 是否是ie浏览器
+ * @returns {boolean}
+ * @constructor
+ */
+ isIE: function () {
+ return (!!window.ActiveXObject || "ActiveXObject" in window);
+ },
+ /**
+ * 遍历循环map
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-06 15:07
+ * @param map 循环map
+ * @param func(value,key) 对象操作
+ * @return 是否结束循环
+ */
+ forMap: function (map, func) {
+ for (let key in map) {
+ if (map.hasOwnProperty(key)) {
+ let res = func(map[key], key);
+ if (res === true) {
+ break;
+ }
+ }
+ }
+ },
+ /**
+ * 遍历循环 array(反向循环)
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-08 11:12
+ * @param array 数组
+ * @param func 便利函数返回true 结束循环
+ * @return boolean 是否终止循环跳出
+ */
+ forArray: function (array, func) {
+ let isBreak = false;
+ for (let index = array.length - 1; index >= 0; index--) {
+ isBreak = func(array[index], index);
+ if (isBreak === true) {
+ break;
+ }
+ }
+ return isBreak;
+ },
+ formatDate: function (date, fmt) {
+ if (/(y+)/.test(fmt)) {
+ fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
+ }
+ let o = {
+ 'M+': date.getMonth() + 1,
+ 'd+': date.getDate(),
+ 'h+': date.getHours(),
+ 'm+': date.getMinutes(),
+ 's+': date.getSeconds()
+ };
+ for (let k in o) {
+ let t = new RegExp('(' + k + ')');
+ if (t.test(fmt)) {
+ let str = o[k] + '';
+ fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
+ }
+ }
+
+ function padLeftZero(str) {
+ return ('00' + str).substr(str.length)
+ }
+
+ return fmt;
+ },
+ formatTimestamp: function (timestamp, fmt) {
+ let date = new Date(timestamp);
+ return progFunction.formatDate(date, fmt)
+ },
+ /**
+ * 获取随机数
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-18 15:02
+ * @param start 最小数
+ * @param end 最大数
+ * @param fixed 是整数
+ * @return
+ */
+ getRandom: function (start, end, fixed) {
+ if (fixed === undefined) {
+ fixed = 0;
+ }
+ let differ = end - start
+ let random = Math.random()
+ return (start + differ * random).toFixed(fixed)
+ },
+ /**
+ * 消息管理
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-29 16:07
+ * @param null
+ * @return null
+ */
+ messageQueueManagement: {
+ /**
+ * 创建消息管理
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-29 16:07
+ * @param props {backFunction}
+ * @return null
+ */
+ create: function (props) {
+ let baseProps = {backFunction: null};
+ let nowProps = progFunction.assignObj(baseProps, props);
+ let mqList = [];
+
+ function newInfo(info) {
+ let newV = {
+ id: "mq" + performance.now() + "_" + Math.floor(Math.random() * 100000000),
+ info: info,
+ }
+ mqList.push(newV);
+ change("D", message);
+ return newV;
+ }
+
+ function removeInfo(message) {
+ for (let i = mqList.length - 1; i >= 0; i--) {
+ if (mqList[i].id === message.id) {
+ mqList.splice(i, 1);
+ change("D", message);
+ return;
+ }
+ }
+ }
+
+ function change(type, data) {
+ if (nowProps.backFunction) {
+ nowProps.backFunction(type, data);
+ }
+ }
+
+ return {
+ putInfo: function (info) {
+ return newInfo(info);
+ },
+ removeInfo: function (message) {
+ removeInfo(message)
+ },
+ getList: function () {
+ return mqList;
+ }
+ };
+ }
+ },
+}
\ No newline at end of file
diff --git a/myJs/js/progLoading.js b/myJs/js/progLoading.js
new file mode 100644
index 0000000..1bdb60a
--- /dev/null
+++ b/myJs/js/progLoading.js
@@ -0,0 +1,156 @@
+//
+// 需要 progFunction.js 支持
+//
+
+/**
+ * 数据加载蒙版
+ * @param property
+ * @constructor
+ */
+function ProgLoading(property) {
+ let baseProperty = {
+ style: {
+ masking: {
+ 'width': '100%',
+ 'height': '100%',
+ 'top': '0',
+ 'left': '0',
+ 'position': 'absolute',
+ 'text-align': 'center',
+ 'background-color': '#00000077',
+ },
+ box: {
+ 'background-color': '#000161',
+ 'color': '#00ffd5',
+ 'top': '50%',
+ 'left': '50%',
+ 'position': 'absolute',
+ 'transform': 'translate(-50%, -50%)',
+ 'padding': '20px 50px',
+ },
+ },
+ class: {
+ masking_class: [],
+ masking_style: {},
+ box_class: [],
+ box_style: {},
+ },
+ info: {
+ div: null,
+ content: "数据加载中......",
+ },
+ };
+ let div;//蒙版
+ let box;//对话框
+ let autoClose = false;
+ let nowShowState = false;
+ initProgLoading(property);
+
+ /**
+ * 参数合并初始化
+ * @param property
+ */
+ function initProgLoading(property) {
+ console.log('参数初始化');
+ if (typeof (property) === "string") {
+ //字符串的话就作为信息传入处理
+ property = {info: {content: property,}}
+ }
+ progFunction.assignObj(baseProperty, property);
+ }
+
+ /**
+ * 添加class
+ * @param item
+ * @param classList
+ */
+ function addClass(item, classList) {
+ for (let i = 0, len = classList.length; i < len; i++) {
+ item.classList.add(classList[i]);
+ }
+ }
+
+ /**
+ * 添加样式
+ * @param item
+ * @param styles
+ */
+ function addStyle(item, styles) {
+ for (let key in styles) {
+ if (styles.hasOwnProperty(key)) {
+ item.style[key] = styles[key];
+ }
+ }
+ }
+
+ /**
+ * 显示loading
+ * @param property
+ */
+ this.show = function (property) {
+ initProgLoading(property);
+ if (div === undefined) {
+ let nowZIndex = progFunction.getMaxZIndex() + 100;
+ div = document.createElement("div");
+ div.style['z-index'] = nowZIndex;
+ if (autoClose) {
+ let _this = this;
+ div.onclick = _this.close;
+ }
+ }
+ else {
+ //样式 class 清理
+ }
+ //region 蒙版样式设定
+ if (baseProperty.class.masking_class.length > 0) {
+ addClass(div, baseProperty.class.masking_class);
+ addStyle(div, baseProperty.class.masking_style);
+ }
+ else {
+ addStyle(div, baseProperty.style.masking);
+ }
+ //endregion
+ if (box === undefined) {
+ box = document.createElement("div");
+ div.appendChild(box);
+ }
+ //region box样式设定
+ if (baseProperty.class.box_class.length > 0) {
+ addClass(box, baseProperty.class.box_class);
+ addStyle(box, baseProperty.class.box_style);
+ }
+ else {
+ addStyle(box, baseProperty.style.box);
+ }
+ box.innerHTML = baseProperty.info.content;
+ document.body.append(div);
+ nowShowState = true;
+ return this;
+ }
+ this.close = function () {
+ if (div !== undefined && nowShowState) {
+ nowShowState = false;
+ document.body.removeChild(div);
+ }
+ }
+ /**
+ * 显示信息到时间自动关闭
+ * @author LiuHuiYu
+ * Created DateTime 2021-02-18 10:36
+ * @param property 参数
+ * @param time 显示时间(毫秒)
+ * @return
+ */
+ this.showInfo = function (property, time) {
+ autoClose = true;
+ if (time === undefined) {
+ time = 3000;
+ }
+ this.show(property);
+ let _this = this;
+ setTimeout(function () {
+ _this.close();
+ }, time);
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/myJs/js/progPaging.js b/myJs/js/progPaging.js
new file mode 100644
index 0000000..27095b8
--- /dev/null
+++ b/myJs/js/progPaging.js
@@ -0,0 +1,154 @@
+/**
+ * 分页功能
+ * @author LiuHuiYu
+ * Created DateTime 2021-02-07 10:09
+ * @param property {showFirstPage,showLastPage,parentDiv,outerDiv,outPage,goPageEvent}
+ * @return
+ */
+function ProgPaging(property) {
+ let baseProperty = {
+ /**
+ * 显示首页
+ */
+ showFirstPage: true,
+ /**
+ * 显示末页
+ */
+ showLastPage: true,
+ /**
+ * 分页上级节点(如果没有默认是body)
+ */
+ parentDiv: null,
+ /**
+ * 分页Dom
+ */
+ outerDiv: null,
+ /**
+ * 输出函数
+ * 参数(页面索引,是否是当前页,是否是首页,是否是末页)
+ */
+ outPage: setPage,
+ /**
+ * 跳转事件函数
+ */
+ goPageEvent: goPage,
+ };
+ Object.assign(baseProperty, property);
+
+ /**
+ * 设置更新分页页面
+ * @param index 当前索引
+ * @param isNowPage 是否是当前页面
+ * @param isFirst 是否是第一页
+ * @param isLast 是否是最后一页
+ */
+ function setPage(index, isNowPage, isFirst, isLast) {
+ let li = document.createElement("li");
+ if (!isNowPage) {
+ (function (index) {
+ //监听点击事件 object比如google地图中的Maker对象
+ li.addEventListener("click", function () {
+ baseProperty.goPageEvent(index); //调用方法
+ });
+ })(index);
+ }
+ if (isNowPage) {
+ li.innerHTML = '(' + (index + 1) + ')';
+ }
+ else if (isFirst) {
+ li.innerHTML = '首页';
+ }
+ else if (isLast) {
+ li.innerHTML = '末页';
+ }
+ else {
+ li.innerHTML = (index + 1);
+ }
+
+ baseProperty.outerDiv.appendChild(li);
+ }
+
+ function goPage(index) {
+ console.info("跳转" + index);
+ }
+
+ /**
+ * 功能描述
+ * @author LiuHuiYu
+ * Created DateTime 2021-02-07 10:15
+ * @param countPageNum 总页数
+ * @param nowPageIndex 当前页索引(0开始)
+ * @param showPageNum 显示页面数量(最少显示3页)
+ * @param property 更新设定参数
+ * @return
+ */
+ this.showPage = function page(countPageNum, nowPageIndex, showPageNum, property) {
+ Object.assign(baseProperty, property);
+
+ //region 异常数据处理
+ if (countPageNum <= 1) {
+ //不显示
+ return;
+ }
+ if (showPageNum < 3) {
+ showPageNum = 3;
+ }
+ //页面异常数据处理
+ if (nowPageIndex < 0) {
+ nowPageIndex = 0;
+ }
+ else if (nowPageIndex > countPageNum - 1) {
+ nowPageIndex = countPageNum - 1
+ }
+ if (showPageNum > countPageNum) {
+ showPageNum = countPageNum;
+ }
+ //endregion
+ //显示页面的中间位置//取丢弃小数部分,保留整数部分
+ let halfAmount = Math.ceil((showPageNum - 1) / 2);
+ let amendmentsNum = (showPageNum + 1) % 2;
+ let frontNumber, afterNumber;
+ //当前页面位置判断。
+ if (nowPageIndex <= halfAmount) {
+ frontNumber = nowPageIndex;
+ afterNumber = showPageNum - 1 - frontNumber;
+ }
+ else if ((countPageNum - nowPageIndex - 1) <= halfAmount) {
+ afterNumber = countPageNum - nowPageIndex - 1;
+ frontNumber = showPageNum - 1 - afterNumber;
+ }
+ else {
+ if (countPageNum / 2 > nowPageIndex) {
+ frontNumber = halfAmount + amendmentsNum;
+ afterNumber = showPageNum - 1 - frontNumber;
+ }
+ else {
+ afterNumber = halfAmount + amendmentsNum;
+ frontNumber = showPageNum - 1 - afterNumber;
+ }
+ }
+
+ if (baseProperty.parentDiv == null) {
+ baseProperty.parentDiv = document.createElement("div");
+ document.body.append(baseProperty.parentDiv);
+ }
+ if (baseProperty.outerDiv == null) {
+ baseProperty.outerDiv = document.createElement("lu");
+ baseProperty.parentDiv.appendChild(baseProperty.outerDiv);
+ }
+ baseProperty.outerDiv.innerHTML = '';
+ if ((nowPageIndex - frontNumber) > 0) {
+ setPage(0, (nowPageIndex === 0), true, false);
+ }
+ for (let i = frontNumber; i > 0; i--) {
+ setPage(nowPageIndex - i, false, false, false);
+ }
+ setPage(nowPageIndex, true, false, false);
+ for (let i = 0; i < afterNumber; i++) {
+ setPage(nowPageIndex + i + 1, false, false, false);
+ }
+ if ((nowPageIndex + afterNumber) < countPageNum - 1) {
+ setPage(countPageNum - 1, (nowPageIndex === (countPageNum - 1)), false, true);
+ }
+ }
+}
diff --git a/okhttp3util/pom.xml b/okhttp3util/pom.xml
new file mode 100644
index 0000000..ab9d227
--- /dev/null
+++ b/okhttp3util/pom.xml
@@ -0,0 +1,93 @@
+
+
+ 4.0.0
+
+ com.liuhuiyu
+ okhttp3util
+ 1.0-SNAPSHOT
+ jar
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.10.0-RC1
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ 1.3.70
+
+
+ com.google.code.gson
+ gson
+ 2.8.6
+
+
+ org.jetbrains
+ annotations
+ 19.0.0
+
+
+ org.projectlombok
+ lombok
+ 1.18.18
+ true
+
+
+ org.apache.commons
+ commons-lang3
+ 3.9
+
+
+
+
+
+
+
+ maven-releases
+ Nexus Releases Repository Pro
+ http://47.242.184.139:8081/repository/maven-releases/
+
+
+ maven-snapshots
+ Nexus Snapshots Repository Pro
+ http://47.242.184.139:8081/repository/maven-snapshots/
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ 1.3.70
+
+
+ compile
+ process-sources
+
+ compile
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpException.java b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpException.java
new file mode 100644
index 0000000..76a630a
--- /dev/null
+++ b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpException.java
@@ -0,0 +1,12 @@
+package com.liuhuiyu.okhttp;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-01-09 17:30
+ */
+public class OkHttpException extends RuntimeException{
+ public OkHttpException(String message) {
+ super(message);
+ }
+}
diff --git a/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpUtil.java b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpUtil.java
new file mode 100644
index 0000000..d909432
--- /dev/null
+++ b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpUtil.java
@@ -0,0 +1,600 @@
+package com.liuhuiyu.okhttp;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import okhttp3.*;
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Supplier;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-01-09 15:06
+ */
+public class OkHttpUtil {
+ private final OkHttpClient.Builder client;
+// private final Request.Builder builder;
+ /**
+ * 保存body中的form-data、x-www-form-urlencoded 信息
+ * Created DateTime 2021-03-29 22:00
+ */
+// private final Map bodyMap;
+ private final List bodyMap;
+ /**
+ * 保存params信息
+ * Created DateTime 2021-03-29 21:58
+ */
+ private final Map paramMap;
+ private final List headerList;
+ private String method;
+ private String bodyString = "";
+ private Object tag;
+ public static final String MEDIA_TYPE_APPLICATION_JSON_UTF_8 = "application/json;charset=utf-8";
+ public static int CONNECT_TIMEOUT = 15;
+ public static int READ_TIMEOUT = 15;
+ public static int WRITE_TIMEOUT = 15;
+
+ private OkHttpUtil(int connectTimeout, int readTimeout, int writeTimeout) {
+ this.client = new OkHttpClient.Builder()
+ .retryOnConnectionFailure(true)
+ .connectTimeout(connectTimeout, TimeUnit.SECONDS)
+ .readTimeout(readTimeout, TimeUnit.SECONDS)
+ .writeTimeout(writeTimeout, TimeUnit.SECONDS)
+ .connectionPool(new ConnectionPool(5, 1, TimeUnit.SECONDS));
+ //.build();
+ this.paramMap = new HashMap<>(0);
+// this.bodyMap = new HashMap<>(0);
+ this.bodyMap = new ArrayList<>(0);
+ this.headerList = new ArrayList<>();
+ this.method = "";
+ }
+// public void https(){
+// this.client.hostnameVerifier(new HostnameVerifier() {
+// @Override
+// public boolean verify(String hostname, SSLSession session) {
+// return true;
+// }
+// }).sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
+// }
+
+ /**
+ * 创建实例
+ *
+ * @return 实例
+ */
+ public static OkHttpUtil create() {
+ return create(CONNECT_TIMEOUT, READ_TIMEOUT, WRITE_TIMEOUT);
+ }
+
+ /**
+ * 创建实例
+ *
+ * @param connectTimeout 连接超时
+ * @param readTimeout 读取超时
+ * @param writeTimeout 写入超时
+ * @return com.liuhuiyu.okhttp.OkHttpUtil
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-30 9:39
+ */
+ public static OkHttpUtil create(int connectTimeout, int readTimeout, int writeTimeout) {
+ return new OkHttpUtil(connectTimeout, readTimeout, writeTimeout);
+ }
+
+ public void setMethod(String value) {
+ this.method = value == null ? "" : value.trim();
+ }
+
+ public void setBodyString(String bodyString) {
+ this.bodyString = bodyString;
+ }
+
+ public void setTag(Object tag) {
+ this.tag = tag;
+ }
+
+ /**
+ * 添加 body
+ *
+ * @param key 键值
+ * @param value 数值
+ * @return OkHttpUtil
+ */
+ public OkHttpUtil addBody(String key, String value) {
+ this.bodyMap.add(new String[]{key, value});
+// this.bodyMap.put(key, value);
+ return this;
+ }
+
+ /**
+ * 添加uri参数
+ *
+ * @param key 键值
+ * @param value 数值
+ * @return OkHttpUtil
+ */
+ public OkHttpUtil addQueryParameter(String key, String value) {
+ this.paramMap.put(key, value);
+ return this;
+ }
+
+ /**
+ * 添加Header
+ *
+ * @param key 键值
+ * @param value 数值
+ * @return OkHttpUtil
+ */
+ public OkHttpUtil addHeader(String key, String value) {
+ this.headerList.add(new String[]{key, value});
+ return this;
+ }
+
+ /**
+ * 加入认证
+ *
+ * @param username 认证账号
+ * @param password 认证密码
+ * @return OkHttpUtil
+ */
+ public OkHttpUtil headerAuthorizationByBasicAuth(String username, String password) {
+ String base64AppMsg;
+ String appMsg = username + ":" + password;
+ base64AppMsg = Base64.getEncoder().encodeToString(appMsg.getBytes(StandardCharsets.UTF_8));
+ return this.addHeader("Authorization", "Basic " + base64AppMsg);
+ }
+
+ public OkHttpUtil headerAuthorizationByBearerToken(String token) {
+ return this.addHeader("Authorization", "Bearer " + token);
+ }
+
+ //region 生成基本数据
+ private HttpUrl getHttpUrl(String url) {
+ HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
+ this.paramMap.forEach(urlBuilder::addQueryParameter);
+ return urlBuilder.build();
+ }
+
+ private RequestBody getRequestBody() {
+ RequestBody body;
+ if (this.bodyMap.size() > 0) {
+// if ("".equals(this.method)) {
+ FormBody.Builder bodyBuilder = new FormBody.Builder();
+// this.bodyMap.forEach(bodyBuilder::add);
+ this.bodyMap.forEach((infos) -> bodyBuilder.add(infos[0], infos[1]));
+ body = bodyBuilder.build();
+// bodyBuilder.add("a", "1");
+// }
+// else {
+// Gson gson = new Gson();
+// String jsonData = gson.toJson(bodyMap);
+// body = RequestBody.create(jsonData, MediaType.parse(this.method));
+// }
+ }
+ else if (StringUtils.isNotBlank(this.bodyString)) {
+ body = RequestBody.create(this.bodyString, MediaType.parse(this.method));
+ }
+ else {
+ body = new FormBody.Builder().build();
+ }
+ return body;
+ }
+
+ private void addHeader(Request.Builder builder) {
+ this.headerList.forEach(keyValue -> builder.addHeader(keyValue[0], keyValue[1]));
+ }
+
+ private void addTag(Request.Builder builder) {
+ if (this.tag != null) {
+ builder.tag(this.tag);
+ }
+ }
+ //endregion
+ //region post申请
+
+ /**
+ * 执行 post
+ *
+ * @param url 地址
+ * @return Response
+ */
+ public Response executePost(String url) {
+ try {
+ HttpUrl httpUrl = this.getHttpUrl(url);
+ RequestBody body = this.getRequestBody();
+
+ Request.Builder builder = new Request.Builder();
+ this.addHeader(builder);
+ this.addTag(builder);
+ builder.post(body);
+ builder.url(httpUrl);
+ /* builder.method(this.method,body); */
+ Request request = builder.build();
+ return this.client.build().newCall(request).execute();
+ }
+ catch (IOException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ public String executePostToString(String url) {
+ try (Response response = this.executePost(url)) {
+ return Objects.requireNonNull(response.body()).string();
+ }
+ catch (IOException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ public Map executePostToMap(String url) {
+ String strJson = this.executePostToString(url);
+ return getStringObjectMap(strJson);
+ }
+
+ public List executePostToList(String url) {
+ return executeList(() -> this.executePostToString(url));
+ }
+ //endregion
+
+ //region get申请
+
+ /**
+ * @param url 地址
+ * @return Response
+ */
+ public Response executeGet(String url) {
+ try {
+ HttpUrl httpUrl = this.getHttpUrl(url);
+ Request.Builder builder = new Request.Builder();
+ this.addHeader(builder);
+ this.addTag(builder);
+ builder.get();
+ builder.url(httpUrl);
+ Request request = builder.build();
+ return this.client.build().newCall(request).execute();
+ }
+ catch (IOException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ public String executeGetToString(String url) {
+ String resData;
+ try (Response response = this.executeGet(url)) {
+ resData = Objects.requireNonNull(response.body()).string();
+ }
+ catch (IOException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ return resData;
+ }
+
+ public Map executeGetToMap(String url) {
+ return executeMap(() -> this.executeGetToString(url));
+ }
+
+ public List executeGetList(String url) {
+ return executeList(() -> this.executeGetToString(url));
+ }
+ //endregion
+
+ //region put申请
+
+ /**
+ * @param url 地址
+ * @return Response
+ */
+ public Response executePut(String url) {
+ try {
+ HttpUrl httpUrl = this.getHttpUrl(url);
+ RequestBody body = this.getRequestBody();
+
+ Request.Builder builder = new Request.Builder();
+ this.addHeader(builder);
+ this.addTag(builder);
+ builder.put(body);
+ builder.url(httpUrl);
+ Request request = builder.build();
+ return this.client.build().newCall(request).execute();
+ }
+ catch (IOException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+
+ }
+
+ public String executePutToString(String url) {
+ try (Response response = this.executePut(url)) {
+ return Objects.requireNonNull(response.body()).string();
+ }
+ catch (IOException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ public Map executePutToMap(String url) {
+ String strJson = this.executePutToString(url);
+ return getStringObjectMap(strJson);
+ }
+
+ public List executePutList(String url) {
+ return executeList(() -> this.executePutToString(url));
+ }
+ //endregion
+
+ //region webSocket
+ public static WebSocket webSocket(String url, WebSocketListener webSocketListener) {
+ OkHttpClient client = new OkHttpClient.Builder().retryOnConnectionFailure(true).build();
+ Request request = new Request.Builder().url(url).build();
+ client.dispatcher().cancelAll();//清理一次
+
+ return client.newWebSocket(request, webSocketListener);
+ }
+ //endregion
+
+ /**
+ * 使用函数式将String转换成Map
+ *
+ * @param supplier 数据获取函数式
+ * @return java.util.Map
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-16 9:08
+ */
+ private static Map executeMap(Supplier supplier) {
+ String strJson = supplier.get();
+ return getStringObjectMap(strJson);
+ }
+
+ /**
+ * 使用函数式将String转换成List
+ *
+ * @param supplier 数据获取函数式
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-16 9:09
+ */
+ private static List executeList(Supplier supplier) {
+ String strJson = supplier.get();
+ return getStringObjectList(strJson);
+ }
+
+ /**
+ * 将json字符串转换成Map
+ *
+ * @param strJson json字符串
+ * @return java.util.Map
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-30 9:04
+ */
+ @NotNull
+ public static Map getStringObjectMap(String strJson) {
+ try {
+ Gson gson = new Gson();
+ Map resultMap = gson.fromJson(strJson, new TypeToken>() {
+ }.getType());
+ return mapDoubleToInt(resultMap);
+ }
+ catch (JsonSyntaxException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ public static List getStringObjectList(String strJson) {
+ try {
+ Gson gson = new Gson();
+ List resultList = gson.fromJson(strJson, new TypeToken>() {
+ }.getType());
+ return listDoubleToInt(resultList);
+ }
+ catch (JsonSyntaxException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ public static Map mapDoubleToInt(Map, ?> resultMap) {
+ Map res = new HashMap<>(resultMap.size());
+ for (Object keyObj : resultMap.keySet()) {
+ String key = keyObj.toString();
+ if (resultMap.get(key) instanceof Double) {
+ Double value = (Double) resultMap.get(key);
+ if (value.intValue() == value) {
+ res.put(key, ((Double) resultMap.get(key)).intValue());
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ else if (resultMap.get(key) instanceof List>) {
+ res.put(key, listDoubleToInt((List>) resultMap.get(key)));
+ }
+ else if (resultMap.get(key) instanceof Map, ?>) {
+ res.put(key, mapDoubleToInt((Map, ?>) resultMap.get(key)));
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ return res;
+ }
+
+ public static List listDoubleToInt(List> list) {
+ List res = new ArrayList<>(list.size());
+ for (Object o : list) {
+ if (o instanceof Number) {
+ Double value = (Double) o;
+ if (value.intValue() == value) {
+ Object v = value.intValue();
+ res.add(v);
+ }
+ else {
+ res.add(value);
+ }
+ }
+ else if (o instanceof Map, ?>) {
+ res.add(mapDoubleToInt((Map, ?>) o));
+ }
+ else if (o instanceof List>) {
+ res.add(listDoubleToInt((List>) o));
+ }
+ else {
+ res.add(o);
+ }
+ }
+ return res;
+ }
+
+ //region https支持
+ private MyTrustManager mMyTrustManager;
+
+ public OkHttpUtil https() {
+ this.client.sslSocketFactory(createSSLSocketFactory(), mMyTrustManager)
+ .hostnameVerifier(new TrustAllHostnameVerifier());
+ return this;
+ }
+
+ private SSLSocketFactory createSSLSocketFactory() {
+ SSLSocketFactory ssfFactory = null;
+ try {
+ mMyTrustManager = new MyTrustManager();
+ SSLContext sc = SSLContext.getInstance("TLS");
+ sc.init(null, new TrustManager[]{mMyTrustManager}, new SecureRandom());
+ ssfFactory = sc.getSocketFactory();
+ }
+ catch (Exception ignored) {
+ ignored.printStackTrace();
+ }
+
+ return ssfFactory;
+ }
+
+ //实现X509TrustManager接口
+ public class MyTrustManager implements X509TrustManager {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ }
+
+ //实现HostnameVerifier接口
+ private class TrustAllHostnameVerifier implements HostnameVerifier {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ }
+
+ /**
+ * 对外提供的获取支持自签名的okhttp客户端
+ *
+ * @param certificate 自签名证书的输入流
+ * @return 支持自签名的客户端
+ */
+ public OkHttpClient getTrusClient(InputStream certificate) {
+ X509TrustManager trustManager;
+ SSLSocketFactory sslSocketFactory;
+ try {
+ trustManager = trustManagerForCertificates(certificate);
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ //使用构建出的trustManger初始化SSLContext对象
+ sslContext.init(null, new TrustManager[]{trustManager}, null);
+ //获得sslSocketFactory对象
+ sslSocketFactory = sslContext.getSocketFactory();
+ }
+ catch (GeneralSecurityException e) {
+ throw new RuntimeException(e);
+ }
+ return new OkHttpClient.Builder()
+ .sslSocketFactory(sslSocketFactory, trustManager)
+ .build();
+ }
+
+ /**
+ * 获去信任自签证书的trustManager
+ *
+ * @param in 自签证书输入流
+ * @return 信任自签证书的trustManager
+ * @throws GeneralSecurityException
+ */
+ private X509TrustManager trustManagerForCertificates(InputStream in)
+ throws GeneralSecurityException {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ //通过证书工厂得到自签证书对象集合
+ Collection extends Certificate> certificates = certificateFactory.generateCertificates(in);
+ if (certificates.isEmpty()) {
+ throw new IllegalArgumentException("expected non-empty set of trusted certificates");
+ }
+ //为证书设置一个keyStore
+ char[] password = "password".toCharArray(); // Any password will work.
+ KeyStore keyStore = newEmptyKeyStore(password);
+ int index = 0;
+ //将证书放入keystore中
+ for (Certificate certificate : certificates) {
+ String certificateAlias = Integer.toString(index++);
+ keyStore.setCertificateEntry(certificateAlias, certificate);
+ }
+ // Use it to build an X509 trust manager.
+ //使用包含自签证书信息的keyStore去构建一个X509TrustManager
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
+ KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(keyStore, password);
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
+ TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(keyStore);
+ TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+ if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
+ throw new IllegalStateException("Unexpected default trust managers:"
+ + Arrays.toString(trustManagers));
+ }
+ return (X509TrustManager) trustManagers[0];
+ }
+
+ private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ InputStream in = null; // By convention, 'null' creates an empty key store.
+ keyStore.load(null, password);
+ return keyStore;
+ }
+ catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ //endregion
+
+}
diff --git a/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpUtil2.java b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpUtil2.java
new file mode 100644
index 0000000..c6e69da
--- /dev/null
+++ b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/OkHttpUtil2.java
@@ -0,0 +1,278 @@
+package com.liuhuiyu.okhttp;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import okhttp3.*;
+import org.jetbrains.annotations.NotNull;
+
+import javax.net.ssl.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.*;
+import java.util.function.Supplier;
+
+/**
+ * OkHttpUtil升级版
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-07-06 10:05
+ */
+public class OkHttpUtil2 {
+ private final OkHttpClient.Builder client;
+ private final Request.Builder request;
+ private final HttpUrl.Builder httpUrl;
+ private final FormBody.Builder bodyBuilder;
+ private MethodModel methodModel;
+ private RequestBody requestBody;
+
+ public static OkHttpUtil2 create(String url) {
+ return new OkHttpUtil2(url);
+ }
+
+ private OkHttpUtil2(String url) {
+ this.httpUrl = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
+ this.request = new Request.Builder();
+ this.client = new OkHttpClient.Builder();
+ this.bodyBuilder = new FormBody.Builder();
+ this.methodModel = MethodModel.GET;
+ }
+
+ /**
+ * 添加地址参数
+ *
+ * @param name 键值
+ * @param value 值
+ * @return com.liuhuiyu.okhttp.OkHttpUtil2
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-06 10:20
+ */
+ public OkHttpUtil2 addQueryParameter(String name, String value) {
+ this.httpUrl.addQueryParameter(name, value);
+ return this;
+ }
+
+ /**
+ * 添加body参数
+ *
+ * @param name 参数名称
+ * @param value 参数值
+ * @return com.liuhuiyu.okhttp.OkHttpUtil2
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-06 11:06
+ */
+ public OkHttpUtil2 addBody(String name, String value) {
+ this.bodyBuilder.add(name, value);
+ return this;
+ }
+
+ public OkHttpUtil2 setBody(String bodyString, String method) {
+ this.requestBody = RequestBody.create(bodyString, MediaType.parse(method));
+ return this;
+ }
+
+ /**
+ * 模式
+ *
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-06 10:33
+ */
+ public enum MethodModel {
+ /**
+ * get方法
+ * Created DateTime 2021-07-06 10:40
+ */
+ GET,
+ /**
+ * post方法
+ * Created DateTime 2021-07-06 10:40
+ */
+ POST,
+ /**
+ * delete方法
+ * Created DateTime 2021-07-06 10:40
+ */
+ DELETE,
+ /**
+ * put方法
+ * Created DateTime 2021-07-06 10:40
+ */
+ PUT,
+ /**
+ * patch方法
+ * Created DateTime 2021-07-06 10:40
+ */
+ PATCH,
+ /**
+ * head方法
+ * Created DateTime 2021-07-06 10:40
+ */
+ HEAD,
+ ;
+
+ public String getName() {
+ return this.name();
+ }
+
+ protected void builder(Request.Builder builder, RequestBody requestBody) {
+ builder.method(this.name(), requestBody);
+ }
+ }
+
+ //region 执行模式设定
+
+ public OkHttpUtil2 setMethodModel(OkHttpUtil2.MethodModel methodModel) {
+ this.methodModel = methodModel;
+ return this;
+ }
+
+ public OkHttpUtil2 get() {
+ this.methodModel = MethodModel.GET;
+ return this;
+ }
+
+ public OkHttpUtil2 post() {
+ this.methodModel = MethodModel.POST;
+ return this;
+ }
+
+ public OkHttpUtil2 delete() {
+ this.methodModel = MethodModel.DELETE;
+ return this;
+ }
+
+ public OkHttpUtil2 put() {
+ this.methodModel = MethodModel.PUT;
+ return this;
+ }
+
+ //endregion
+
+ //region 执行查询
+ public Response execute() {
+ this.request.url(httpUrl.build());
+ OkHttpClient client = this.client.build();
+ Request request = this.request.build();
+ if (this.requestBody == null) {
+ this.requestBody = this.bodyBuilder.build();
+ }
+ this.methodModel.builder(this.request, this.requestBody);
+ try {
+ return client.newCall(request).execute();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String executeToString() {
+ try {
+ return Objects.requireNonNull(this.execute().body()).string();
+ }
+ catch (IOException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ public Map executeToMap() {
+ return executeMap(this::executeToString);
+ }
+ //endregion
+
+ //region 返回信息转换
+
+ /**
+ * 使用函数式将String转换成Map
+ *
+ * @param supplier 数据获取函数式
+ * @return java.util.Map
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-16 9:08
+ */
+ private static Map executeMap(Supplier supplier) {
+ String strJson = supplier.get();
+ return getStringObjectMap(strJson);
+ }
+
+ /**
+ * 将json字符串转换成Map
+ *
+ * @param strJson json字符串
+ * @return java.util.Map
+ * @author LiuHuiYu
+ * Created DateTime 2021-03-30 9:04
+ */
+ @NotNull
+ private static Map getStringObjectMap(String strJson) {
+ try {
+ Gson gson = new Gson();
+ Map resultMap = gson.fromJson(strJson, new TypeToken>() {
+ }.getType());
+ return mapDoubleToInt(resultMap);
+ }
+ catch (JsonSyntaxException e) {
+ throw new OkHttpException(e.getMessage());
+ }
+ }
+
+ private static Map mapDoubleToInt(Map, ?> resultMap) {
+ Map res = new HashMap<>(resultMap.size());
+ for (Object keyObj : resultMap.keySet()) {
+ String key = keyObj.toString();
+ if (resultMap.get(key) instanceof Double) {
+ Double value = (Double) resultMap.get(key);
+ if (value.intValue() == value) {
+ res.put(key, ((Double) resultMap.get(key)).intValue());
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ else if (resultMap.get(key) instanceof List>) {
+ res.put(key, listDoubleToInt((List>) resultMap.get(key)));
+ }
+ else if (resultMap.get(key) instanceof Map, ?>) {
+ res.put(key, mapDoubleToInt((Map, ?>) resultMap.get(key)));
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ return res;
+ }
+
+ private static List listDoubleToInt(List> list) {
+ List res = new ArrayList<>(list.size());
+ for (Object o : list) {
+ if (o instanceof Number) {
+ Double value = (Double) o;
+ if (value.intValue() == value) {
+ Object v = value.intValue();
+ res.add(v);
+ }
+ else {
+ res.add(value);
+ }
+ }
+ else if (o instanceof Map, ?>) {
+ res.add(mapDoubleToInt((Map, ?>) o));
+ }
+ else if (o instanceof List>) {
+ res.add(listDoubleToInt((List>) o));
+ }
+ else {
+ res.add(o);
+ }
+ }
+ return res;
+ }
+ //endregion
+}
diff --git a/okhttp3util/src/main/java/com/liuhuiyu/okhttp/WebSocketManager.java b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/WebSocketManager.java
new file mode 100644
index 0000000..c999419
--- /dev/null
+++ b/okhttp3util/src/main/java/com/liuhuiyu/okhttp/WebSocketManager.java
@@ -0,0 +1,178 @@
+package com.liuhuiyu.okhttp;
+
+import com.google.gson.Gson;
+import lombok.extern.log4j.Log4j2;
+import okhttp3.Response;
+import okhttp3.WebSocket;
+import okhttp3.WebSocketListener;
+import okio.ByteString;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-31 17:33
+ */
+public final class WebSocketManager {
+ boolean err = false;
+ boolean run = false;
+
+ /**
+ * 功能描述
+ *
+ * @param url 地址
+ * @param webSocketListener 监听反馈
+ * @return com.liuhuiyu.okhttp.WebSocketManager
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-01 8:20
+ */
+ public static WebSocketManager create(String url, WebSocketListener webSocketListener) {
+ return new WebSocketManager(url, webSocketListener);
+ }
+
+ String url;
+ WebSocketListener webSocketListener;
+ WebSocket webSocket;
+ int restartMaxNum = 5;
+ int restartNum = 0;
+
+ private WebSocketManager(String url, WebSocketListener webSocketListener) {
+ this.url = url;
+ this.webSocketListener = webSocketListener;
+ }
+
+ /**
+ * 设定最多重新启动的次数
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-01 9:36
+ * @param num 次数
+ */
+ public void setRestartMaxNum(int num) {
+ this.restartMaxNum = Math.max(num, 0);
+ }
+
+ public boolean start() {
+ if (!run) {
+ this.restartNum = 0;
+ this.run(this.url);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ public boolean stop() {
+ if (run) {
+ this.webSocket.close(0, "主动关闭");
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * 消息发送
+ *
+ * @param message 消息
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-01 9:30
+ */
+ public void send(String message) {
+ if (this.run) {
+ this.webSocket.send(message);
+ }
+ }
+
+ /**
+ * 对象发送
+ *
+ * @param jsonObject json对象
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-01 9:32
+ */
+ public void sendJson(Object jsonObject) {
+ Gson gson = new Gson();
+ String json = gson.toJson(jsonObject);
+ this.send(json);
+ }
+
+ private void restart(){
+ if(this.restartMaxNum==0 || this.restartNum resMap = okHttpUtil.executeGetToMap(url);
+ }
+
+ @Test
+ public void testTime() {
+ for (int i = 0; i < 100; i++) {
+ testGetForLogin();
+ }
+ }
+
+ private String getToken() {
+ String url = getUrl("/Authentication/Login");
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+ okHttpUtil.addQueryParameter("userid", "ZH_Admin");
+ okHttpUtil.addQueryParameter("password", "UmVob21lLnpocHNAMjAyMA==");
+ Map resMap = okHttpUtil.executeGetToMap(url);
+ return resMap.get("token").toString();
+ }
+
+ @Test
+ public void testGet02() {
+ String url = getUrl("/U_RS_BASICINFO/GetUserInfoByManID");
+ String token = getToken();
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+ okHttpUtil.headerAuthorizationByBearerToken(token);
+ okHttpUtil.headerAuthorizationByBearerToken(token);
+ Response res = okHttpUtil.executeGet(url);
+ String resString = okHttpUtil.executeGetToString(url);
+ Map resMap = okHttpUtil.executeGetToMap(url);
+ }
+
+ @Test
+ public void testGet03() {
+ String url = getUrl("/U_RS_BASICINFO/GetTreeUser");
+ String token = getToken();
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+ okHttpUtil.addQueryParameter("dc", "ZH");
+ okHttpUtil.headerAuthorizationByBearerToken(token);
+ okHttpUtil.headerAuthorizationByBearerToken(token);
+ Response res = okHttpUtil.executeGet(url);
+ String resString = okHttpUtil.executeGetToString(url);
+ Map resMap = okHttpUtil.executeGetToMap(url);
+ }
+
+ //endregion
+ @Test
+ public void test() {
+ Map m1 = new HashMap<>();
+ Map m2 = new HashMap<>();
+ Map m3 = new HashMap<>();
+ List list1 = new ArrayList<>();
+ list1.add(1.0);
+ list1.add(2.0);
+ list1.add(3.0);
+ list1.add(4.1);
+ list1.add(5.0);
+ m3.put("m3_1", list1);
+ m3.put("m3_2", 2.0);
+ m3.put("m3_3", 3.0);
+ m2.put("m2_1", m3);
+ m2.put("m2_2", 5.0);
+ m2.put("m2_3", 6.1);
+ m1.put("m1_1", m2);
+ m1.put("m1_2", 4.0);
+ m1.put("m1_3", 1.1);
+ Map map = OkHttpUtil.mapDoubleToInt(m1);
+
+ }
+
+ @Test
+ public void testHeadGet() {
+ String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiWkhfQWRtaW4iLCJleHAiOjE2MTI2MzM4MzAsImlzcyI6Imh0dHA6Ly8xOTIuMTY4LjIuNzo4MDA2IiwiYXVkIjoiaHR0cDovLzE5Mi4xNjguMi43OjgwMDYifQ.E6R3ei7UyUK3UnLAKbbLj9vIO9frdUtekT1UD4hHB6A";
+ String url = "http://192.168.2.7:8006/U_SYSTREE/GetUserTreeStr";
+ Map map = OkHttpUtil.create().headerAuthorizationByBearerToken(token).addQueryParameter("dc", "ZH").executeGetToMap(url);
+ if (Integer.parseInt(map.get("code").toString()) == 200) {
+ System.out.println(map.get("data"));
+ }
+ else {
+ System.out.println(map);
+ }
+ }
+
+ @Test
+ public void testPut01() {
+ String url = "http://192.168.2.7:8006/YJYAJX/QYSX";
+ String token = this.getToken();
+ String id = "b7af1ab0-0719-4e3e-93f0-c81dba07e9cb";
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+ okHttpUtil.addQueryParameter("id", id);
+ okHttpUtil.headerAuthorizationByBearerToken(token);
+ Response response = okHttpUtil.executePut(url);
+ Map map = okHttpUtil.executePutToMap(url);
+ /*
+ {
+ "code": 200,
+ "msg": "",
+ "id": "b7af1ab0-0719-4e3e-93f0-c81dba07e9cb",
+ "JSR": "管理员",
+ "JSSJ": "2021-03-26 10:35:25"
+ }
+ */
+ }
+
+ @Test
+ public void testPut02() {
+ String token = this.getToken();
+ String url = "http://192.168.2.7:8006/YJYAJX/UpDate";
+ Map queryParameter = new HashMap<>(5);
+ queryParameter.put("id", "aa30fe55-746c-45a1-8bc1-ef91cd7566c9");
+ queryParameter.put("yjyaid", "96f3065d-8006-4758-a784-b12f147594b6");
+ queryParameter.put("title", "2021年122号台风天鸽应急预案");
+ queryParameter.put("type", "防风");
+ queryParameter.put("dz", "200002");
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+ okHttpUtil.headerAuthorizationByBearerToken(token);
+ for (String key : queryParameter.keySet()) {
+ okHttpUtil.addBody(key, queryParameter.get(key));
+ }
+ okHttpUtil.setMethod(OkHttpUtil.MEDIA_TYPE_APPLICATION_JSON_UTF_8);
+ Response response = okHttpUtil.executePut(url);
+ Map map = okHttpUtil.executePutToMap(url);
+ }
+
+ static CountDownLatch countDownLatch = new CountDownLatch(1);
+
+ @Test
+ public void testWebSocket() throws InterruptedException {
+ String url = "ws://localhost:8111/ws1";
+ WebSocketListener webSocketListener = new WebSocketListener() {
+ @Override
+ public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
+ super.onClosed(webSocket, code, reason);
+ }
+
+ @Override
+ public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
+ super.onClosing(webSocket, code, reason);
+ }
+
+ @Override
+ public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
+ super.onFailure(webSocket, t, response);
+ }
+
+ @Override
+ public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) {
+ super.onMessage(webSocket, text);
+ }
+
+ @Override
+ public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) {
+ super.onMessage(webSocket, bytes);
+ }
+
+ @Override
+ public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) {
+ super.onOpen(webSocket, response);
+ }
+ };
+ OkHttpUtil.webSocket(url, webSocketListener);
+ countDownLatch.await();
+ }
+
+ @Test
+ public void testHttps() {
+ String url = "http://10.0.21.227/WebService.asmx/GetToken";
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+ okHttpUtil.setMethod("application/json");
+ okHttpUtil.addBody("userName", "zhAdmin");
+ okHttpUtil.addBody("userPwd", "zh@2021");
+ okHttpUtil.https();
+ Map map = okHttpUtil.executePostToMap(url);
+ String token = map.get("token").toString();
+ String url2 = "https://safety-vsmapi.geg.com.cn/WebService.asmx/GetDataRequest";
+ OkHttpUtil okHttpUtil2 = OkHttpUtil.create();
+ okHttpUtil2.setMethod("application/json");
+ String[] names = {"", "巫中建"};//"巫中建";
+ String name = names[0];//"巫中建";
+ String[] ids = {"", "51162119900401647X", "510231197208103576", "511621"};
+ String idCards = ids[3];//""510231197208103576";
+ String pageSize = "5";
+ okHttpUtil2.setBodyString("{\n" +
+ " \"token\":\"" + token + "\",\n" +
+ " \"dataType\":\"C_VENUSER\",\n" +
+ " \"company\":\"ZHP\",\n" +
+ " \"pageSize\":" + pageSize + ",\n" +
+ " \"data\":{" +
+ " \"code\":\"\"," +
+ " \"name\":\"" + name + "\"," +
+ " \"idcards\":\"" + idCards + "\"," +
+ " \"suCode\":\"\"," +
+ " \"mobile\":\"\"," +
+ " \"suName\":\"\"" +
+ " }\n" +
+ "}\n");
+// String info=okHttpUtil.executePostToString(url);
+ Map map2 = okHttpUtil2.executePostToMap(url2);
+
+ }
+
+ @Test
+ public void testHttpsGet() {
+ String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13614600169";
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+// okHttpUtil.https();
+ String info = okHttpUtil.executeGetToString(url);
+ }
+
+ @Test
+ public void testHttpsGet2(){
+ String url="https://127.0.0.1:8125/api/v1.0/system/authentication/login_do";
+ Map queryParameter = new HashMap<>(2);
+ String account="ZH_AF_Admin";
+ String password="UmVob21lLnpoYWZAMjEwNg==";
+ queryParameter.put("account", account);
+ queryParameter.put("password", password);
+ OkHttpUtil okHttpUtil = OkHttpUtil.create();
+ for (String key : queryParameter.keySet()) {
+ okHttpUtil.addQueryParameter(key, queryParameter.get(key));
+ }
+ okHttpUtil.https();
+ Map map = okHttpUtil.executeGetToMap(url);
+ }
+ @Test
+ public void testFor() {
+ int num = 100_000;
+ int n = 0;
+ long m = 0;
+ for (int k = 0; k <= 50; k++) {
+ for (int j = 0; j <= 10_000; j++) {
+ n = 0;
+ for (int i = 0; i <= num; i++) {
+ n += i * 2 - 1;
+ m++;
+ }
+ }
+ }
+ System.out.println(m + "," + n);
+ }
+
+ @Test
+ public void testVoid() {
+ String id = "f592b1eac6fb4d1091041bf1dab89aa2";
+ String url = "http://10.19.0.114:8354/partnerRequest/hik8700/queryHls.shtml";
+ String str = OkHttpUtil.create().addQueryParameter("indexCode", id).executeGetToString(url);
+ }
+
+}
\ No newline at end of file
diff --git a/okhttp3util/src/test/java/com/liuhuiyu/okhttp/OkHttpUtilTestKt.kt b/okhttp3util/src/test/java/com/liuhuiyu/okhttp/OkHttpUtilTestKt.kt
new file mode 100644
index 0000000..16bf94c
--- /dev/null
+++ b/okhttp3util/src/test/java/com/liuhuiyu/okhttp/OkHttpUtilTestKt.kt
@@ -0,0 +1,75 @@
+//package com.liuhuiyu.okhttp
+//
+//import org.junit.Test
+//
+///**
+// * @author LiuHuiYu
+// * @version v1.0.0.0
+// * Created DateTime 2021-04-01 10:00
+// */
+//class OkHttpUtilTestKt {
+// @Test
+// fun test01() {
+// print("this is my first Kotlin.\n")
+// }
+//
+// private fun getUrl(url: String): String {
+// return "http://192.168.2.7:8006$url"
+// }
+//
+// @Test
+// fun testGetForLogin() {
+// val url: String = this.getUrl("/Authentication/Login")
+// val okHttpUtil = OkHttpUtil.create()
+// okHttpUtil.addQueryParameter("userid", "ZH_Admin")
+// okHttpUtil.addQueryParameter("password", "UmVob21lLnpocHNAMjAyMA==")
+// val res = okHttpUtil.executeGet(url)
+// val resString = okHttpUtil.executeGetToString(url)
+// val resMap = okHttpUtil.executeGetToMap(url)
+// }
+//
+// @Test
+// fun testTime() {
+// for (i in 0..99) {
+// testGetForLogin()
+// }
+// }
+//
+// private fun getToken(): String {
+// val url = getUrl("/Authentication/Login")
+// val okHttpUtil = OkHttpUtil.create()
+// okHttpUtil.addQueryParameter("userid", "ZH_Admin")
+// okHttpUtil.addQueryParameter("password", "UmVob21lLnpocHNAMjAyMA==")
+// val resMap = okHttpUtil.executeGetToMap(url)
+// return resMap["token"].toString()
+// }
+//
+// @Test
+// fun testGet02() {
+// val url = getUrl("/U_RS_BASICINFO/GetUserInfoByManID")
+// val token = getToken()
+// val okHttpUtil = OkHttpUtil.create()
+// okHttpUtil.headerAuthorizationByBearerToken(token)
+// okHttpUtil.headerAuthorizationByBearerToken(token)
+// val res = okHttpUtil.executeGet(url)
+// val resString = okHttpUtil.executeGetToString(url)
+// val resMap = okHttpUtil.executeGetToMap(url)
+// }
+//
+// @Test
+// fun testFor() {
+// val num = 100000
+// var n = 0
+// var m: Long = 0
+// for (k in 0..50) {
+// for (j in 0..10000) {
+// n = 0
+// for (i in 0..num) {
+// n += i * 2 - 1
+// m++
+// }
+// }
+// }
+// println("$m,$n")
+// }
+//}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..7fbb646
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.6.RELEASE
+
+
+ com.springcloud
+ utils
+ 1.0.0
+ utils
+ pom
+ Demo project for Spring Boot
+
+
+ 1.8
+ Greenwich.RELEASE
+
+
+
+ jpa
+ okhttp3util
+ spring-util
+ test
+ util
+ web
+
+
+
+
+
+ maven-releases
+ Nexus Releases Repository Pro
+ http://47.242.184.139:8081/repository/maven-releases/
+
+
+ maven-snapshots
+ Nexus Snapshots Repository Pro
+ http://47.242.184.139:8081/repository/maven-snapshots/
+
+
+
+
diff --git a/spring-util/pom.xml b/spring-util/pom.xml
new file mode 100644
index 0000000..bcf87ec
--- /dev/null
+++ b/spring-util/pom.xml
@@ -0,0 +1,69 @@
+
+
+ 4.0.0
+
+ com.liuhuiyu
+ spring-util
+ 1.0.0
+ jar
+
+ liuhuiyu-spring-util
+ spring个人工具类
+ https://github.com/liuhuiyu2004/utils
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.6.RELEASE
+
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.16
+ provided
+ true
+
+
+ org.jetbrains
+ annotations
+ 19.0.0
+
+
+ org.springframework
+ spring-context
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.apache.logging.log4j
+ log4j-api
+
+
+
+ 8
+ 8
+
+
+
+
+
+ maven-releases
+ Nexus Releases Repository Pro
+ http://47.242.184.139:8081/repository/maven-releases/
+
+
+ maven-snapshots
+ Nexus Snapshots Repository Pro
+ http://47.242.184.139:8081/repository/maven-snapshots/
+
+
+
+
\ No newline at end of file
diff --git a/spring-util/src/main/java/com/liuhuiyu/spring_util/SpringUtil.java b/spring-util/src/main/java/com/liuhuiyu/spring_util/SpringUtil.java
new file mode 100644
index 0000000..85dc533
--- /dev/null
+++ b/spring-util/src/main/java/com/liuhuiyu/spring_util/SpringUtil.java
@@ -0,0 +1,54 @@
+package com.liuhuiyu.spring_util;
+import lombok.extern.log4j.Log4j2;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * 在初始化的时候加入 @Bean public SpringUtil springUtilBean(){ return new SpringUtil(); }
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-06-24 14:55
+ */
+@Log4j2
+public class SpringUtil implements ApplicationContextAware {
+ private static ApplicationContext applicationContext;
+
+ @Override
+ public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
+ if (SpringUtil.applicationContext == null) {
+ SpringUtil.applicationContext = applicationContext;
+ }
+ log.info("===ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext=%1$s==={}", SpringUtil.applicationContext);
+ log.info("--------------------------------------------------------------");
+ }
+
+ //获取applicationContext
+ public static ApplicationContext getApplicationContext() {
+ return applicationContext;
+ }
+
+ //通过name获取 Bean.
+ public static @NotNull Object getBean(String name) {
+ return getApplicationContext().getBean(name);
+ }
+
+ //通过class获取Bean.
+ public static @NotNull T getBean(Class clazz) {
+ return getApplicationContext().getBean(clazz);
+ }
+
+ /**
+ * 通过name,以及Clazz返回指定的Bean
+ *
+ * @param name 名称
+ * @param clazz 类class
+ * @param 类
+ * @return 类实例
+ */
+ public static @NotNull T getBean(String name, Class clazz) {
+ return getApplicationContext().getBean(name, clazz);
+ }
+}
diff --git a/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/RunTimeAspect.java b/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/RunTimeAspect.java
new file mode 100644
index 0000000..5218c41
--- /dev/null
+++ b/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/RunTimeAspect.java
@@ -0,0 +1,24 @@
+package com.liuhuiyu.spring_util.run_timer;
+
+
+import lombok.extern.log4j.Log4j2;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-02 11:56
+ */
+@Aspect
+@Component
+@Log4j2
+public class RunTimeAspect {
+ @Around(value = "@annotation(timer)")
+ public Object logAround(ProceedingJoinPoint pjp, RunTimer timer) throws Throwable {
+ TimerUtil tu = new TimerUtil();
+ return tu.runTime(pjp, timer);
+ }
+}
diff --git a/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/RunTimer.java b/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/RunTimer.java
new file mode 100644
index 0000000..618daea
--- /dev/null
+++ b/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/RunTimer.java
@@ -0,0 +1,15 @@
+package com.liuhuiyu.spring_util.run_timer;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * 运行时间注解
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-02 11:22
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RunTimer {
+ String explain() default "";
+}
diff --git a/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/TimerUtil.java b/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/TimerUtil.java
new file mode 100644
index 0000000..356480b
--- /dev/null
+++ b/spring-util/src/main/java/com/liuhuiyu/spring_util/run_timer/TimerUtil.java
@@ -0,0 +1,68 @@
+package com.liuhuiyu.spring_util.run_timer;
+
+
+import lombok.extern.log4j.Log4j2;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.reflect.MethodSignature;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-02 11:23
+ */
+@Log4j2
+public class TimerUtil {
+ public void runTime(Method m, Object obj) throws InvocationTargetException, IllegalAccessException {
+ long start = System.currentTimeMillis();
+ m.invoke(obj);
+ long end = System.currentTimeMillis();
+ log.info("{}执行时间:{}", m.getName(), (end - start));
+ }
+
+ public Object runTime(ProceedingJoinPoint pjp, RunTimer runTimer) throws Throwable {
+ Signature sig = pjp.getSignature();
+ MethodSignature msig;// = null;
+ if (!(sig instanceof MethodSignature)) {
+ throw new IllegalArgumentException("该注解只能用于方法");
+ }
+ msig = (MethodSignature) sig;
+ Object target = pjp.getTarget();
+ Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
+
+ long start = System.currentTimeMillis();
+ Object res = pjp.proceed();
+ long end = System.currentTimeMillis();
+
+ log.info("{}.{} {}执行时间:{}", currentMethod.getDeclaringClass().getName(), currentMethod.getName(), runTimer.explain(), (end - start));
+ return res;
+ }
+
+ public void getTime() {
+ // 获取当前类型名字
+ String className = Thread.currentThread().getStackTrace()[2].getClassName();
+ System.out.println("current className(expected): " + className);
+ try {
+ Class> c = Class.forName(className);
+ Object obj = c.newInstance();
+ Method[] methods = c.getDeclaredMethods();
+ for (Method m : methods) {
+ // 判断该方法是否包含Timer注解
+ if (m.isAnnotationPresent(RunTimer.class)) {
+ m.setAccessible(true);
+ long start = System.currentTimeMillis();
+ // 执行该方法
+ m.invoke(obj);
+ long end = System.currentTimeMillis();
+ System.out.println(m.getName() + "() time consumed: " + (end - start) + "\\\\n");
+ }
+ }
+ }
+ catch (ReflectiveOperationException e) {
+ log.error(e.toString());
+ }
+ }
+}
diff --git a/spring-util/src/main/resources/META-INF/spring.factories b/spring-util/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..04be253
--- /dev/null
+++ b/spring-util/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.liuhuiyu.spring_util.SpringUtil,\
+com.liuhuiyu.spring_util.run_timer.RunTimeAspect
\ No newline at end of file
diff --git a/test/pom.xml b/test/pom.xml
new file mode 100644
index 0000000..17ccac3
--- /dev/null
+++ b/test/pom.xml
@@ -0,0 +1,120 @@
+
+
+
+ 4.0.0
+
+ com.liuhuiyu
+ test
+ 1.0-SNAPSHOT
+ jar
+
+ 测试基础类
+
+ http://www.liuhuiyu.com
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.8
+ compile
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ 2.1.6.RELEASE
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ 2.1.6.RELEASE
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ 2.1.6.RELEASE
+
+
+
+
+ org.jetbrains
+ annotations
+ 19.0.0
+
+
+
+
+
+
+
+
+ maven-releases
+ Nexus Releases Repository Pro
+ http://47.242.184.139:8081/repository/maven-releases/
+
+
+ maven-snapshots
+ Nexus Snapshots Repository Pro
+ http://47.242.184.139:8081/repository/maven-snapshots/
+
+
+
+
+
+
+
+ maven-clean-plugin
+ 3.1.0
+
+
+
+ maven-resources-plugin
+ 3.0.2
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+
+ maven-surefire-plugin
+ 2.22.1
+
+
+ maven-jar-plugin
+ 3.0.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+ maven-site-plugin
+ 3.7.1
+
+
+ maven-project-info-reports-plugin
+ 3.0.0
+
+
+
+
+
diff --git a/test/src/main/java/com/liuhuiyu/test/BaseControllerTest.java b/test/src/main/java/com/liuhuiyu/test/BaseControllerTest.java
new file mode 100644
index 0000000..9f127e7
--- /dev/null
+++ b/test/src/main/java/com/liuhuiyu/test/BaseControllerTest.java
@@ -0,0 +1,103 @@
+package com.liuhuiyu.test;
+
+import lombok.SneakyThrows;
+import lombok.extern.log4j.Log4j2;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.io.UnsupportedEncodingException;
+import java.util.function.Consumer;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-07-21 9:26
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@AutoConfigureMockMvc//网站测试
+@Log4j2
+public class BaseControllerTest {
+ @Autowired
+ protected WebApplicationContext wac;
+
+ protected MockMvc mvc;
+
+ @Before()
+ public void setup() {
+ mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+ }
+
+ protected void printHtml(@NotNull ResultActions resultActions) throws UnsupportedEncodingException {
+ this.responseInfo(resultActions);
+ this.printInfo("html信息");
+ log.info(resultActions.andReturn().getResponse().getContentAsString());
+ this.printInfo("html end");
+ }
+
+ protected void printJsonResult(@NotNull ResultActions resultActions) throws UnsupportedEncodingException {
+ this.responseInfo(resultActions);
+ this.printInfo("json信息");
+ log.info(resultActions.andReturn().getResponse().getContentAsString());
+ this.printInfo("json end");
+ }
+
+ /**
+ * 显示Response信息
+ * Created DateTime 2021-02-23 9:10
+ *
+ * @param resultActions ResultActions
+ * @author LiuHuiYu
+ */
+ private void responseInfo(@NotNull ResultActions resultActions) throws UnsupportedEncodingException {
+ String json = resultActions.andReturn().getResponse().getContentAsString();
+ int size = json.getBytes().length;
+ this.printInfo("访问地址");
+ log.info("{}{}", resultActions.andReturn().getRequest().getLocalAddr(), resultActions.andReturn().getRequest().getRequestURI());
+ this.printInfo("参数信息");
+ for (String key : resultActions.andReturn().getRequest().getParameterMap().keySet()) {
+ log.info("{}:{}", key, resultActions.andReturn().getRequest().getParameterMap().get(key));
+ }
+ this.printInfo("字节Byte:" + size);
+ this.printInfo("流量bit:" + (size * 8));
+ }
+
+ protected void printInfo(String info) {
+ log.info("/******************************* " + info + " *******************************/");
+ }
+
+ @SneakyThrows
+ protected MockHttpSession adminLoginSession(String adminAttribute, Object value) {
+ return setSession((session) -> session.setAttribute(adminAttribute, value));
+ }
+
+ @SneakyThrows
+ protected MockHttpSession userLoginSession(String userAttribute, Object value) {
+ return setSession((session) -> session.setAttribute(userAttribute, value));
+ }
+
+ /**
+ * session设定;
+ * session.setAttribute(“admin”,admin);//对session进行登陆设置
+ * Created DateTime 2021-02-23 9:19
+ *
+ * @param consumer session
+ * @author LiuHuiYu
+ */
+ @SneakyThrows
+ protected MockHttpSession setSession(Consumer consumer) {
+ MockHttpSession session = new MockHttpSession();
+ consumer.accept(session);
+ return session;
+ }
+}
\ No newline at end of file
diff --git a/test/src/main/java/com/liuhuiyu/test/BaseServiceTest.java b/test/src/main/java/com/liuhuiyu/test/BaseServiceTest.java
new file mode 100644
index 0000000..7809cea
--- /dev/null
+++ b/test/src/main/java/com/liuhuiyu/test/BaseServiceTest.java
@@ -0,0 +1,62 @@
+package com.liuhuiyu.test;
+
+import lombok.extern.log4j.Log4j2;
+import org.jetbrains.annotations.NotNull;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.domain.Page;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.List;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-07-06 10:43
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Log4j2
+public abstract class BaseServiceTest {
+
+ @Before
+ public void login() {
+
+ }
+
+ @After
+ public void after() {
+
+ }
+
+ protected void printList(@NotNull List> list) {
+ for (Object obj : list) {
+ log.info(obj.toString());
+ }
+ log.info("size = " + list.size());
+ }
+
+ protected void printObject(Object obj) {
+ if (obj == null) {
+ log.info("Obj=null");
+ } else {
+ log.info(obj.toString());
+ }
+ }
+
+ protected void printPageImpl(@NotNull Page> pageImpl) {
+ log.info("总记录数:" + pageImpl.getTotalElements());
+ log.info("当前页号索引:" + pageImpl.getNumber());
+
+ log.info("每页数据:" + pageImpl.getSize());
+
+ log.info("当前页记录数:" + pageImpl.getNumberOfElements());
+ log.info("当前页号:" + (pageImpl.getNumber() + 1));
+
+ log.info("总页数:" + pageImpl.getTotalPages());
+ printList(pageImpl.getContent());
+ }
+}
+
diff --git a/test/src/test/java/com/liuhuiyu/test/AppTest.java b/test/src/test/java/com/liuhuiyu/test/AppTest.java
new file mode 100644
index 0000000..e3d1e61
--- /dev/null
+++ b/test/src/test/java/com/liuhuiyu/test/AppTest.java
@@ -0,0 +1,20 @@
+package com.liuhuiyu.test;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+{
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/util/README.md b/util/README.md
new file mode 100644
index 0000000..72cf543
--- /dev/null
+++ b/util/README.md
@@ -0,0 +1,41 @@
+# util 简介
+My util, Common tools collection
+工具集合类
+# 包说明
+|包|说明|
+|---|---|
+|asserts|断言|
+|constant.enums|常量枚举|
+|exception|异常|
+|spring|spring工具|
+|web|web工具|
+#导入方法
+1.将项目maven打jar包
+Maven->Util->生命周期->package
+2.在要引用的项目中建立lib文件夹
+3.复制jar包到lib文件夹
+4.在pom.xml中
+dependencies 标签中加入
+~~~
+
+ com.liuhuiyu
+ util
+ 1.0-SNAPSHOT
+ system
+ ${project.basedir}/lib/util-1.0-SNAPSHOT.jar
+
+~~~
+build 标签中加入
+~~~
+
+
+ lib
+ /BOOT-INF/lib/
+
+ **/*.jar
+
+
+
+~~~
+本地仓库安装
+mvn install:install-file -Dfile=util-1.0.0.jar -DgroupId=com.liuhuiyu -DartifactId=util -Dversion=1.0-SNAPSHOT -Dpackaging=jar
diff --git a/util/pom.xml b/util/pom.xml
new file mode 100644
index 0000000..cf2e1b2
--- /dev/null
+++ b/util/pom.xml
@@ -0,0 +1,269 @@
+
+
+
+ 4.0.0
+
+ com.liuhuiyu
+ util
+ 1.0.0
+ jar
+
+ liuhuiyu-util
+ 个人工具类
+ https://github.com/liuhuiyu2004/util
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.6.RELEASE
+
+
+
+
+
+
+
+ maven-releases
+ Nexus Releases Repository Pro
+ http://47.242.184.139:8081/repository/maven-releases/
+
+
+ maven-snapshots
+ Nexus Snapshots Repository Pro
+ http://47.242.184.139:8081/repository/maven-snapshots/
+
+
+
+
+
+ MIT License
+ https://github.com/everitoken/evt4j/blob/master/LICENSE
+ repo
+
+
+
+ https://github.com/liuhuiyu2004/util
+ scm:git:git@github.com:liuhuiyu2004/util
+ scm:git:git@github.com:liuhuiyu2004/util
+
+
+
+ liuhuiyu
+ liuhuiyu2004@outlook.com
+
+
+
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.apache.logging.log4j
+ log4j-api
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+
+ org.jetbrains
+ annotations
+ 19.0.0
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+
+ net.sourceforge.nekohtml
+ nekohtml
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+ org.apache.directory.studio
+ org.apache.commons.codec
+ 1.8
+
+
+
+
+
+
+
+
+
+ commons-io
+ commons-io
+ 2.8.0
+
+
+ com.google.code.gson
+ gson
+ 2.8.6
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.18
+ true
+
+
+
+ commons-beanutils
+ commons-beanutils
+ 1.9.4
+
+
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.7
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.1.0
+
+ false
+ none
+
+
+
+ attach-javadocs
+
+ jar
+
+ package
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+ maven-assembly-plugin
+
+
+ jar-with-dependencies
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.6.1
+
+ 1.8
+ 1.8
+
+
+
+ maven-surefire-plugin
+ 2.19.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+ 3.7.1
+
+
+ org.apache.maven.plugins
+ maven-project-info-reports-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
diff --git a/util/src/main/java/com/liuhuiyu/util/ObjectUtil.java b/util/src/main/java/com/liuhuiyu/util/ObjectUtil.java
new file mode 100644
index 0000000..0676ba7
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/ObjectUtil.java
@@ -0,0 +1,74 @@
+package com.liuhuiyu.util;
+
+/**
+ * 此函数已经作废 尽量使用
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-01-28 8:23
+ */
+public class ObjectUtil {
+ public static boolean isNull(Object o) {
+ return o == null;
+ }
+
+ public static boolean equals(Object o1, Object o2) {
+ if (o1 == null) {
+ return o2 == null;
+ }
+ return o1.equals(o2);
+ }
+
+ public static Integer parseInteger(Object o) {
+ return parseInteger(o, 0, 0);
+ }
+
+ public static Integer parseInteger(Object o, Integer defValue, Integer nullValue) {
+ if (isNull(o)) {
+ return nullValue;
+ }
+ if (o instanceof Integer) {
+ return (Integer) o;
+ } else {
+ try {
+ return Integer.parseInt(o.toString());
+ } catch (Exception ex) {
+ return defValue;
+ }
+ }
+ }
+
+ public static Long parseLong(Object o) {
+ return parseLong(o.toString(), 0L, 0L);
+ }
+
+ public static Long parseLong(Object o, Long defValue, Long nullValue) {
+ if (isNull(o)) {
+ return nullValue;
+ }
+ if (o instanceof Long) {
+ return (Long) o;
+ } else {
+ try {
+ return Long.parseLong(o.toString());
+ } catch (Exception ex) {
+ return defValue;
+ }
+ }
+ }
+
+ public static String parseString(Object o) {
+ return parseString(o, "", "");
+ }
+
+ public static String parseString(Object o, String defValue, String nullValue) {
+ if (isNull(o)) {
+ return nullValue;
+ } else {
+ if (o instanceof String) {
+ return (String) o;
+ } else {
+ return o.toString();
+ }
+ }
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/asserts/LhyAssert.java b/util/src/main/java/com/liuhuiyu/util/asserts/LhyAssert.java
new file mode 100644
index 0000000..07f83a3
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/asserts/LhyAssert.java
@@ -0,0 +1,102 @@
+package com.liuhuiyu.util.asserts;
+
+import com.liuhuiyu.util.constant.enums.ResultEnum;
+import com.liuhuiyu.util.exception.LhyException;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-09-10 8:41
+ */
+public class LhyAssert {
+ //region assertTrue
+
+ public static void assertTrue(boolean value, RuntimeException exception) {
+ if (!value) {
+ throw exception;
+ }
+ }
+
+ public static void assertTrue(boolean value, String message) {
+ assertTrue(value, new RuntimeException(message));
+ }
+
+ /**
+ * 对象不为空则抛出异常
+ *
+ * @param value 对象
+ * @param resultEnum 错误枚举
+ */
+ public static void assertTrue(boolean value, ResultEnum resultEnum) {
+ if (!value) {
+ throw new LhyException(resultEnum);
+ }
+ }
+ //endregion
+
+ //region assertFalse
+
+ public static void assertFalse(boolean value, String message) {
+ assertTrue(!value, message);
+ }
+
+ public static void assertFalse(boolean value, RuntimeException exception) {
+ assertTrue(!value, exception);
+ }
+ //endregion
+
+ //region assertNotNull
+ public static void assertNotNull(Object object, RuntimeException exception) {
+ assertTrue(object != null, exception);
+ }
+
+ /**
+ * 对象为空则抛出异常
+ *
+ * @param object 对象
+ */
+ public static void assertNotNull(Object object, String message) {
+ assertTrue(object != null, message);
+ }
+
+ /**
+ * 对象为空则抛出异常
+ *
+ * @param object 对象
+ * @param resultEnum 错误枚举
+ */
+ public static void assertNotNull(Object object, ResultEnum resultEnum) {
+ assertTrue(object != null, resultEnum);
+ }
+ //endregion
+
+ //region assertNull
+ /**
+ * 对象不为空则抛出异常
+ *
+ * @param object 对象
+ */
+ public static void assertNull(Object object, RuntimeException exception) {
+ assertTrue(object == null, exception);
+ }
+
+ /**
+ * 对象不为空则抛出异常
+ *
+ * @param object 对象
+ */
+ public static void assertNull(Object object, String message) {
+ assertTrue(object == null, message);
+ }
+
+ /**
+ * 对象不为空则抛出异常
+ *
+ * @param object 对象
+ * @param resultEnum 错误枚举
+ */
+ public static void assertNull(Object object, ResultEnum resultEnum) {
+ assertTrue(object == null, resultEnum);
+ }
+ //endregion
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/constant/enums/ResultEnum.java b/util/src/main/java/com/liuhuiyu/util/constant/enums/ResultEnum.java
new file mode 100644
index 0000000..712f7fa
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/constant/enums/ResultEnum.java
@@ -0,0 +1,33 @@
+package com.liuhuiyu.util.constant.enums;
+
+/**
+ * 返回信息集合
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-07-08 11:45
+ */
+public enum ResultEnum {
+ /**
+ * 成功
+ */
+ SUCCESS(0, "成功"),
+ CUSTOM_ERROR(-1,"自定义错误"),
+ ;
+
+ private Integer code;
+ private String message;
+
+ ResultEnum(Integer code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/date/LocalDateUtil.java b/util/src/main/java/com/liuhuiyu/util/date/LocalDateUtil.java
new file mode 100644
index 0000000..228916d
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/date/LocalDateUtil.java
@@ -0,0 +1,25 @@
+package com.liuhuiyu.util.date;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 本地日期时间工具
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-05-22 14:39
+ */
+public class LocalDateUtil {
+ public static String dateToString(LocalDate date, String format) {
+ return date.format(DateTimeFormatter.ofPattern(format));
+ }
+ public static String dateToString(LocalDateTime date, String format) {
+ return date.format(DateTimeFormatter.ofPattern(format));
+ }
+ public static String dateToString(LocalTime date, String format) {
+ return date.format(DateTimeFormatter.ofPattern(format));
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/exception/LhyException.java b/util/src/main/java/com/liuhuiyu/util/exception/LhyException.java
new file mode 100644
index 0000000..6cb5e52
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/exception/LhyException.java
@@ -0,0 +1,54 @@
+package com.liuhuiyu.util.exception;
+
+import com.liuhuiyu.util.constant.enums.ResultEnum;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 自定义报错类
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-06-23 13:27
+ */
+public class LhyException extends RuntimeException {
+ private Integer errId;
+/*
+ public ArchivesManagementException(Integer code, String message) {
+ super(message);
+ this.code = code;
+ }
+*/
+
+ public LhyException(@NotNull ResultEnum resultEnum) {
+ super(resultEnum.getMessage());
+ this.errId = resultEnum.getCode();
+ }
+
+ public LhyException(@NotNull ResultEnum resultEnum, String message) {
+ super(resultEnum.getMessage() + ":" + message);
+ this.errId = resultEnum.getCode();
+ }
+
+ public LhyException(String message, @NotNull ResultEnum resultEnum) {
+ super(message + resultEnum.getMessage());
+ this.errId = resultEnum.getCode();
+ }
+
+ public LhyException(String message, @NotNull ResultEnum resultEnum, String message1) {
+ super(message + resultEnum.getMessage() + message1);
+ this.errId = resultEnum.getCode();
+ }
+
+ public LhyException(String message) {
+ super(message);
+ this.errId = 0;
+ }
+
+ public Integer getErrId() {
+ return errId;
+ }
+
+ public void setErrId(Integer errId) {
+ this.errId = errId;
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/exception/RetryUtil.java b/util/src/main/java/com/liuhuiyu/util/exception/RetryUtil.java
new file mode 100644
index 0000000..fe0592f
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/exception/RetryUtil.java
@@ -0,0 +1,101 @@
+package com.liuhuiyu.util.exception;
+
+import lombok.extern.log4j.Log4j2;
+
+import java.util.concurrent.Callable;
+
+/**
+ * 重复执行
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-07-05 15:44
+ */
+@Log4j2
+public class RetryUtil {
+ /**
+ * 多次重试
+ *
+ * @param num 重试次数
+ * @param callFunctions 重试调用函数
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-05 16:58
+ */
+ public static R retry(int num, Callable callFunctions) {
+ return retry(num, false, callFunctions);
+ }
+
+ /**
+ * 多次重试
+ *
+ * @param num 执行次数(失败后重试)
+ * @param callFunctions 重试调用函数
+ * @param failedCall 调用函数失败后执行
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-05 16:58
+ */
+ public static R retry(int num, Callable callFunctions, Runnable failedCall) {
+ return retry(num, true, callFunctions, failedCall);
+ }
+
+ /**
+ * 重试一次
+ *
+ * @param callFunctions 重试调用函数
+ * @param failedCall 调用函数失败后执行
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-05 16:58
+ */
+ public static R retry(Callable callFunctions, Runnable failedCall) {
+ return retry(2, true, callFunctions, failedCall);
+ }
+
+ /**
+ * 失败重试
+ *
+ * @param num 重试次数
+ * @param callFunctions [0]重拾函数,>0 失败后按照失败次数顺序执行 (失败1 执行【1】)
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-05 17:13
+ */
+ public static R retry(int num, Callable callable, Runnable... callFunctions) {
+ return retry(num, true, callable, callFunctions);
+ }
+
+ /**
+ * 失败重试
+ *
+ * @param num 重试次数
+ * @param callFunctions [0]重拾函数,>0 失败后按照失败次数顺序执行 (失败1 执行【1】)
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-05 17:13
+ */
+ public static R retry(int num, boolean loop, Callable callable, Runnable... callFunctions) {
+ int pointer = -1;
+ try {
+ for (int i = 0; i < num - 1; i++) {
+ try {
+ return callable.call();
+ }
+ catch (Exception e) {
+ if (pointer > callFunctions.length) {
+ if (loop) {
+ pointer = 0;
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ pointer++;
+ }
+ callFunctions[pointer].run();
+ }
+ }
+ return callable.call();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/functional/MapToT.java b/util/src/main/java/com/liuhuiyu/util/functional/MapToT.java
new file mode 100644
index 0000000..e2d9ed0
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/functional/MapToT.java
@@ -0,0 +1,18 @@
+package com.liuhuiyu.util.functional;
+
+import java.util.Map;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-23 16:49
+ */
+@FunctionalInterface
+public interface MapToT {
+ /**
+ * Object 转换成 类型 T
+ * @param map Map
+ * @return T
+ */
+ T mapToT(Map map);
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/functional/ObjectToT.java b/util/src/main/java/com/liuhuiyu/util/functional/ObjectToT.java
new file mode 100644
index 0000000..d662806
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/functional/ObjectToT.java
@@ -0,0 +1,16 @@
+package com.liuhuiyu.util.functional;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-23 16:48
+ */
+@FunctionalInterface
+public interface ObjectToT {
+ /**
+ * Object 转换成 类型 T
+ * @param o Object
+ * @return T
+ */
+ T objectToT(Object o);
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/functional/package-info.java b/util/src/main/java/com/liuhuiyu/util/functional/package-info.java
new file mode 100644
index 0000000..1dd6266
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/functional/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * 函数式 接口
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-23 16:47
+ */
+package com.liuhuiyu.util.functional;
\ No newline at end of file
diff --git a/util/src/main/java/com/liuhuiyu/util/list/ListUtil.java b/util/src/main/java/com/liuhuiyu/util/list/ListUtil.java
new file mode 100644
index 0000000..5716f62
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/list/ListUtil.java
@@ -0,0 +1,249 @@
+package com.liuhuiyu.util.list;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * 对象转换成List
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-04-14 10:59
+ */
+public class ListUtil {
+ public static final String ARRAY_HEAD = "[";
+
+ /**
+ * 将对象 转换成 List
+ *
+ * @param obj List对象 或者 array对象
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 9:26
+ */
+ public static List objectToList(Object obj) {
+ return objectToListT(obj, (o) -> o);
+// if (obj == null) {
+// return new ArrayList<>(0);
+// }
+// else if (obj instanceof List>) {
+// List resList;
+// List> list = (List>) obj;
+// resList = new ArrayList<>(list.size());
+// resList.addAll(list);
+// return resList;
+// }
+// else if (obj instanceof Collection) {
+// List resList;
+// Collection> list = (Collection>) obj;
+// resList = new ArrayList<>(list.size());
+// resList.addAll(list);
+// return resList;
+// }
+// else if (obj instanceof Object[]) {
+// Object[] objects = (Object[]) obj;
+// List resList = new ArrayList<>(objects.length);
+// Collections.addAll(resList, objects);
+// return resList;
+// }
+// else if (obj.getClass().getName().indexOf(ARRAY_HEAD) == 0) {
+// return new ArrayList<>(0);
+// }
+// else {
+// throw new RuntimeException("无法转换");
+// }
+
+ }
+
+ /**
+ * 将对象 转换成 List
+ *
+ * @param obj List对象
+ * @param function 转换函数
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 9:26
+ */
+ public static List objectToListT(Object obj, Function function) {
+ if (obj == null) {
+ return new ArrayList<>(0);
+ }
+ else if (obj instanceof List>) {
+ List resList;
+ List> list = (List>) obj;
+ resList = new ArrayList<>(list.size());
+ list.forEach((o) -> {
+ T t = function.apply(o);
+ if (t != null) {
+ resList.add(t);
+ }
+ });
+ return resList;
+ }
+ else if (obj instanceof Collection) {
+ List resList;
+ Collection> list = (Collection>) obj;
+ resList = new ArrayList<>(list.size());
+ list.forEach((o) -> {
+ T t = function.apply(o);
+ if (t != null) {
+ resList.add(t);
+ }
+ });
+ return resList;
+ }
+ else if (obj instanceof Object[]) {
+ Object[] objects = (Object[]) obj;
+ if (objects.length == 0) {
+ return new ArrayList<>(0);
+ }
+ else {
+ List resList = new ArrayList<>(objects.length);
+ for (Object object : objects) {
+ T t = function.apply(object);
+ if (t != null) {
+ resList.add(function.apply(t));
+ }
+ }
+ return resList;
+ }
+ }
+ else if (obj.getClass().getName().indexOf(ARRAY_HEAD) == 0) {
+ return new ArrayList<>(0);
+ }
+ else {
+ throw new RuntimeException("无法转换");
+ }
+ }
+
+ /**
+ * 获取元素t 在列表中 对应的索引
+ *
+ * @param t 查询的对象
+ * @param list 列表对象
+ * @param comparable 列表比较函数式
+ * @return java.lang.Integer
+ * @author LiuHuiYu
+ * Created DateTime 2021-05-19 22:48
+ */
+ public static Integer getIndex(T t, U[] list, BiFunction comparable) {
+ for (int i = 0; i < list.length; i++) {
+ if (comparable == null) {
+ if (t.equals(list[i])) {
+ return i;
+ }
+ }
+ else if (comparable.apply(t, list[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * 获取排序后的列表
+ *
+ * @param list 要排序的列表
+ * @param sorts 排序的排列顺序
+ * @param compare 排序匹配规则
+ * @return java.util.List
+ */
+ public static List getSortList(List list, L[] sorts, BiFunction compare) {
+ return getSortList(list, sorts, compare, true, true, true);
+ }
+
+ /**
+ * 获取排序后的列表
+ *
+ * @param list 要排序的列表
+ * @param sorts 排序的排列顺序
+ * @param compare 排序匹配规则
+ * @param asc 按照排序顺序输出
+ * @param notMatchedPostfix 未匹配的元素放到最后
+ * @param notMatchedAsc 未匹配的元素顺序输出
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-05-25 19:13
+ */
+ public static List getSortList(List list, L[] sorts, BiFunction compare, Boolean asc, Boolean notMatchedPostfix, Boolean notMatchedAsc) {
+
+ List resList = new ArrayList<>(list.size());
+ list.stream().sorted((a1, a2) -> {
+ Integer index1 = ListUtil.getIndex(a1, sorts, compare);
+ Integer index2 = ListUtil.getIndex(a2, sorts, compare);
+ if (index1 == -1 && index2 == -1) {
+ return notMatchedPostfix ? 1 : -1;
+ }
+ else if (index1 == -1) {
+ return notMatchedAsc ? 1 : -1;
+ }
+ else if (index2 == -1) {
+ return notMatchedAsc ? -1 : 1;
+ }
+ else if (asc) {
+ return index1.compareTo(index2);
+ }
+ else {
+ return index2.compareTo(index1);
+ }
+ }).forEach(resList::add);
+ return resList;
+ }
+
+ /**
+ * List 转换
+ *
+ * @param tList 原始list
+ * @param function 转换规则
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-06-04 16:08
+ */
+ public static List listToList(List tList, Function function) {
+ List rList = new ArrayList<>(0);
+ for (T item : tList) {
+ rList.add(function.apply(item));
+ }
+ return rList;
+ }
+
+ /**
+ * list 转换成 数组
+ *
+ * @param list List
+ * @return T[]
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 9:17
+ */
+ public static T[] listToArray(List list) {
+ if (list.size() == 0) {
+ @SuppressWarnings("unchecked") final T[] a1 = (T[]) new Object[0];
+ return a1;
+ }
+ Class> z = list.get(0).getClass();
+ @SuppressWarnings("unchecked") final T[] a = (T[]) Array.newInstance(z, list.size());
+ for (int i = 0; i < list.size(); i++) {
+ a[i] = list.get(i);
+ }
+ return a;
+ }
+
+ /**
+ * 数组转换 List
+ *
+ * @param array 数组
+ * @return java.util.List
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 9:17
+ */
+ public static List arrayToList(T[] array) {
+ List list = new ArrayList<>(array.length);
+ Collections.addAll(list, array);
+ return list;
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/map/MapUtil.java b/util/src/main/java/com/liuhuiyu/util/map/MapUtil.java
new file mode 100644
index 0000000..2b5fdf0
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/map/MapUtil.java
@@ -0,0 +1,485 @@
+package com.liuhuiyu.util.map;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import com.liuhuiyu.util.date.LocalDateUtil;
+import org.apache.commons.beanutils.BeanUtils;
+
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-01-20 14:53
+ */
+public class MapUtil {
+
+ boolean throwException = false;
+
+ public boolean isThrowException() {
+ return throwException;
+ }
+
+ public void setThrowException(boolean throwException) {
+ this.throwException = throwException;
+ }
+ //region 静态方法
+
+ /**
+ * Map对象转换成Map对象
+ *
+ * @param obj Map对象
+ * @return Map对象
+ */
+ public static Map mapObjectToStringKeyMap(Object obj) {
+ if (obj == null) {
+ return null;
+ }
+ else if (obj instanceof Map, ?>) {
+ Map, ?> map = (Map, ?>) obj;
+ Map resMap = new HashMap<>(map.size());
+ map.forEach((k, v) -> resMap.put(k.toString(), v));
+ return resMap;
+ }
+ else {
+ return new HashMap<>(0);
+ }
+ }
+
+ private Object getMapObjectValue(Map map, String key) {
+ return getMapObjectValue(map, key, null);
+ }
+
+ private Object getMapObjectValue(Map map, String key, Object defValue) {
+ return map.getOrDefault(key, defValue);
+ }
+
+ public static String getMapStringValue(Map map, String key) {
+ return getMapStringValue(map, key, "");
+ }
+
+ /**
+ * 获取字符串(如果key 不存在返回 “”)
+ *
+ * @param map map
+ * @param key key
+ * @return 字符串
+ */
+ public static String getMapStringValue(Map map, String key, String defValue) {
+ if (map.containsKey(key)) {
+ Object obj = map.get(key);
+ return obj == null ? defValue : obj.toString();
+ }
+ else {
+ return defValue;
+ }
+ }
+
+ public static Integer getMapIntegerValue(Map map, String key) {
+ return getMapIntegerValue(map, key, 0);
+ }
+
+ public static Integer getMapIntegerValue(Map map, String key, Integer defValue) {
+ Object obj = map.getOrDefault(key, defValue);
+ if (obj == null) {
+ return defValue;
+ }
+ else if (obj instanceof Number) {
+ return ((Number) obj).intValue();
+ }
+ else {
+ String value = obj.toString();
+ try {
+ return Integer.parseInt(value);
+ }
+ catch (NumberFormatException ex) {
+ return defValue;
+ }
+ }
+ }
+
+ public static Float getMapFloatValue(Map map, String key) {
+ return getMapFloatValue(map, key, 0F);
+ }
+
+ public static Float getMapFloatValue(Map map, String key, Float defValue) {
+ Object obj = map.getOrDefault(key, defValue);
+ if (obj == null) {
+ return defValue;
+ }
+ else if (obj instanceof Number) {
+ return ((Number) obj).floatValue();
+ }
+ else {
+ String value = obj.toString();
+ try {
+ return Float.parseFloat(value);
+ }
+ catch (NumberFormatException ex) {
+ return defValue;
+ }
+ }
+ }
+
+ public static Long getMapLongValue(Map map, String key) {
+ return getMapLongValue(map, key, 0L);
+ }
+
+ public static Long getMapLongValue(Map map, String key, Long defValue) {
+ Object obj = map.getOrDefault(key, defValue);
+ if (obj == null) {
+ return defValue;
+ }
+ else if (obj instanceof Number) {
+ return ((Number) obj).longValue();
+ }
+ else {
+ String value = obj.toString();
+ try {
+ return Long.parseLong(value);
+ }
+ catch (NumberFormatException ex) {
+ return defValue;
+ }
+ }
+ }
+
+ public static Boolean getMapBooleanValue(Map map, String key) {
+ return getMapBooleanValue(map, key, false);
+ }
+
+ public static Boolean getMapBooleanValue(Map map, String key, boolean defValue) {
+ Object obj = map.getOrDefault(key, defValue);
+ if (obj instanceof Boolean) {
+ return (Boolean) obj;
+ }
+ try {
+ return Boolean.parseBoolean(obj.toString());
+ }
+ catch (Exception ex) {
+ return defValue;
+ }
+ }
+
+ /**
+ * 将 map 中的 可转化为 int 的数字转化为 int
+ *
+ * @param resultMap map
+ * @return 修正后的map
+ */
+ public static Map mapNumberToInt(Map, ?> resultMap) {
+ Map res = new HashMap<>(resultMap.size());
+ for (Object keyObj : resultMap.keySet()) {
+ String key = keyObj.toString();
+ if (resultMap.get(key) instanceof Double) {
+ Double value = (Double) resultMap.get(key);
+ if (value.intValue() == value) {
+ res.put(key, ((Double) resultMap.get(key)).intValue());
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ else if (resultMap.get(key) instanceof List>) {
+ res.put(key, listNumberToInt((List>) resultMap.get(key)));
+ }
+ else if (resultMap.get(key) instanceof Map, ?>) {
+ res.put(key, mapNumberToInt((Map, ?>) resultMap.get(key)));
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ return res;
+ }
+
+ /**
+ * 将 list 中的 可转化为 int 的数字转化为 int
+ *
+ * @param list list
+ * @return 修正后的list
+ */
+ public static List listNumberToInt(List> list) {
+ List res = new ArrayList<>(list.size());
+ for (Object o : list) {
+ if (o instanceof Number) {
+ Double value = (Double) o;
+ if (value.intValue() == value) {
+ Object v = value.intValue();
+ res.add(v);
+ }
+ else {
+ res.add(value);
+ }
+ }
+ else if (o instanceof Map, ?>) {
+ res.add(mapNumberToInt((Map, ?>) o));
+ }
+ else if (o instanceof List>) {
+ res.add(listNumberToInt((List>) o));
+ }
+ else {
+ res.add(o);
+ }
+ }
+ return res;
+ }
+
+ public static T mapToObject(Map map, T t) {
+ if (map == null) {
+ return null;
+ }
+ try {
+ BeanUtils.populate(t, map);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return t;
+ }
+
+ //endregion
+ public static Map mapOfJsonString(String jsonString) {
+ try {
+ Gson gson = new Gson();
+ Map resultMap = gson.fromJson(jsonString, new TypeToken>() {
+ }.getType());
+ return mapDoubleToInt(resultMap);
+ }
+ catch (JsonSyntaxException e) {
+ throw new RuntimeException("无法解析成Map格式数据");
+ }
+ }
+
+ public static Map mapDoubleToInt(Map, ?> resultMap) {
+ Map res = new HashMap<>(resultMap.size());
+ for (Object keyObj : resultMap.keySet()) {
+ String key = keyObj.toString();
+ if (resultMap.get(key) instanceof Double) {
+ Double value = (Double) resultMap.get(key);
+ if (value.intValue() == value) {
+ res.put(key, ((Double) resultMap.get(key)).intValue());
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ else if (resultMap.get(key) instanceof List>) {
+ res.put(key, listDoubleToInt((List>) resultMap.get(key)));
+ }
+ else if (resultMap.get(key) instanceof Map, ?>) {
+ res.put(key, mapDoubleToInt((Map, ?>) resultMap.get(key)));
+ }
+ else {
+ res.put(key, resultMap.get(key));
+ }
+ }
+ return res;
+ }
+
+ public static List listDoubleToInt(List> list) {
+ List res = new ArrayList<>(list.size());
+ for (Object o : list) {
+ if (o instanceof Number) {
+ Double value = (Double) o;
+ if (value.intValue() == value) {
+ Object v = value.intValue();
+ res.add(v);
+ }
+ else {
+ res.add(value);
+ }
+ }
+ else if (o instanceof Map, ?>) {
+ res.add(mapDoubleToInt((Map, ?>) o));
+ }
+ else if (o instanceof List>) {
+ res.add(listDoubleToInt((List>) o));
+ }
+ else {
+ res.add(o);
+ }
+ }
+ return res;
+ }
+
+
+ public static MapUtil ofJsonString(String jsonString) {
+ Map map = mapOfJsonString(jsonString);
+ return new MapUtil(map);
+ }
+
+ private final Map map;
+
+ public MapUtil(Map map) {
+ this.map = map;
+ }
+
+ public String getStringValue(String key) {
+ return getMapStringValue(this.map, key);
+ }
+
+ public String getStringValue(String key, String defValue) {
+ return getMapStringValue(this.map, key, defValue);
+ }
+
+ public Integer getIntegerValue(String key) {
+ return getMapIntegerValue(map, key);
+ }
+
+ public Integer getIntegerValue(String key, Integer defValue) {
+ return getMapIntegerValue(map, key, defValue);
+ }
+
+ public Float getFloatValue(String key) {
+ return getMapFloatValue(map, key);
+ }
+
+ public Float getFloatValue(String key, Float defValue) {
+ return getMapFloatValue(map, key, defValue);
+ }
+
+ public Long getLongValue(String key) {
+ return getMapLongValue(map, key);
+ }
+
+ public Long getLongValue(String key, Long defValue) {
+ return getMapLongValue(map, key, defValue);
+ }
+
+ public Object getObjectValue(String key) {
+ return getMapObjectValue(map, key);
+ }
+
+ public Object getObjectValue(String key, Object defValue) {
+ return getMapObjectValue(map, key, defValue);
+ }
+
+ public T getValue(String key, T defValue) {
+ Object obj = map.getOrDefault(key, defValue);
+ if (obj.getClass().equals(defValue.getClass())) {
+ return (T) obj;
+ }
+ else if (throwException) {
+ throw new RuntimeException("类型转换失败。");
+ }
+ else {
+ return defValue;
+ }
+ }
+
+ public Boolean getBooleanValue(String key) {
+ return getMapBooleanValue(map, key);
+ }
+
+ public Boolean getBooleanValue(String key, boolean defValue) {
+ return getMapBooleanValue(map, key, defValue);
+ }
+
+ public Timestamp getTimestampValue(String key) {
+ return getTimestampValue(key, Timestamp.valueOf(LocalDateTime.now()));
+ }
+
+ public Timestamp getTimestampValue(String key, Timestamp defValue) {
+ Object obj = map.get(key);
+ if (obj == null) {
+ return defValue;
+ }
+ else if (obj instanceof Timestamp) {
+ return (Timestamp) obj;
+ }
+ else if (obj instanceof Number) {
+ return new Timestamp(((Number) obj).longValue());
+ }
+ else if (obj instanceof String) {
+ try {
+ return Timestamp.valueOf((String) obj);
+ }
+ catch (Exception ex) {
+ return defValue;
+ }
+ }
+ else {
+ return defValue;
+ }
+ }
+
+ public T getValue(String key, Function function) {
+ return function.apply(map.getOrDefault(key, null));
+ }
+
+ public List getListValue(String key, Function function) {
+ Function> function2 = (obj) -> new ResInfo<>(true, function.apply(obj));
+ return getCollectionValueAllowJudgment(key, function2, () -> new ArrayList<>(0));
+ }
+
+ /**
+ * Collection获取(List;Set)
+ *
+ * @param key 键值
+ * @param function 转换
+ * @param initializeCollection 初始化 Collection
+ * @return java.util.Collection
+ * @author LiuHuiYu
+ * Created DateTime 2021-08-06 9:50
+ */
+ public > R getCollectionValue(String key, Function function, Supplier initializeCollection) {
+ Function> function2 = (obj) -> new ResInfo<>(true, function.apply(obj));
+ return getCollectionValueAllowJudgment(key, function2, initializeCollection);
+ }
+
+ /**
+ * Collection获取(List;Set)
+ *
+ * @param key 键值
+ * @param function 转换
+ * @param initializeCollection 初始化 Collection
+ * @return java.util.Collection
+ * @author LiuHuiYu
+ * Created DateTime 2021-08-06 9:50
+ */
+ public > R getCollectionValueAllowJudgment(String key, Function> function, Supplier initializeCollection) {
+ R resList = initializeCollection.get();
+ if (this.map.containsKey(key)) {
+ Object obj = this.map.get(key);
+ if (obj instanceof Collection>) {
+ Collection> list = (Collection>) obj;
+ list.forEach(item -> {
+ ResInfo resInfo = function.apply(item);
+ if (resInfo.res) {
+ resList.add(resInfo.resData);
+ }
+ });
+ return resList;
+ }
+ else if (this.throwException) {
+ throw new RuntimeException("无法解析非List数据");
+ }
+ else {
+ return resList;
+ }
+ }
+ else if (this.throwException) {
+ throw new RuntimeException("不存在的键值。");
+ }
+ else {
+ return resList;
+ }
+ }
+
+ public static class ResInfo {
+ Boolean res;
+ T resData;
+
+ public ResInfo(Boolean res, T resData) {
+ this.res = res;
+ this.resData = resData;
+ }
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/model/Result.java b/util/src/main/java/com/liuhuiyu/util/model/Result.java
new file mode 100644
index 0000000..3b9e576
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/model/Result.java
@@ -0,0 +1,125 @@
+package com.liuhuiyu.util.model;
+
+import lombok.Data;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-07-08 11:44
+ */
+@Data
+public class Result implements Serializable {
+ public static final int OK = 0;
+ public static final int ERROR = -1;
+
+ /**
+ * 返回码
+ */
+ private Integer flag;
+ /**
+ * 信息
+ */
+ private String msg;
+ /**
+ * 返回数据
+ */
+ private T data;
+
+ public Result() {
+ this.flag = OK;
+ this.msg = "操作成功";
+ this.data = null;
+ }
+
+ private Result(T data) {
+ this();
+ this.data = data;
+ }
+
+ private Result(T data, Integer flag) {
+ this();
+ this.data = data;
+ this.flag = flag;
+ }
+
+ private Result(T data, Integer flag, String msg) {
+ this();
+ this.data = data;
+ this.flag = flag;
+ this.msg = msg;
+ }
+
+ public boolean isSuccess() {
+ return this.flag.equals(OK);
+ }
+
+ /**
+ * 通过静态方法获取实例
+ */
+ @Contract(value = "_ -> new", pure = true)
+ public static @NotNull Result of(T data) {
+ return new Result<>(data);
+ }
+
+ @Contract(value = "_, _ -> new", pure = true)
+ public static @NotNull Result of(T data, Integer flag) {
+ return new Result<>(data, flag);
+ }
+
+ @Contract(value = "_, _, _ -> new", pure = true)
+ public static @NotNull Result of(T data, Integer flag, String msg) {
+ return new Result<>(data, flag, msg);
+ }
+
+ @Contract(value = "_ -> new", pure = true)
+ public static @NotNull Result error(String msg) {
+ return new Result<>(null, ERROR, msg);
+ }
+
+ @Contract(value = "_, _-> new", pure = true)
+ public static @NotNull Result error(String msg, int errorCode) {
+ return new Result<>(null, errorCode, msg);
+ }
+
+ @Contract(value = " -> new", pure = true)
+ public static @NotNull Result success() {
+ return new Result<>(null, OK, "");
+ }
+
+ private static String FLAG_KEY = "flag";
+ private static String MSG_KEY = "msg";
+ private static String DATA_KEY = "data";
+
+ public static @NotNull Result ofMap(Map map, Class clazz) {
+ Result result = new Result<>();
+ if (map.containsKey(FLAG_KEY)) {
+ result.flag = ((Number) map.get(FLAG_KEY)).intValue();
+ }
+ else {
+ throw new RuntimeException("缺少关键字" + FLAG_KEY);
+ }
+ if (map.containsKey(MSG_KEY)) {
+ result.msg = map.get(MSG_KEY).toString();
+ }
+ else {
+ throw new RuntimeException("缺少关键字" + MSG_KEY);
+ }
+ if (map.containsKey(DATA_KEY)) {
+ if (clazz.isInstance(map.get(DATA_KEY))) {
+ result.data = clazz.cast(map.get(DATA_KEY));
+ }
+ else {
+ throw new RuntimeException("Map 关键字‘" + DATA_KEY + "’无法转换为当前类型。");
+ }
+ }
+ else {
+ throw new RuntimeException("缺少关键字" + DATA_KEY);
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/util/src/main/java/com/liuhuiyu/util/security/RsaUtil.java b/util/src/main/java/com/liuhuiyu/util/security/RsaUtil.java
new file mode 100644
index 0000000..03ac548
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/security/RsaUtil.java
@@ -0,0 +1,179 @@
+package com.liuhuiyu.util.security;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.*;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-02-18 9:00
+ */
+public class RsaUtil {
+ public static final String CHARSET = "UTF-8";
+ public static final String RSA_ALGORITHM = "RSA";
+ public static final String MAP_KEY_PUBLIC = "publicKey";
+ public static final String MAP_KEY_PRIVATE = "privateKey";
+
+ public static Map createKeys(int keySize) {
+ //为RSA算法创建一个KeyPairGenerator对象
+ KeyPairGenerator kpg;
+ try {
+ kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalArgumentException("没有[" + RSA_ALGORITHM + "]的算法");
+ }
+
+ //初始化KeyPairGenerator对象,密钥长度
+ kpg.initialize(keySize);
+ //生成密匙对
+ KeyPair keyPair = kpg.generateKeyPair();
+ //得到公钥
+ Key publicKey = keyPair.getPublic();
+ String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
+ //得到私钥
+ Key privateKey = keyPair.getPrivate();
+ String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
+ Map keyPairMap = new HashMap<>(2);
+ keyPairMap.put(MAP_KEY_PUBLIC, publicKeyStr);
+ keyPairMap.put(MAP_KEY_PRIVATE, privateKeyStr);
+
+ return keyPairMap;
+ }
+
+ /**
+ * 得到公钥
+ *
+ * @param publicKey 密钥字符串(经过base64编码)
+ * @throws NoSuchAlgorithmException 字符串错误
+ */
+ public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ //通过X509编码的Key指令获得公钥对象
+ KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
+ X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
+ return (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
+ }
+
+ /**
+ * 得到私钥
+ *
+ * @param privateKey 密钥字符串(经过base64编码)
+ * @throws NoSuchAlgorithmException 字符串错误
+ */
+ public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ //通过PKCS#8编码的Key指令获得私钥对象
+ KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
+ PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
+ return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
+ }
+
+ /**
+ * 公钥加密
+ *
+ * @param data 要加密数据
+ * @param publicKey 公钥
+ * @return 加密后的数据
+ */
+ public static String publicEncrypt(String data, RSAPublicKey publicKey) {
+ return encrypt(data, publicKey);
+ }
+
+ private static String encrypt(String data, Key key) {
+ try {
+ RSAKey rsaKey = (RSAKey) key;
+ Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), rsaKey.getModulus().bitLength()));
+ } catch (Exception e) {
+ throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
+ }
+ }
+
+ /**
+ * 私钥解密
+ *
+ * @param data 要解密数据
+ * @param privateKey 私钥
+ * @return 解密后的数据
+ */
+ public static String privateDecrypt(String data, RSAPrivateKey privateKey) {
+ return decrypt(data, privateKey);
+ }
+
+ /**
+ * 私钥加密
+ *
+ * @param data 要加密的数据
+ * @param privateKey 私钥
+ * @return 加密后的数据
+ */
+ public static String privateEncrypt(String data, RSAPrivateKey privateKey) {
+ return encrypt(data, privateKey);
+ }
+
+ /**
+ * 公钥解密
+ *
+ * @param data 要解密的数据
+ * @param publicKey 公钥
+ * @return 解密后的数据
+ */
+ public static String publicDecrypt(String data, RSAPublicKey publicKey) {
+ return decrypt(data, publicKey);
+ }
+
+ private static String decrypt(String data, Key key) {
+ try {
+ RSAKey rsaKey = (RSAKey) key;
+ Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), rsaKey.getModulus().bitLength()), CHARSET);
+ } catch (Exception e) {
+ throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
+ }
+ }
+
+
+
+ private static byte[] rsaSplitCodec(Cipher cipher, int opMode, byte[] dataBytes, int keySize) throws IOException {
+ int maxBlock;
+ if (opMode == Cipher.DECRYPT_MODE) {
+ maxBlock = keySize / 8;
+ }
+ else {
+ maxBlock = keySize / 8 - 11;
+ }
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ int offSet = 0;
+ byte[] buff;
+ int i = 0;
+ try {
+ while (dataBytes.length > offSet) {
+ if (dataBytes.length - offSet > maxBlock) {
+ buff = cipher.doFinal(dataBytes, offSet, maxBlock);
+ }
+ else {
+ buff = cipher.doFinal(dataBytes, offSet, dataBytes.length - offSet);
+ }
+ out.write(buff, 0, buff.length);
+ i++;
+ offSet = i * maxBlock;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
+ }
+ return out.toByteArray();
+ }
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/thread/ExecutorBuilder.java b/util/src/main/java/com/liuhuiyu/util/thread/ExecutorBuilder.java
new file mode 100644
index 0000000..1615199
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/thread/ExecutorBuilder.java
@@ -0,0 +1,133 @@
+package com.liuhuiyu.util.thread;
+
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-07-17 10:29
+ */
+public class ExecutorBuilder {
+ /**
+ * 参数初始化(初始化cpu数量)
+ * Created DateTime 2021-07-17 10:31
+ */
+ private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+ /**
+ * 初始化线程数量(2-4)
+ * Created DateTime 2021-07-17 10:51
+ */
+ private int corePoolSize = Math.max(2, Math.min(CPU_COUNT - 1, 4));
+ /**
+ * 线程池大小(cpu * 2 +1)
+ * Created DateTime 2021-07-17 10:51
+ */
+ private int maxPoolSize = CPU_COUNT * 2 + 1;
+ /**
+ * 阻塞队列(20)
+ * Created DateTime 2021-07-17 10:52
+ */
+ private int workQueue = 20;
+ /**
+ * 线程空闲后的存活时长(30秒)
+ * Created DateTime 2021-07-17 10:52
+ */
+ private int keepAliveSeconds = 30;
+ private String threadName = "taskExecutor-";
+
+ public static ExecutorBuilder create() {
+ return new ExecutorBuilder();
+ }
+
+ /**
+ * 核心线程数量大小
+ *
+ * @param corePoolSize 核心线程数量大小
+ * @return com.liuhuiyu.util.thread.ThreadUtil.ExecutorBuilder
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 10:28
+ */
+ public ExecutorBuilder corePoolSize(int corePoolSize) {
+ this.corePoolSize = corePoolSize;
+ return this;
+ }
+
+ /**
+ * 线程池最大容纳线程数
+ *
+ * @param maxPoolSize 线程池最大容纳线程数
+ * @return com.liuhuiyu.util.thread.ThreadUtil.ExecutorBuilder
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 10:28
+ */
+ public ExecutorBuilder maxPoolSize(int maxPoolSize) {
+ this.maxPoolSize = maxPoolSize;
+ return this;
+ }
+
+ /**
+ * 阻塞队列
+ *
+ * @param workQueue 阻塞队列
+ * @return com.liuhuiyu.util.thread.ThreadUtil.ExecutorBuilder
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 10:28
+ */
+ public ExecutorBuilder workQueue(int workQueue) {
+ this.workQueue = workQueue;
+ return this;
+ }
+
+ /**
+ * 线程空闲后的存活时长
+ *
+ * @param keepAliveSeconds 线程空闲后的存活时长
+ * @return com.liuhuiyu.util.thread.ThreadUtil.ExecutorBuilder
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 10:27
+ */
+ public ExecutorBuilder keepAliveSeconds(int keepAliveSeconds) {
+ this.keepAliveSeconds = keepAliveSeconds;
+ return this;
+ }
+
+ /**
+ * 线程名称
+ *
+ * @param threadName 线程名称
+ * @return com.liuhuiyu.util.thread.ThreadUtil.ExecutorBuilder
+ * @author LiuHuiYu
+ * Created DateTime 2021-07-17 10:27
+ */
+ public ExecutorBuilder threadName(String threadName) {
+ this.threadName = threadName;
+ return this;
+ }
+
+ public ThreadPoolTaskExecutor builder() {
+// return (r)->{
+// Thread thread=new Thread(r);
+// thread.setName(threadName);
+// thread.start();
+// };
+ ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
+ //核心线程数
+ threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
+ //最大线程数
+ threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
+ //等待队列
+ threadPoolTaskExecutor.setQueueCapacity(workQueue);
+ //线程前缀
+ threadPoolTaskExecutor.setThreadNamePrefix(threadName);
+ //线程池维护线程所允许的空闲时间,单位为秒
+ threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
+ // 线程池对拒绝任务(无线程可用)的处理策略
+ threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ threadPoolTaskExecutor.initialize();
+ return threadPoolTaskExecutor;
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/thread/ThreadUtil.java b/util/src/main/java/com/liuhuiyu/util/thread/ThreadUtil.java
new file mode 100644
index 0000000..52977f3
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/thread/ThreadUtil.java
@@ -0,0 +1,89 @@
+package com.liuhuiyu.util.thread;
+
+import lombok.extern.log4j.Log4j2;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.scheduling.concurrent.ExecutorConfigurationSupport;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * 多线程工具
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-04-14 14:02
+ */
+@Log4j2
+public class ThreadUtil {
+ /**
+ * 异步List循环(等待返回结果)
+ *
+ * @param list list
+ * @param consumer list处理
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-14 14:03
+ */
+ public static void asynchronousDataLoading(List list, Consumer consumer) {
+ asynchronousDataLoading(list, consumer, ExecutorBuilder.create().threadName("async-load-").builder());
+ }
+
+ /**
+ * 异步List循环(等待返回结果)
+ *
+ * @param list list
+ * @param consumer list处理
+ * @param executor 线程池
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-14 14:03
+ */
+ public static void asynchronousDataLoading(@NotNull List list, Consumer consumer, ThreadPoolTaskExecutor executor) {
+ asynchronousDataLoading(list, consumer, executor, executor::shutdown);
+ }
+
+ /**
+ * 异步List循环(等待返回结果)
+ *
+ * @param list list
+ * @param consumer list处理
+ * @param executor 线程池
+ * @param closeExecutor 提供关闭线程池的方法
+ * @author LiuHuiYu
+ * Created DateTime 2021-04-14 14:03
+ */
+ public static void asynchronousDataLoading(@NotNull List list, Consumer consumer, Executor executor, Runnable closeExecutor) {
+ CompletableFuture.allOf(list.stream()
+ .map(item -> CompletableFuture.runAsync(() -> consumer.accept(item), executor))
+ .toArray(CompletableFuture[]::new)).join();
+ closeExecutor.run();
+ }
+
+ /**
+ * 休眠(带返回状态(成功:正常无中断;失败:异常中断引发休眠结束))
+ *
+ * @param millis 休眠时间
+ * @author LiuHuiYu
+ * Created DateTime 2021-08-20 14:43
+ */
+ public static boolean sleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ return true;
+ }
+ catch (InterruptedException e) {
+ Thread.currentThread().interrupt();//如果不加上这一句,那么cd将会都是false,因为在捕捉到InterruptedException异常的时候就会自动的中断标志置为了false
+ Boolean c = Thread.interrupted();
+ Boolean d = Thread.interrupted();
+ log.error("中断引发休眠异常:{};重置中断位{}->{}", e.getMessage(), c, d);
+ return false;
+ }
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/web/AddressRoutingUtil.java b/util/src/main/java/com/liuhuiyu/util/web/AddressRoutingUtil.java
new file mode 100644
index 0000000..da4df2d
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/web/AddressRoutingUtil.java
@@ -0,0 +1,51 @@
+package com.liuhuiyu.util.web;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+/**
+ * 地址生成工具
+ *
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-06-23 13:42
+ */
+public class AddressRoutingUtil {
+ /**
+ * 获取地址
+ *
+ * @param request request
+ * @param root 根目录
+ * @param path 网页路径
+ * @return 可以访问的地址
+ */
+ public static String getFullAddress(HttpServletRequest request, String root, String path) {
+ return getFullAddress(request, root, path, null);
+ }
+
+ /**
+ * 获取地址
+ *
+ * @param request request
+ * @param root 根目录
+ * @param path 网页路径
+ * @param parameter 参数对
+ * @return 可以访问的地址
+ */
+ public static String getFullAddress(HttpServletRequest request, String root, String path, Map parameter) {
+ String foot = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
+ String address;
+ address = foot + root + path;
+
+ if (null == parameter) {
+ return address;
+ } else {
+ String linkSymbol = "?";
+ for (String key : parameter.keySet()) {
+ address = String.format("%1$s%2$s%3$s=%4$s", address, linkSymbol, key, parameter.get(key).toString());
+ linkSymbol = "&";
+ }
+ return address;
+ }
+ }
+}
diff --git a/util/src/main/java/com/liuhuiyu/util/web/HttpUtil.java b/util/src/main/java/com/liuhuiyu/util/web/HttpUtil.java
new file mode 100644
index 0000000..394aa12
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/web/HttpUtil.java
@@ -0,0 +1,29 @@
+package com.liuhuiyu.util.web;
+
+import com.liuhuiyu.util.asserts.*;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-06-23 13:23
+ */
+public class HttpUtil {
+ public static @NotNull HttpServletRequest getHttpServletRequest() {
+ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ LhyAssert.assertNotNull(attributes, "Spring配置错误");
+ return attributes.getRequest();
+ }
+
+ public static HttpServletResponse getHttpServletResponse() {
+ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ LhyAssert.assertNotNull(attributes, "Spring配置错误");
+ return attributes.getResponse();
+ }
+}
+
diff --git a/util/src/main/java/com/liuhuiyu/util/web/JsUtil.java b/util/src/main/java/com/liuhuiyu/util/web/JsUtil.java
new file mode 100644
index 0000000..9f79089
--- /dev/null
+++ b/util/src/main/java/com/liuhuiyu/util/web/JsUtil.java
@@ -0,0 +1,107 @@
+package com.liuhuiyu.util.web;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-03-09 11:35
+ */
+public class JsUtil {
+ private static final String BASE_64_HASH = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ public static final String VALUE_RANGE_REGEX = "([^\\u0000-\\u00ff])";
+
+ public static boolean isMatcher(String inStr, String reg) {
+ Pattern pattern = Pattern.compile(reg);
+ Matcher matcher = pattern.matcher(inStr);
+ return matcher.matches();
+ }
+
+ /**
+ * btoa method
+ *
+ * @param inStr 字符串
+ * @return 加密后的字符串
+ */
+ public static String btoa(String inStr) {
+ if (inStr == null || isMatcher(inStr, VALUE_RANGE_REGEX)) {
+ return null;
+ }
+ StringBuilder result = new StringBuilder();
+ int i = 0;
+ int mod = 0;
+ int ascii;
+ int prev = 0;
+ while (i < inStr.length()) {
+ ascii = inStr.charAt(i);
+ mod = i % 3;
+ switch (mod) {
+ case 0:
+ result.append(BASE_64_HASH.charAt(ascii >> 2));
+ break;
+ case 1:
+ result.append(BASE_64_HASH.charAt((prev & 3) << 4 | (ascii >> 4)));
+ break;
+ case 2:
+ result.append(BASE_64_HASH.charAt((prev & 0x0f) << 2 | (ascii >> 6)));
+ result.append(BASE_64_HASH.charAt(ascii & 0x3f));
+ break;
+ default:
+ break;
+ }
+ prev = ascii;
+ i++;
+ }
+
+ if (mod == 0) {
+ result.append(BASE_64_HASH.charAt((prev & 3) << 4));
+ result.append("==");
+ }
+ else if (mod == 1) {
+ result.append(BASE_64_HASH.charAt((prev & 0x0f) << 2));
+ result.append("=");
+ }
+ return result.toString();
+ }
+
+
+ /**
+ * // atob method
+ * // 逆转encode的思路即可
+ *
+ * @param inStr 加密字符串
+ * @return 解密后字符串
+ */
+ public static String atob(String inStr) {
+ if (inStr == null) {
+ return null;
+ }
+ inStr = inStr.replaceAll("\\s|=", "");
+ StringBuilder result = new StringBuilder();
+ int cur;
+ int prev = -1;
+ int mod;
+ int i = 0;
+ while (i < inStr.length()) {
+ cur = BASE_64_HASH.indexOf(inStr.charAt(i));
+ mod = i % 4;
+ switch (mod) {
+ case 1:
+ result.append((char) (prev << 2 | cur >> 4));
+ break;
+ case 2:
+ result.append((char) ((prev & 0x0f) << 4 | cur >> 2));
+ break;
+ case 3:
+ result.append((char) ((prev & 3) << 6 | cur));
+ break;
+ default:
+ break;
+ }
+ prev = cur;
+ i++;
+ }
+ return result.toString();
+ }
+}
diff --git a/util/src/test/java/com/liuhuiyu/util/HttpUtilTest.java b/util/src/test/java/com/liuhuiyu/util/HttpUtilTest.java
new file mode 100644
index 0000000..e2f91d0
--- /dev/null
+++ b/util/src/test/java/com/liuhuiyu/util/HttpUtilTest.java
@@ -0,0 +1,39 @@
+package com.liuhuiyu.util;
+
+import junit.framework.TestCase;
+import lombok.extern.log4j.Log4j2;
+import sun.misc.Contended;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2020-12-29 9:16
+ */
+@Log4j2
+public class HttpUtilTest extends TestCase {
+
+ public void testA1() {
+ log.info("Run OK");
+ }
+// private volatile boolean s;
+// private volatile String b(){
+//
+// }
+// @Contended
+// class b{
+////LoadLoad;
+////StoreStore;
+// void s2(){
+// ----StoreStoreBarrier----
+// Load;
+// Store;
+// }
+//// StoreLoad;
+// }
+
+ public void testStringToInt() {
+ String s = "123s";
+ Integer i = Integer.getInteger(s, 101);
+ log.info("i = {}", i);
+ }
+}
\ No newline at end of file
diff --git a/util/src/test/java/com/liuhuiyu/util/exception/RetryUtilTest.java b/util/src/test/java/com/liuhuiyu/util/exception/RetryUtilTest.java
new file mode 100644
index 0000000..5293890
--- /dev/null
+++ b/util/src/test/java/com/liuhuiyu/util/exception/RetryUtilTest.java
@@ -0,0 +1,176 @@
+package com.liuhuiyu.util.exception;
+
+import com.liuhuiyu.util.thread.ThreadUtil;
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-07-05 15:59
+ */
+@Log4j2
+public class RetryUtilTest {
+// @Test
+// public void t1() {
+// time = System.currentTimeMillis();
+// String s = s1(time, "abc");
+// log.info("返回信息:{}", s);
+// }
+//
+// long time;
+
+// private String s1(long time, String s) {
+// log.info("进入时间{}", time);
+// getTime();
+// long newTime = System.currentTimeMillis();
+// log.info("{},{}", time, newTime);
+// if (newTime > time + 1000) {
+// return s;
+// }
+// Object o = RetryUtil.setRetryTimes(13).retry(s);
+// if (o != null) {
+// return o.toString();
+// }
+// throw new RuntimeException("错误");
+// }
+
+ private long getTime() {
+ log.info("gettime");
+ return System.currentTimeMillis();
+ }
+
+ private int retryTimes = 3;
+
+ @Test
+ public void upperMethod() {
+ method("123", "456");
+ }
+
+ public void method(String param1, String param2) {
+ System.out.println(param1 + param2);
+
+ // 其他一些操作,但是没有得到预期的返回结果,或者抛出异常
+ boolean isException = true;
+ if (isException && retryTimes > 0) {
+ retryTimes--;
+ method(param1, param2);
+ }
+ }
+
+ @Test
+ public void upperMethod2() {
+ method(3, "123", "456");
+ }
+
+ public void method(int retryTimes, String param1, String param2) {
+ System.out.println(param1 + param2);
+
+ // 其他一些操作,但是没有得到预期的返回结果,或者抛出异常
+ boolean isException = true;
+ if (isException && retryTimes > 0) {
+ method(--retryTimes, param1, param2);
+ }
+ }
+
+ // @Test
+// public void mainMethod() throws InterruptedException {
+// String s = subMethod("123", "456");
+// log.info(s);
+// }
+//
+// public String subMethod(String param1, String param2) throws InterruptedException {
+// long t = System.currentTimeMillis();
+// log.info("begin:{},{},{}", param1, param2, t);
+// Thread.sleep(100);
+// new RetryUtil().retry(10, param1, param2);
+// long t2 = System.currentTimeMillis();
+// log.info("end:{},{},{}-{}", param1, param2, t, t2);
+// return param1 + param2 + t;
+// }
+ @Test
+ public void retry() {
+ Map map = new HashMap<>(1);
+ long time = System.currentTimeMillis();
+ RetryUtil.retry(3, () -> {
+ try {
+ Thread.sleep(600);
+ }
+ catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ map.put("res", s(time));
+ return false;
+ });
+ log.info(map);
+ }
+
+ @Test
+ public void retry2() {
+ Map map = new HashMap<>(1);
+ long time = System.currentTimeMillis();
+ RetryUtil.retry(10, () -> {
+ return time;
+ }, () -> {
+ try {
+ log.info("失败次执行");
+ Thread.sleep(300);
+ }
+ catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ });
+ log.info(map);
+ }
+
+ @Test
+ public void retry3() {
+ Map map = new HashMap<>(1);
+ long time = System.currentTimeMillis();
+ RetryUtil.retry(3, () -> {
+ map.put("res", s(time));
+ return time;
+ }, () -> {
+ try {
+ log.info("失败1次执行");
+ Thread.sleep(500);
+ }
+ catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }, () -> {
+ try {
+ log.info("失败2次执行");
+ Thread.sleep(500);
+ }
+ catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ });
+ log.info(map);
+ }
+
+ private String s(long o) {
+ long time = System.currentTimeMillis();
+ if (o > time - 1000) {
+ throw new RuntimeException("");
+ }
+ return "" + time;
+ }
+
+ @Test
+ public void testTime(){
+ LocalDateTime time=LocalDateTime.now().plusSeconds(5);
+ ThreadUtil.sleep(2000);
+ log.info("2秒后比较{}",time.isBefore(LocalDateTime.now()));
+ ThreadUtil.sleep(2000);
+ log.info("2秒后比较{}",time.isBefore(LocalDateTime.now()));
+ ThreadUtil.sleep(2000);
+ log.info("2秒后比较{}",time.isBefore(LocalDateTime.now()));
+ }
+}
\ No newline at end of file
diff --git a/util/src/test/java/com/liuhuiyu/util/list/ListUtilTest.java b/util/src/test/java/com/liuhuiyu/util/list/ListUtilTest.java
new file mode 100644
index 0000000..ab40d67
--- /dev/null
+++ b/util/src/test/java/com/liuhuiyu/util/list/ListUtilTest.java
@@ -0,0 +1,119 @@
+package com.liuhuiyu.util.list;
+
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-05-25 19:16
+ */
+@Log4j2
+public class ListUtilTest {
+ @Test
+ public void objectToList() {
+ Object o = getList();
+ List list = ListUtil.objectToList(o);
+ log.info("转换List:{}", list);
+ Object o1 = getArray();
+ List list1 = ListUtil.objectToList(o1);
+ log.info("转换List:{}", list1);
+ Object o2 = new int[]{};
+ List list2 = ListUtil.objectToList(o2);
+ log.info("转换List:{}", list2);
+ }
+
+ @Test
+ public void objectToListT() {
+ Object o = getList();
+ List list = ListUtil.objectToListT(o, (obj) -> {
+ if (obj instanceof Integer) {
+ return (Integer) obj;
+ }
+ else {
+ return 0;
+ }
+ });
+ log.info("转换List:{}", list);
+ Object o1 = getArray();
+ List list1 = ListUtil.objectToListT(o1, (obj) -> {
+ if (obj instanceof Integer) {
+ return (Integer) obj;
+ }
+ else {
+ return 0;
+ }
+ });
+ log.info("转换List:{}", list1);
+ }
+
+
+ @Test
+ public void getSortList() {
+ List list = new ArrayList<>();
+ Collections.addAll(list, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ Integer[] sorts = {1, 3, 5, 7, 9, 4, 8};
+ BiFunction compare = Integer::equals;
+ List res;
+ res = ListUtil.getSortList(list, sorts, compare);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, true, false, false);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, true, false, true);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, true, true, false);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, true, true, true);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, false, false, false);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, false, false, true);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, false, true, false);
+ log.info(res);
+ res = ListUtil.getSortList(list, sorts, compare, false, true, true);
+ log.info(res);
+ }
+
+ @Test
+ public void listToList() {
+ List integerList = this.getList();
+ List longList = ListUtil.listToList(integerList, Integer::longValue);
+ List strList = ListUtil.listToList(integerList, (i) -> "'" + i.toString() + "'");
+ log.info("{}->{}->{}", integerList, longList, strList);
+ }
+
+ @Test
+ public void listToArray() {
+ List integerList = this.getList();
+ Integer[] is = ListUtil.listToArray(integerList);
+ log.info("{}->{}", integerList, is);
+ }
+
+ @Test
+ public void arrayToList() {
+ Integer[] array = getArray();
+ List list = ListUtil.arrayToList(array);
+ log.info("{}->{}", array, list);
+ }
+
+ private List getList() {
+ List integerList = new ArrayList<>(10);
+ for (int i = 0; i < 10; i++) {
+ integerList.add(i);
+ }
+ return integerList;
+ }
+
+ private Integer[] getArray() {
+ return new Integer[]{1, 2, 3, 4, 5, 6, 7};
+ }
+}
\ No newline at end of file
diff --git a/util/src/test/java/com/liuhuiyu/util/map/MapUtilTest.java b/util/src/test/java/com/liuhuiyu/util/map/MapUtilTest.java
new file mode 100644
index 0000000..ae39db1
--- /dev/null
+++ b/util/src/test/java/com/liuhuiyu/util/map/MapUtilTest.java
@@ -0,0 +1,24 @@
+package com.liuhuiyu.util.map;
+
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-06-07 9:02
+ */
+@Log4j2
+public class MapUtilTest {
+ @Test
+ public void test() {
+ String json = "{a:1,b:1.5,c:[{j:1,k:1.6},{j:2,k:1.7}],d:8088.0,16}";
+ Map map = MapUtil.mapOfJsonString(json);
+ log.info(map);
+ }
+
+}
\ No newline at end of file
diff --git a/util/src/test/java/com/liuhuiyu/util/security/RSAUtilTest.java b/util/src/test/java/com/liuhuiyu/util/security/RSAUtilTest.java
new file mode 100644
index 0000000..94013df
--- /dev/null
+++ b/util/src/test/java/com/liuhuiyu/util/security/RSAUtilTest.java
@@ -0,0 +1,82 @@
+package com.liuhuiyu.util.security;
+
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Map;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-02-18 9:22
+ */
+@Log4j2
+public class RSAUtilTest {
+
+ @Test
+ public void createKeys() {
+ int keySize = 512;
+ Map map = RsaUtil.createKeys(keySize);
+ log.info(map);
+ }
+
+ @Test
+ public void getPublicKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ int keySize = 512;
+ Map map = RsaUtil.createKeys(keySize);
+ RSAPublicKey key = RsaUtil.getPublicKey(map.get(RsaUtil.MAP_KEY_PUBLIC));
+ log.info(key);
+ }
+
+ @Test
+ public void getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ int keySize = 512;
+ Map map = RsaUtil.createKeys(keySize);
+ RSAPrivateKey key = RsaUtil.getPrivateKey(map.get(RsaUtil.MAP_KEY_PRIVATE));
+ log.info(key);
+ }
+
+ @Test
+ public void publicEncrypt() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ int keySize = 512;
+ String info = "abcd";
+ Map map = RsaUtil.createKeys(keySize);
+ String encryptInfo = RsaUtil.publicEncrypt(info, RsaUtil.getPublicKey(map.get(RsaUtil.MAP_KEY_PUBLIC)));
+ log.info(encryptInfo);
+ }
+
+ @Test
+ public void privateDecrypt() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ int keySize = 512;
+ String info = "abcd";
+ Map map = RsaUtil.createKeys(keySize);
+ String encryptInfo = RsaUtil.publicEncrypt(info, RsaUtil.getPublicKey(map.get(RsaUtil.MAP_KEY_PUBLIC)));
+ log.info(encryptInfo);
+ String decryptInfo=RsaUtil.privateDecrypt(encryptInfo,RsaUtil.getPrivateKey(map.get(RsaUtil.MAP_KEY_PRIVATE)));
+ log.info(decryptInfo);
+ }
+
+ @Test
+ public void privateEncrypt() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ int keySize = 512;
+ String info = "abcd";
+ Map map = RsaUtil.createKeys(keySize);
+ String encryptInfo = RsaUtil.privateEncrypt(info, RsaUtil.getPrivateKey(map.get(RsaUtil.MAP_KEY_PRIVATE)));
+ log.info(encryptInfo);
+ }
+
+ @Test
+ public void publicDecrypt() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ int keySize = 512;
+ String info = "abcd";
+ Map map = RsaUtil.createKeys(keySize);
+ String encryptInfo = RsaUtil.privateEncrypt(info, RsaUtil.getPrivateKey(map.get(RsaUtil.MAP_KEY_PRIVATE)));
+ log.info(encryptInfo);
+ String decryptInfo=RsaUtil.publicDecrypt(encryptInfo,RsaUtil.getPublicKey(map.get(RsaUtil.MAP_KEY_PUBLIC)));
+ log.info(decryptInfo);
+ }
+}
\ No newline at end of file
diff --git a/util/src/test/java/com/liuhuiyu/util/thread/ThreadCpu.java b/util/src/test/java/com/liuhuiyu/util/thread/ThreadCpu.java
new file mode 100644
index 0000000..3c4af63
--- /dev/null
+++ b/util/src/test/java/com/liuhuiyu/util/thread/ThreadCpu.java
@@ -0,0 +1,51 @@
+package com.liuhuiyu.util.thread;
+
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-07-30 20:25
+ */
+@Log4j2
+public class ThreadCpu {
+ private static int x = 0, y = 0;
+ private static int a = 0, b = 0;
+ int i = 0;
+
+ @Test
+ public void test() throws InterruptedException {
+ int i = 0;
+ for (; ; ) {
+ i++;
+ x = 0;
+ y = 0;
+ a = 0;
+ b = 0;
+ Thread one = new Thread(() -> {
+ a = 1;
+ x = b;
+ });
+
+ Thread other = new Thread(() -> {
+ b = 1;
+ y = a;
+ });
+ one.start();
+ other.start();
+ one.join();
+ other.join();
+ String result = "第" + i + "次 (" + x + "," + y + ")";
+ // 出现00组合 证明cpu乱序执行了
+ if (x == 0 && y == 0) {
+ System.err.println(result);
+ break;
+ } else {
+ //System.out.println(result);
+ }
+ }
+ }
+}
diff --git a/util/src/test/java/com/liuhuiyu/util/thread/ThreadUtilTest.java b/util/src/test/java/com/liuhuiyu/util/thread/ThreadUtilTest.java
new file mode 100644
index 0000000..3bf7eb9
--- /dev/null
+++ b/util/src/test/java/com/liuhuiyu/util/thread/ThreadUtilTest.java
@@ -0,0 +1,132 @@
+package com.liuhuiyu.util.thread;
+
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+
+/**
+ * @author LiuHuiYu
+ * @version v1.0.0.0
+ * Created DateTime 2021-07-17 10:36
+ */
+@Log4j2
+public class ThreadUtilTest {
+ @Test
+ public void asynchronousDataLoading() {
+ List list = new ArrayList<>(5);
+ Collections.addAll(list, 5, 1, 6, 4, 3, 2, 7, 5, 6);
+ ThreadUtil.asynchronousDataLoading(list, this::testExe);
+ }
+
+ @Test
+ public void asynchronousDataLoading2() {
+ List