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 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 list = new ArrayList<>(5); + Collections.addAll(list, 5, 1, 6, 4, 3, 2, 7, 5, 6); + for (int i = 0; i < 100; i++) { + ThreadPoolTaskExecutor threadPoolTaskExecutor = ExecutorBuilder.create().corePoolSize(list.size()).threadName("test-" + i + "-").builder(); + ThreadUtil.asynchronousDataLoading(list, this::testExe, threadPoolTaskExecutor); + } + } + + private void testExe(Integer i) { + try { + log.info("开始:{}", i); + Thread.sleep(i * 1000); + log.info("完成:{}", i); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Test + public void s() { + List list = new ArrayList() {{ + this.add("1"); + this.add("2"); + this.add("3"); + this.add("3"); + this.add("32"); + }}; + String[] array = list.toArray(new String[0]); + log.info("{},{}", list, list.size()); + log.info(":{};{};", array, array.length); + } + + private List getIntegerList() { + return new ArrayList() {{ + this.add(1); + this.add(2); + this.add(3); + this.add(4); + this.add(5); + }}; + } + + @Test + @SuppressWarnings({"rawtypes", "unused"}) + public void testCompletableFuture() throws ExecutionException, InterruptedException { + List integerList = getIntegerList(); +// AtomicReference> future = new AtomicReference<>(); + integerList.forEach(i -> { + CompletableFuture future01 = CompletableFuture.supplyAsync(() -> { + sleep(i); + return i; + }); +// future.set(future01); + }); + CompletableFuture.supplyAsync(() -> integerList.stream().map((item) -> CompletableFuture.runAsync(() -> sleep(item))).collect(Collectors.toList())); + CompletableFuture[] s2 = integerList.stream().map((item) -> CompletableFuture.runAsync(() -> sleep(item))).toArray(CompletableFuture[]::new); + CompletableFuture.anyOf(s2).thenAccept((a) -> { + }).get(); + } + + private void sleep(Integer i) { +// log.info("进入{}",i); + log.info("任务{}线程:", Thread.currentThread().getId()); + + if (i < 3) + throw new RuntimeException(); + try { + Thread.sleep(i * 1000); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + log.info("离开{}", Thread.currentThread().getId()); + } + + @Test + public void testSleep() { + Runnable runnable = () -> { + long millis = 10_000; + log.info("开始执行:{}毫秒延时。", millis); + if (ThreadUtil.sleep(millis)) { + log.info("正常结束。"); + } + else { + log.info("线程内异常,中断休眠"); + } + }; + Thread thread = new Thread(runnable); + thread.start(); + log.info("3秒后引发中断。"); + if (ThreadUtil.sleep(3_000)) { + log.info("引发中断。"); + thread.interrupt(); + log.info("引发中断完成。"); + } + long millis = 100_000; + log.info("程序完成。"); + if (!ThreadUtil.sleep(millis)) { + log.info("异常中断休眠"); + } + } +} \ No newline at end of file diff --git a/util/src/test/java/com/liuhuiyu/util/web/WebUtilTest.java b/util/src/test/java/com/liuhuiyu/util/web/WebUtilTest.java new file mode 100644 index 0000000..7e7b93d --- /dev/null +++ b/util/src/test/java/com/liuhuiyu/util/web/WebUtilTest.java @@ -0,0 +1,23 @@ +package com.liuhuiyu.util.web; + +import junit.framework.TestCase; +import lombok.extern.log4j.Log4j2; + +/** + * @author LiuHuiYu + * @version v1.0.0.0 + * Created DateTime 2021-03-09 11:42 + */ +@Log4j2 +public class WebUtilTest extends TestCase { + public void testBtoA() { + String b = "abcd"; + String a = JsUtil.btoa(b); + log.info("bToA a={};b={}", a, b); + } + public void testAtoB() { + String a = "YWJjZA=="; + String b = JsUtil.atob(a); + log.info("aToB a={};b={}", a, b); + } +} \ No newline at end of file diff --git a/web/pom.xml b/web/pom.xml new file mode 100644 index 0000000..b45e783 --- /dev/null +++ b/web/pom.xml @@ -0,0 +1,98 @@ + + + + 4.0.0 + + com.liuhuiyu + web + 1.0-SNAPSHOT + + web + http://com.liuhuiyu.com + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.11 + test + + + org.springframework.boot + spring-boot-starter-aop + 2.1.6.RELEASE + + + org.springframework.boot + spring-boot-starter-web + 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/ + + + + + + + + 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/web/src/main/java/com/liuhuiyu/web/IpUtil.java b/web/src/main/java/com/liuhuiyu/web/IpUtil.java new file mode 100644 index 0000000..f0af9c4 --- /dev/null +++ b/web/src/main/java/com/liuhuiyu/web/IpUtil.java @@ -0,0 +1,34 @@ +package com.liuhuiyu.web; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author LiuHuiYu + * @version v1.0.0.0 + * Created DateTime 2021-02-23 21:05 + */ +public class IpUtil { + public static final String UNKNOWN="unknown"; + public static String getIpAddress(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (isNullIp(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (isNullIp(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (isNullIp(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (isNullIp(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (isNullIp(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } + public static boolean isNullIp(String ip){ + return ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip); + } +} \ No newline at end of file diff --git a/web/src/main/java/com/liuhuiyu/web/RequestParametersUtil.java b/web/src/main/java/com/liuhuiyu/web/RequestParametersUtil.java new file mode 100644 index 0000000..ab82128 --- /dev/null +++ b/web/src/main/java/com/liuhuiyu/web/RequestParametersUtil.java @@ -0,0 +1,78 @@ +package com.liuhuiyu.web; + +import javax.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; + +/** + * @author LiuHuiYu + * @version v1.0.0.0 + * Created DateTime 2021-07-20 13:53 + */ +public class RequestParametersUtil { + public static final String GET = "GET"; + public static final String POST = "POST"; + + /** + * 获取request中参数 + * + * @param request 页面请求 + */ + public static Map getRequestParameters(HttpServletRequest request) { + //请求参数 + String parameters = ""; + //GET请求时的参数 + if (GET.equals(request.getMethod())) { + //网址中的参数 + String urlParameter = request.getQueryString(); + if (urlParameter != null && !"".equals(urlParameter)) { + try { + urlParameter = URLDecoder.decode(urlParameter, "UTF-8"); + } + catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + else { + urlParameter = ""; + } + parameters = urlParameter; + } + //POST请求时的参数 + else if (POST.equals(request.getMethod())) { + //表单及网址中全部参数 + StringBuilder totalParameter = new StringBuilder(); + Map params = request.getParameterMap(); + //参数个数 + int parametersNum = request.getParameterMap().size(); + int flag = 1; + for (String key : params.keySet()) { + + String[] values = params.get(key); + for (String value : values) { + totalParameter.append(key).append("=").append(value); + } + if (flag < parametersNum) { + totalParameter.append("&"); + } + flag += 1; + } + parameters = totalParameter.toString(); + } + Map map = new HashMap<>(0); + String[] arr = parameters.split("&"); + for (String s : arr) { + int index = s.indexOf("="); + //=不能是首位或者是末尾 + if (index < 1 || index >= (s.length() - 1)) { + break; + } + String key = s.substring(0, index); + String value = s.substring(index + 1); + map.put(key, value); + } + return map; + } +} diff --git a/web/src/main/java/com/liuhuiyu/web/aspect/BaseAspect.java b/web/src/main/java/com/liuhuiyu/web/aspect/BaseAspect.java new file mode 100644 index 0000000..ca115be --- /dev/null +++ b/web/src/main/java/com/liuhuiyu/web/aspect/BaseAspect.java @@ -0,0 +1,51 @@ +package com.liuhuiyu.web.aspect; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; + +/** + * 基础拦截器 + * @author LiuHuiYu + * @version v1.0.0.0 + * Created DateTime 2018-06-28 16:49 + */ +public abstract class BaseAspect { + + + protected Boolean isResponseBody (ProceedingJoinPoint pjp){ + MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); + Method method = methodSignature.getMethod(); + return method.getAnnotation(ResponseBody.class)!=null; + } + + /** + * 获取 HttpServletRequest + * @return HttpServletRequest + */ + protected HttpServletRequest getHttpServletRequest() { + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (attributes == null) { + throw new RuntimeException("ServletRequestAttributes 空指针异常。"); + } + return attributes.getRequest(); + } + + /** + * 获取 HttpServletResponse + * @return HttpServletResponse + */ + protected HttpServletResponse getHttpServletResponse() { + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (attributes == null) { + throw new RuntimeException("ServletRequestAttributes 空指针异常。"); + } + return attributes.getResponse(); + } +} \ No newline at end of file diff --git a/web/src/main/java/com/liuhuiyu/web/controller/AbsBaseController.java b/web/src/main/java/com/liuhuiyu/web/controller/AbsBaseController.java new file mode 100644 index 0000000..d6e8556 --- /dev/null +++ b/web/src/main/java/com/liuhuiyu/web/controller/AbsBaseController.java @@ -0,0 +1,35 @@ +package com.liuhuiyu.web.controller; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author LiuHuiYu + * @version v1.0.0.0 + * Created DateTime 2020-12-29 8:48 + */ +public abstract class AbsBaseController { + /** + * 首页 + */ + protected static final String PATH_INDEX = "/index"; + /** + * 当前目录默认地址 + */ + protected static final String PATH_DEFAULT = "/"; + /** + * 页号属性 + */ + public static final String ATTRIBUTE_PAGE_INDEX = "page_index"; + /** + * 页面大小 + */ + public static final String ATTRIBUTE_PAGE_SIZE = "page_size"; + /** + * id + */ + public static final String ATTRIBUTE_ID = "id"; + /** + * 默认页面大小 + */ + protected static final int DEF_PAGE_SIZE = 20; +} diff --git a/web/src/main/java/com/liuhuiyu/web/package-info.java b/web/src/main/java/com/liuhuiyu/web/package-info.java new file mode 100644 index 0000000..ac428ae --- /dev/null +++ b/web/src/main/java/com/liuhuiyu/web/package-info.java @@ -0,0 +1,6 @@ +/** + * @author LiuHuiYu + * @version v1.0.0.0 + * Created DateTime 2021-01-12 11:13 + */ +package com.liuhuiyu.web; \ No newline at end of file