├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src └── main └── java └── com └── xjbg └── java └── sdk ├── cache ├── CacheTemplate.java └── LocalCacheHelper.java ├── customize └── jackson │ └── CustomObjectMapper.java ├── encrypt ├── AESOperator.java ├── Authenticator.java ├── MD5.java ├── RsaOperator.java └── SHA.java ├── enums ├── DatePatternEnum.java ├── Encoding.java ├── EnvEnum.java └── FlagEnum.java ├── http ├── client │ └── HttpClientWrapper.java ├── config │ └── HttpConnectionConfig.java ├── request │ └── BaseHttpRequest.java └── util │ └── HttpClientUtil.java ├── lock ├── StripedLock.java └── impl │ ├── DefaultRedisDistributedLock.java │ └── DefaultReentrantStripedLock.java ├── monitor └── VMInfo.java ├── tree ├── BinaryTree.java ├── DefaultTree.java ├── Tree.java └── TreeUtils.java └── util ├── Base64Util.java ├── BeanUtil.java ├── CollectionUtil.java ├── DateUtil.java ├── ExceptionUtil.java ├── FileUtil.java ├── HexUtil.java ├── JsonUtil.java ├── Levenshtein.java ├── NumberUtil.java ├── PinYinUtil.java ├── RandomUtil.java ├── ReflectionUtil.java ├── RetryUtil.java ├── SnowFlake.java ├── StringUtil.java ├── ThreadPoolUtils.java └── XmlUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | *.iml 3 | .idea/ 4 | /target -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SDK -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xjbg.java 8 | sdk 9 | 1.0-SNAPSHOT 10 | 11 | java-sdk 12 | java sdk 13 | https://github.com/Kestrong/java-sdk 14 | 2019 15 | 16 | 17 | 18 | Apache 2 19 | http://www.apache.org/licenses/LICENSE-2.0.txt 20 | repo 21 | A business-friendly OSS license 22 | 23 | 24 | 25 | 26 | 27 | kesc 28 | Lancelot 29 | kestrong@foxmail.com 30 | 31 | 32 | 33 | 34 | UTF-8 35 | 1.8 36 | 37 | 38 | 39 | 40 | 41 | org.projectlombok 42 | lombok 43 | 1.18.30 44 | provided 45 | 46 | 47 | 48 | com.google.guava 49 | guava 50 | 31.0.1-jre 51 | 52 | 53 | 54 | commons-fileupload 55 | commons-fileupload 56 | 1.5 57 | 58 | 59 | 60 | commons-io 61 | commons-io 62 | 2.7 63 | 64 | 65 | commons-collections 66 | commons-collections 67 | 3.2.2 68 | 69 | 70 | org.apache.commons 71 | commons-lang3 72 | 3.13.0 73 | 74 | 75 | com.fasterxml.jackson.dataformat 76 | jackson-dataformat-xml 77 | 2.14.2 78 | 79 | 80 | org.apache.httpcomponents 81 | httpclient 82 | 4.5.13 83 | 84 | 85 | javax.servlet 86 | javax.servlet-api 87 | 3.1.0 88 | provided 89 | 90 | 91 | joda-time 92 | joda-time 93 | 2.12.5 94 | 95 | 96 | 97 | junit 98 | junit 99 | 4.13.1 100 | test 101 | 102 | 103 | 104 | ch.qos.logback 105 | logback-classic 106 | 1.2.9 107 | 108 | 109 | org.springframework.boot 110 | spring-boot-starter-data-redis 111 | 112 | 113 | org.springframework.boot 114 | spring-boot-starter-logging 115 | 116 | 117 | 2.7.12 118 | 119 | 120 | 121 | com.esotericsoftware 122 | reflectasm 123 | 1.11.8 124 | 125 | 126 | com.belerweb 127 | pinyin4j 128 | 2.5.1 129 | 130 | 131 | 132 | cn.afterturn 133 | easypoi-base 134 | 4.4.0 135 | 136 | 137 | 138 | 139 | 140 | 141 | ossrh 142 | https://oss.sonatype.org/content/repositories/snapshots 143 | 144 | 145 | ossrh 146 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 147 | 148 | 149 | 150 | 151 | 152 | 153 | src/main/resources 154 | true 155 | 156 | 157 | src/test/resources 158 | true 159 | 160 | 161 | 162 | 163 | org.apache.maven.plugins 164 | maven-dependency-plugin 165 | 2.2 166 | 167 | 168 | org.apache.maven.plugins 169 | maven-compiler-plugin 170 | 171 | ${jdk.version} 172 | ${jdk.version} 173 | ${project.build.sourceEncoding} 174 | 175 | 176 | 177 | org.apache.maven.plugins 178 | maven-surefire-plugin 179 | 2.18.1 180 | 181 | true 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/cache/LocalCacheHelper.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.cache; 2 | 3 | import com.google.common.cache.Cache; 4 | import com.google.common.cache.CacheBuilder; 5 | import com.google.common.cache.CacheLoader; 6 | import com.google.common.cache.LoadingCache; 7 | import lombok.SneakyThrows; 8 | import org.apache.commons.collections4.map.LRUMap; 9 | 10 | import javax.annotation.Nonnull; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.concurrent.Callable; 15 | import java.util.concurrent.TimeUnit; 16 | import java.util.function.Function; 17 | 18 | /** 19 | * memory cache using guava cache, be careful of modifying cache items if necessary 20 | * 21 | * @author kesc 22 | * @date 2021-06-22 15:28 23 | */ 24 | @SuppressWarnings(value = "unused") 25 | public class LocalCacheHelper { 26 | private static final Map> CACHE_MAP = new LRUMap<>(); 27 | public static final String DEFAULT_CACHE_TYPE = "defaultCacheType"; 28 | private static final byte[] LOCK = new byte[0]; 29 | private static final Integer DEFAULT_MAX_SIZE = Integer.valueOf(System.getProperty("local.cache.size", "1000")); 30 | private static final Integer DEFAULT_DURATION = Integer.valueOf(System.getProperty("local.cache.duration", "30")); 31 | private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MINUTES; 32 | 33 | static { 34 | getCache(DEFAULT_CACHE_TYPE); 35 | } 36 | 37 | private static boolean cacheEnable() { 38 | return Boolean.parseBoolean(System.getProperty("local.cache.enable", "true")); 39 | } 40 | 41 | public static LoadingCache buildCache(Integer maxSize, Integer duration, TimeUnit timeUnit, 42 | Function function) { 43 | if (!cacheEnable()) { 44 | maxSize = 0; 45 | duration = 0; 46 | } 47 | return CacheBuilder.newBuilder().maximumSize(maxSize).expireAfterWrite(duration, timeUnit) 48 | .build(new CacheLoader() { 49 | @Override 50 | public V load(@Nonnull K key) { 51 | return function.apply(key); 52 | } 53 | }); 54 | } 55 | 56 | public static LoadingCache buildCache(Function function) { 57 | return buildCache(DEFAULT_MAX_SIZE, DEFAULT_DURATION, DEFAULT_TIME_UNIT, function); 58 | } 59 | 60 | public static Cache buildCache(Integer maxSize, Integer duration, TimeUnit timeUnit) { 61 | if (!cacheEnable()) { 62 | maxSize = 0; 63 | duration = 0; 64 | } 65 | return CacheBuilder.newBuilder().maximumSize(maxSize).expireAfterWrite(duration, timeUnit).build(); 66 | } 67 | 68 | public static Cache buildCache() { 69 | return buildCache(DEFAULT_MAX_SIZE, DEFAULT_DURATION, DEFAULT_TIME_UNIT); 70 | } 71 | 72 | private static Cache getCache(String cacheType) { 73 | if (CACHE_MAP.containsKey(cacheType)) { 74 | return CACHE_MAP.get(cacheType); 75 | } 76 | synchronized (LOCK) { 77 | if (CACHE_MAP.containsKey(cacheType)) { 78 | return CACHE_MAP.get(cacheType); 79 | } 80 | return CACHE_MAP.compute(cacheType, (s, k) -> buildCache()); 81 | } 82 | } 83 | 84 | @SneakyThrows 85 | @SuppressWarnings(value = "unchecked") 86 | public static V get(String cacheType, String key, Callable loader) { 87 | if (!cacheEnable()) { 88 | if (loader == null) { 89 | return null; 90 | } 91 | return loader.call(); 92 | } 93 | Cache cache = getCache(cacheType); 94 | try { 95 | if (loader == null) { 96 | return (V) cache.getIfPresent(key); 97 | } 98 | return (V) cache.get(key, loader); 99 | } catch (Exception e) { 100 | return null; 101 | } 102 | } 103 | 104 | public static V get(String key, Callable loader) { 105 | return get(DEFAULT_CACHE_TYPE, key, loader); 106 | } 107 | 108 | public static V get(String cacheType, String key) { 109 | return get(cacheType, key, null); 110 | } 111 | 112 | public static V get(String key) { 113 | return get(DEFAULT_CACHE_TYPE, key); 114 | } 115 | 116 | public static Map get(String cacheType, List keys, Callable loader) { 117 | Map result = new HashMap<>(keys.size()); 118 | for (String key : keys) { 119 | V o = get(cacheType, key, loader); 120 | result.put(key, o); 121 | } 122 | return result; 123 | } 124 | 125 | public static Map get(List keys, Callable loader) { 126 | return get(DEFAULT_CACHE_TYPE, keys, loader); 127 | } 128 | 129 | public static Map get(String cacheType, List keys) { 130 | return get(cacheType, keys, null); 131 | } 132 | 133 | public static Map get(List keys) { 134 | return get(DEFAULT_CACHE_TYPE, keys); 135 | } 136 | 137 | public static void set(String cacheType, String key, Object value) { 138 | getCache(cacheType).put(key, value); 139 | } 140 | 141 | public static void set(String key, Object value) { 142 | set(DEFAULT_CACHE_TYPE, key, value); 143 | } 144 | 145 | public static void set(String cacheType, Map items) { 146 | getCache(cacheType).putAll(items); 147 | } 148 | 149 | public static void set(Map items) { 150 | set(DEFAULT_CACHE_TYPE, items); 151 | } 152 | 153 | public static void remove(String cacheType, String key) { 154 | Cache loadingCache = CACHE_MAP.get(cacheType); 155 | if (loadingCache != null) { 156 | loadingCache.invalidate(key); 157 | } 158 | } 159 | 160 | public static void remove(String key) { 161 | remove(DEFAULT_CACHE_TYPE, key); 162 | } 163 | 164 | public static void removeType(String cacheType) { 165 | Cache loadingCache = CACHE_MAP.get(cacheType); 166 | if (loadingCache != null) { 167 | loadingCache.invalidateAll(); 168 | } 169 | } 170 | 171 | public static void removeType() { 172 | removeType(DEFAULT_CACHE_TYPE); 173 | } 174 | 175 | public static void clear() { 176 | for (Map.Entry> entry : CACHE_MAP.entrySet()) { 177 | entry.getValue().invalidateAll(); 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/customize/jackson/CustomObjectMapper.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.customize.jackson; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.databind.DeserializationContext; 5 | import com.fasterxml.jackson.databind.DeserializationFeature; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.SerializationFeature; 8 | import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; 9 | import com.fasterxml.jackson.databind.module.SimpleModule; 10 | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; 11 | import com.xjbg.java.sdk.enums.DatePatternEnum; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.apache.commons.lang3.StringUtils; 14 | 15 | import java.io.IOException; 16 | import java.math.BigDecimal; 17 | import java.text.SimpleDateFormat; 18 | 19 | /** 20 | * @author kesc 21 | * @since 2019/5/15 22 | */ 23 | @Slf4j 24 | public class CustomObjectMapper extends ObjectMapper { 25 | 26 | public CustomObjectMapper() { 27 | init(); 28 | } 29 | 30 | private void init() { 31 | try { 32 | configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false); 33 | configure(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL, true); 34 | } catch (Error var6) { 35 | log.error("SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL not support your version, please upgrade jackson >=2.11"); 36 | } 37 | 38 | configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 39 | configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 40 | setDateFormat(new SimpleDateFormat(DatePatternEnum.YYYYMMDDHHMMSS_BYSEP.getFormat())); 41 | SimpleModule module = new SimpleModule(); 42 | module.addSerializer(BigDecimal.class, ToStringSerializer.instance); 43 | module.addDeserializer(String.class, new StdScalarDeserializer(String.class) { 44 | @Override 45 | public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { 46 | return StringUtils.trim(jp.getValueAsString()); 47 | } 48 | }); 49 | registerModules(module); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/encrypt/AESOperator.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.encrypt; 2 | 3 | import com.xjbg.java.sdk.util.RandomUtil; 4 | import com.xjbg.java.sdk.util.StringUtil; 5 | import lombok.SneakyThrows; 6 | 7 | import javax.crypto.BadPaddingException; 8 | import javax.crypto.Cipher; 9 | import javax.crypto.IllegalBlockSizeException; 10 | import javax.crypto.NoSuchPaddingException; 11 | import javax.crypto.spec.IvParameterSpec; 12 | import javax.crypto.spec.SecretKeySpec; 13 | import java.io.BufferedInputStream; 14 | import java.io.IOException; 15 | import java.io.InputStream; 16 | import java.nio.charset.StandardCharsets; 17 | import java.security.InvalidAlgorithmParameterException; 18 | import java.security.InvalidKeyException; 19 | import java.security.NoSuchAlgorithmException; 20 | import java.util.Arrays; 21 | import java.util.Base64; 22 | 23 | /** 24 | * @author kesc 25 | * @date 2016年12月9日 上午9:00:36 26 | */ 27 | @SuppressWarnings({"unused"}) 28 | public class AESOperator { 29 | private final static String ALGORITHM = "AES"; 30 | private final static int KEY_LENGTH = 16; 31 | /** 32 | * transformation - the name of the transformation, e.g., 33 | * AES/CBC/PKCS5Padding. 34 | */ 35 | private final static String TRANSFORMATION = "AES/CBC/PKCS5Padding"; 36 | /** 37 | * 加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式,key需要为16位。 38 | */ 39 | private byte[] key; 40 | private byte[] ivParameter; 41 | 42 | public AESOperator() { 43 | this(RandomUtil.randomAlphanumeric(KEY_LENGTH), RandomUtil.randomAlphanumeric(KEY_LENGTH)); 44 | } 45 | 46 | public AESOperator(String iv) { 47 | this(StringUtil.getBytes(iv)); 48 | } 49 | 50 | public AESOperator(String key, String iv) { 51 | this(StringUtil.getBytes(key), StringUtil.getBytes(iv)); 52 | } 53 | 54 | public AESOperator(byte[] iv) { 55 | checkIv(iv); 56 | this.ivParameter = iv; 57 | } 58 | 59 | public AESOperator(byte[] key, byte[] iv) { 60 | this(iv); 61 | checkKey(key); 62 | this.key = key; 63 | } 64 | 65 | private void checkIv(byte[] iv) { 66 | if (iv == null || iv.length != KEY_LENGTH) { 67 | throw new IllegalArgumentException(String.format("iv length must be %d.", KEY_LENGTH)); 68 | } 69 | } 70 | 71 | private void checkKey(byte[] key) { 72 | if (key == null || key.length != KEY_LENGTH) { 73 | throw new IllegalArgumentException(String.format("key length must be %d.", KEY_LENGTH)); 74 | } 75 | } 76 | 77 | private void checkSrc(byte[] src) { 78 | if (src == null) { 79 | throw new IllegalArgumentException("source to be encrypted or decrypted can not be null."); 80 | } 81 | } 82 | 83 | public String encrypt(final String src) { 84 | return encrypt(StringUtil.getUTF8Bytes(src), key, ivParameter); 85 | } 86 | 87 | public String encrypt(final String src, final String key) { 88 | return encrypt(StringUtil.getUTF8Bytes(src), StringUtil.getBytes(key), ivParameter); 89 | } 90 | 91 | public String encrypt(final String src, final String key, final String iv) { 92 | return encrypt(StringUtil.getUTF8Bytes(src), 93 | StringUtil.getBytes(key), 94 | StringUtil.getBytes(iv)); 95 | } 96 | 97 | public String encrypt(final byte[] src) { 98 | return encrypt(src, key, ivParameter); 99 | } 100 | 101 | public String encrypt(final byte[] src, final byte[] key) { 102 | return encrypt(src, key, ivParameter); 103 | } 104 | 105 | public String encrypt(final byte[] src, final byte[] key, final byte[] iv) { 106 | byte[] encrypted = encryptRaw(src, key, iv); 107 | return new String(Base64.getEncoder().encode(encrypted), StandardCharsets.UTF_8); 108 | } 109 | 110 | public String encrypt(final InputStream src) throws IOException { 111 | return encrypt(src, key, ivParameter); 112 | } 113 | 114 | public String encrypt(final InputStream src, final String key, final String iv) throws IOException { 115 | return encrypt(src, StringUtil.getBytes(key), StringUtil.getBytes(iv)); 116 | } 117 | 118 | public String encrypt(final InputStream src, final byte[] key, final byte[] iv) throws IOException { 119 | byte[] encrypted = encryptRaw(src, key, iv); 120 | return new String(Base64.getEncoder().encode(encrypted), StandardCharsets.UTF_8); 121 | } 122 | 123 | public byte[] encryptRaw(final byte[] src) { 124 | return encryptRaw(src, key, ivParameter); 125 | } 126 | 127 | public byte[] encryptRaw(final String src) { 128 | return encryptRaw(StringUtil.getUTF8Bytes(src), key, ivParameter); 129 | } 130 | 131 | public byte[] encryptRaw(final String src, final String key, final String iv) { 132 | return encryptRaw(StringUtil.getUTF8Bytes(src), 133 | StringUtil.getBytes(key), 134 | StringUtil.getBytes(iv)); 135 | } 136 | 137 | @SneakyThrows 138 | public byte[] encryptRaw(final byte[] src, final byte[] key, final byte[] iv) { 139 | checkSrc(src); 140 | Cipher cipher = getCipher(key, iv, Cipher.ENCRYPT_MODE); 141 | return cipher.doFinal(src); 142 | } 143 | 144 | public byte[] encryptRaw(final InputStream src) throws IOException { 145 | return encryptRaw(src, key, ivParameter); 146 | } 147 | 148 | public byte[] encryptRaw(final InputStream src, final String key, final String iv) throws IOException { 149 | return encryptRaw(src, StringUtil.getBytes(key), StringUtil.getBytes(iv)); 150 | } 151 | 152 | public byte[] encryptRaw(final InputStream src, final byte[] key, final byte[] iv) throws IOException { 153 | try (InputStream input = new BufferedInputStream(src)) { 154 | Cipher cipher = getCipher(key, iv, Cipher.ENCRYPT_MODE); 155 | final byte[] buffer = new byte[1024]; 156 | int read; 157 | while ((read = input.read(buffer)) != -1) { 158 | cipher.update(buffer, 0, read); 159 | } 160 | return cipher.doFinal(); 161 | } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { 162 | throw new RuntimeException(e); 163 | } 164 | } 165 | 166 | public String decrypt(final String src) { 167 | return decrypt(StringUtil.getUTF8Bytes(src), key, ivParameter); 168 | } 169 | 170 | public String decrypt(final String src, final String key) { 171 | return decrypt(StringUtil.getUTF8Bytes(src), StringUtil.getBytes(key), ivParameter); 172 | } 173 | 174 | public String decrypt(final String src, final String key, final String iv) { 175 | return decrypt(StringUtil.getUTF8Bytes(src), 176 | StringUtil.getBytes(key), 177 | StringUtil.getBytes(iv)); 178 | } 179 | 180 | public String decrypt(final byte[] src) { 181 | return decrypt(src, key, ivParameter); 182 | } 183 | 184 | public String decrypt(final byte[] src, final byte[] key) { 185 | return decrypt(src, key, ivParameter); 186 | } 187 | 188 | @SneakyThrows 189 | public String decrypt(final byte[] src, final byte[] key, final byte[] iv) { 190 | return new String(decryptAsBytes(src, key, iv), StandardCharsets.UTF_8); 191 | } 192 | 193 | public byte[] decryptAsBytes(final byte[] src, final byte[] key, final byte[] iv) { 194 | checkSrc(src); 195 | // 先用base64解密 196 | byte[] decrypted = Base64.getDecoder().decode(src); 197 | return decryptRaw(decrypted, key, iv); 198 | } 199 | 200 | public byte[] decryptAsBytes(final String src) { 201 | return decryptAsBytes(StringUtil.getUTF8Bytes(src), key, ivParameter); 202 | } 203 | 204 | public byte[] decryptAsBytes(final byte[] src) { 205 | return decryptAsBytes(src, key, ivParameter); 206 | } 207 | 208 | public byte[] decryptAsBytes(final String src, final String key, final String iv) { 209 | return decryptAsBytes(StringUtil.getUTF8Bytes(src), StringUtil.getBytes(key), StringUtil.getBytes(iv)); 210 | } 211 | 212 | public String decrypt(final InputStream src) throws IOException { 213 | return decrypt(src, key, ivParameter); 214 | } 215 | 216 | public String decrypt(final InputStream src, final String key, final String iv) throws IOException { 217 | return decrypt(src, StringUtil.getBytes(key), StringUtil.getBytes(iv)); 218 | } 219 | 220 | public String decrypt(final InputStream src, final byte[] key, final byte[] iv) throws IOException { 221 | return new String(decryptAsBytes(src, key, iv), StandardCharsets.UTF_8); 222 | } 223 | 224 | public byte[] decryptAsBytes(final InputStream src) throws IOException { 225 | return decryptAsBytes(src, key, ivParameter); 226 | } 227 | 228 | public byte[] decryptAsBytes(final InputStream src, final String key, final String iv) throws IOException { 229 | return decryptAsBytes(src, StringUtil.getBytes(key), StringUtil.getBytes(iv)); 230 | } 231 | 232 | public byte[] decryptAsBytes(final InputStream src, final byte[] key, final byte[] iv) throws IOException { 233 | try (InputStream input = new BufferedInputStream(src)) { 234 | Cipher cipher = getCipher(key, iv, Cipher.DECRYPT_MODE); 235 | final byte[] buffer = new byte[3 * 1024]; 236 | int read; 237 | Base64.Decoder decoder = Base64.getDecoder(); 238 | //需要先进行base64解码 239 | while ((read = input.read(buffer)) != -1) { 240 | if (read != buffer.length) { 241 | byte[] copy = Arrays.copyOf(buffer, read); 242 | cipher.update(decoder.decode(copy)); 243 | } else { 244 | cipher.update(decoder.decode(buffer)); 245 | } 246 | } 247 | return cipher.doFinal(); 248 | } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { 249 | throw new RuntimeException(e); 250 | } 251 | } 252 | 253 | public byte[] decryptRaw(final byte[] src) { 254 | return decryptRaw(src, key, ivParameter); 255 | } 256 | 257 | public String decryptRawAsString(final byte[] src) { 258 | return decryptRawAsString(src, key, ivParameter); 259 | } 260 | 261 | public byte[] decryptRaw(final String src) { 262 | return decryptRaw(StringUtil.getUTF8Bytes(src), key, ivParameter); 263 | } 264 | 265 | public String decryptRawAsString(final String src) { 266 | return decryptRawAsString(StringUtil.getUTF8Bytes(src)); 267 | } 268 | 269 | public byte[] decryptRaw(final String src, final String key, final String iv) { 270 | return decryptRaw(StringUtil.getUTF8Bytes(src), 271 | StringUtil.getBytes(key), 272 | StringUtil.getBytes(iv)); 273 | } 274 | 275 | public String decryptRawAsString(final String src, final String key, final String iv) { 276 | return decryptRawAsString(StringUtil.getUTF8Bytes(src), StringUtil.getBytes(key), StringUtil.getBytes(iv)); 277 | } 278 | 279 | @SneakyThrows 280 | public byte[] decryptRaw(final byte[] src, final byte[] key, final byte[] iv) { 281 | checkSrc(src); 282 | Cipher cipher = getCipher(key, iv, Cipher.DECRYPT_MODE); 283 | //不进行base64解码 284 | return cipher.doFinal(src); 285 | } 286 | 287 | public String decryptRawAsString(final byte[] src, final byte[] key, final byte[] iv) { 288 | return new String(decryptRaw(src, key, iv), StandardCharsets.UTF_8); 289 | } 290 | 291 | public byte[] decryptRaw(final InputStream src) throws IOException { 292 | return decryptRaw(src, key, ivParameter); 293 | } 294 | 295 | public String decryptRawAsString(final InputStream src) throws IOException { 296 | return decryptRawAsString(src, key, ivParameter); 297 | } 298 | 299 | public byte[] decryptRaw(final InputStream src, final String key, final String iv) throws IOException { 300 | return decryptRaw(src, StringUtil.getBytes(key), StringUtil.getBytes(iv)); 301 | } 302 | 303 | public String decryptRawAsString(final InputStream src, final String key, final String iv) throws IOException { 304 | return decryptRawAsString(src, StringUtil.getBytes(key), StringUtil.getBytes(iv)); 305 | } 306 | 307 | public byte[] decryptRaw(final InputStream src, final byte[] key, final byte[] iv) throws IOException { 308 | try (InputStream input = new BufferedInputStream(src)) { 309 | Cipher cipher = getCipher(key, iv, Cipher.DECRYPT_MODE); 310 | final byte[] buffer = new byte[1024]; 311 | int read; 312 | while ((read = input.read(buffer)) != -1) { 313 | cipher.update(buffer, 0, read); 314 | } 315 | return cipher.doFinal(); 316 | } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { 317 | throw new RuntimeException(e); 318 | } 319 | } 320 | 321 | public String decryptRawAsString(final InputStream src, final byte[] key, final byte[] iv) throws IOException { 322 | return new String(decryptRaw(src, key, iv), StandardCharsets.UTF_8); 323 | } 324 | 325 | private Cipher getCipher(final byte[] key, final byte[] iv, final int mode) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException { 326 | checkKey(key); 327 | checkIv(iv); 328 | Cipher cipher = Cipher.getInstance(TRANSFORMATION); 329 | SecretKeySpec skeySpec = new SecretKeySpec(key, ALGORITHM); 330 | // 使用CBC模式,需要一个向量iv,可增加加密算法的强度 331 | IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); 332 | cipher.init(mode, skeySpec, ivParameterSpec); 333 | return cipher; 334 | } 335 | 336 | public static void main(String[] args) { 337 | String key = "1234567890abcdef"; 338 | String iv = "fedcba0987654321"; 339 | AESOperator aesOperator = new AESOperator(key, iv); 340 | String cSrc = "test"; 341 | System.out.println(cSrc + "长度为" + cSrc.length()); 342 | long lStart = System.currentTimeMillis(); 343 | String enString = aesOperator.encrypt(cSrc); 344 | System.out.println("加密后的字串是:" + enString + "长度为" + enString.length()); 345 | long lUseTime = System.currentTimeMillis() - lStart; 346 | System.out.println("加密耗时:" + lUseTime + "毫秒"); 347 | lStart = System.currentTimeMillis(); 348 | String deString = aesOperator.decrypt(enString); 349 | System.out.println("还原后的字串是:" + deString); 350 | try { 351 | String deString2 = aesOperator.decrypt(cSrc); 352 | System.out.println("解密后的字串是:" + deString2); 353 | } catch (Exception e) { 354 | //ignore 355 | } 356 | lUseTime = System.currentTimeMillis() - lStart; 357 | System.out.println("解密耗时:" + lUseTime + "毫秒"); 358 | } 359 | 360 | } -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/encrypt/Authenticator.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.encrypt; 2 | 3 | import com.xjbg.java.sdk.util.RandomUtil; 4 | 5 | import javax.crypto.SecretKeyFactory; 6 | import javax.crypto.spec.PBEKeySpec; 7 | import java.io.UnsupportedEncodingException; 8 | import java.nio.charset.StandardCharsets; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.security.spec.InvalidKeySpecException; 11 | import java.util.Base64; 12 | import java.util.Base64.Decoder; 13 | 14 | /** 15 | * @author kesc 16 | * @ClassName Authenticator 17 | * @Description 18 | * @date 2017年7月18日 下午2:26:56 19 | */ 20 | public class Authenticator { 21 | public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA512"; 22 | public static final int SALT_BYTES = 24; 23 | public static final int HASH_BYTES = 24; 24 | public static final int PBKDF2_ITERATIONS = 1000; 25 | 26 | public boolean validate(String givenPassword, String hash, String salt) { 27 | Decoder decoder = Base64.getDecoder(); 28 | byte[] hashByte = decoder.decode(hash); 29 | byte[] saltByte = decoder.decode(salt); 30 | return validate(givenPassword, hashByte, saltByte); 31 | } 32 | 33 | public boolean validate(String givenPassword, byte[] hash, byte[] salt) { 34 | try { 35 | byte[] testHash = pbkdf2(givenPassword.toCharArray(), salt, PBKDF2_ITERATIONS, hash.length); 36 | return slowEquals(hash, testHash); 37 | } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 38 | return false; 39 | } 40 | } 41 | 42 | public boolean validate(char[] givenPassword, String hash, String salt) { 43 | Decoder decoder = Base64.getDecoder(); 44 | try { 45 | byte[] hashByte = decoder.decode(hash); 46 | byte[] saltByte = decoder.decode(salt); 47 | byte[] testHash = pbkdf2(givenPassword, saltByte, PBKDF2_ITERATIONS, hashByte.length); 48 | return slowEquals(hashByte, testHash); 49 | } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 50 | return false; 51 | } 52 | } 53 | 54 | /** 55 | * Compares two byte arrays in length-constant time. This comparison method 56 | * is used so that password hashes cannot be extracted from an on-line 57 | * system using a timing attack and then attacked off-line. 58 | * 59 | * @param a the first byte array 60 | * @param b the second byte array 61 | * @return true if both byte arrays are the same, false if not 62 | */ 63 | private boolean slowEquals(byte[] a, byte[] b) { 64 | int diff = a.length ^ b.length; 65 | for (int i = 0; i < a.length && i < b.length; i++) { 66 | diff |= a[i] ^ b[i]; 67 | } 68 | return diff == 0; 69 | } 70 | 71 | /** 72 | * Computes the PBKDF2 hash of a password. 73 | * 74 | * @param password the password to hash. 75 | * @param salt the salt 76 | * @param iterations the iteration count (slowness factor) 77 | * @param bytes the length of the hash to compute in bytes 78 | * @return the PBDKF2 hash of the password 79 | */ 80 | private byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) throws NoSuchAlgorithmException, InvalidKeySpecException { 81 | PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8); 82 | SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM); 83 | return skf.generateSecret(spec).getEncoded(); 84 | } 85 | 86 | public byte[] createHash(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { 87 | return pbkdf2(password.toCharArray(), salt, PBKDF2_ITERATIONS, HASH_BYTES); 88 | } 89 | 90 | public String createHashString(String password, byte[] salt) throws InvalidKeySpecException, NoSuchAlgorithmException { 91 | return new String(Base64.getEncoder().encode(createHash(password, salt)), StandardCharsets.UTF_8); 92 | } 93 | 94 | public byte[] createSalt() { 95 | return RandomUtil.nextBytes(32); 96 | } 97 | 98 | public String createSaltSting() { 99 | return new String(Base64.getEncoder().encode(RandomUtil.nextBytes(32)), StandardCharsets.UTF_8); 100 | } 101 | 102 | public static void main(String[] arg) throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException { 103 | Authenticator a = new Authenticator(); 104 | byte[] salt = a.createSalt(); 105 | byte[] hash = a.createHash("123456", salt); 106 | boolean b = a.validate("123456", hash, salt); 107 | System.out.println(b); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/encrypt/MD5.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.encrypt; 2 | 3 | import com.xjbg.java.sdk.util.HexUtil; 4 | import lombok.SneakyThrows; 5 | import org.apache.commons.codec.digest.MessageDigestAlgorithms; 6 | 7 | import java.io.BufferedInputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.nio.charset.Charset; 11 | import java.nio.charset.StandardCharsets; 12 | import java.security.MessageDigest; 13 | 14 | /** 15 | * @author keshicong 16 | * @ClassName MD5 17 | * @Description 18 | * @date 2016年10月1日 下午2:58:49 19 | */ 20 | public class MD5 { 21 | private static volatile MD5 instance = null; 22 | 23 | private MD5() { 24 | super(); 25 | } 26 | 27 | public static MD5 getInstance() { 28 | if (instance == null) { 29 | synchronized (MD5.class) { 30 | if (instance == null) { 31 | instance = new MD5(); 32 | } 33 | } 34 | } 35 | return instance; 36 | } 37 | 38 | @SneakyThrows 39 | private MessageDigest getMessageDigest() { 40 | return MessageDigest.getInstance(MessageDigestAlgorithms.MD5); 41 | } 42 | 43 | public byte[] md5(final byte[] original) { 44 | if (original == null) { 45 | return null; 46 | } 47 | MessageDigest md = getMessageDigest(); 48 | md.update(original); 49 | // MD5 的计算结果是一个 128 位的长整数 用字节表示就是 16 个字节 50 | return md.digest(); 51 | } 52 | 53 | public byte[] md5(final String original, final Charset charset) { 54 | if (original == null) { 55 | return null; 56 | } 57 | return md5(original.getBytes(charset)); 58 | } 59 | 60 | public byte[] md5(final String original) { 61 | if (original == null) { 62 | return null; 63 | } 64 | return md5(original.getBytes(StandardCharsets.UTF_8)); 65 | } 66 | 67 | public String md5hex(final byte[] original) { 68 | return HexUtil.bytes2HexLower(md5(original)); 69 | } 70 | 71 | 72 | public String md5hex(final String original, final Charset charset) { 73 | if (original == null) { 74 | return null; 75 | } 76 | return md5hex(original.getBytes(charset)); 77 | } 78 | 79 | public String md5hex(final String original) { 80 | if (original == null) { 81 | return null; 82 | } 83 | return md5hex(original.getBytes(StandardCharsets.UTF_8)); 84 | } 85 | 86 | public byte[] md5(final InputStream original) throws IOException { 87 | if (original == null) { 88 | return null; 89 | } 90 | final byte[] buffer = new byte[1024]; 91 | MessageDigest digest = getMessageDigest(); 92 | try (InputStream input = new BufferedInputStream(original)) { 93 | int read; 94 | while ((read = input.read(buffer)) != -1) { 95 | digest.update(buffer, 0, read); 96 | } 97 | } 98 | return digest.digest(); 99 | } 100 | 101 | public String md5hex(final InputStream original) throws IOException { 102 | byte[] bytes = md5(original); 103 | if (bytes == null) { 104 | return null; 105 | } 106 | return HexUtil.bytes2HexLower(bytes); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/encrypt/RsaOperator.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.encrypt; 2 | 3 | import com.xjbg.java.sdk.enums.Encoding; 4 | import com.xjbg.java.sdk.util.Base64Util; 5 | 6 | import javax.crypto.BadPaddingException; 7 | import javax.crypto.Cipher; 8 | import javax.crypto.IllegalBlockSizeException; 9 | import javax.crypto.NoSuchPaddingException; 10 | import java.io.*; 11 | import java.security.*; 12 | import java.security.spec.EncodedKeySpec; 13 | import java.security.spec.InvalidKeySpecException; 14 | import java.security.spec.PKCS8EncodedKeySpec; 15 | import java.security.spec.X509EncodedKeySpec; 16 | 17 | /** 18 | * @author kesc 19 | * @since 2019/9/11 20 | */ 21 | public class RsaOperator { 22 | private final static String RSA = "RSA"; 23 | private final static int DEFAULT_MAX_ENCRYPT_SIZE = 117; 24 | private final static int DEFAULT_MAX_DECRYPT_SIZE = 128; 25 | private int maxEncSize; 26 | private int maxDecSize; 27 | 28 | public RsaOperator() { 29 | this.maxDecSize = DEFAULT_MAX_DECRYPT_SIZE; 30 | this.maxEncSize = DEFAULT_MAX_ENCRYPT_SIZE; 31 | } 32 | 33 | public RsaOperator(int maxEncSize, int maxDecSize) { 34 | this.maxEncSize = maxEncSize; 35 | this.maxDecSize = maxDecSize; 36 | } 37 | 38 | public KeyPair genKey() throws NoSuchAlgorithmException { 39 | return genKey(1024); 40 | } 41 | 42 | public KeyPair genKey(int size) throws NoSuchAlgorithmException { 43 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA); 44 | keyPairGenerator.initialize(size); 45 | return keyPairGenerator.generateKeyPair(); 46 | } 47 | 48 | private byte[] multiSlot(InputStream input, Cipher cipher, int maxLength) throws IOException, BadPaddingException, IllegalBlockSizeException { 49 | try (ByteArrayOutputStream out = new ByteArrayOutputStream(); 50 | InputStream in = new BufferedInputStream(input)) { 51 | byte[] buffer = new byte[maxLength]; 52 | int read; 53 | while ((read = in.read(buffer, 0, maxLength)) != -1) { 54 | out.write(cipher.doFinal(buffer, 0, read)); 55 | } 56 | return out.toByteArray(); 57 | } 58 | } 59 | 60 | private Cipher getCipher(byte[] encodedKey, int mode, boolean isPublic) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException { 61 | EncodedKeySpec encodedKeySpec = isPublic ? new X509EncodedKeySpec(encodedKey) : new PKCS8EncodedKeySpec(encodedKey); 62 | KeyFactory keyFactory = KeyFactory.getInstance(RSA); 63 | Key key = isPublic ? keyFactory.generatePublic(encodedKeySpec) : keyFactory.generatePrivate(encodedKeySpec); 64 | Cipher cipher = Cipher.getInstance(RSA); 65 | cipher.init(mode, key); 66 | return cipher; 67 | } 68 | 69 | private void checkKey(byte[] key) { 70 | if (key == null) { 71 | throw new IllegalArgumentException("key can not be null."); 72 | } 73 | } 74 | 75 | private void checkData(Object data) { 76 | if (data == null) { 77 | throw new IllegalArgumentException("data to be encrypted or decrypted can not be null."); 78 | } 79 | } 80 | 81 | /** 82 | * 私钥加密 83 | * 84 | * @param data 85 | * @param key 86 | * @return 87 | * @throws NoSuchAlgorithmException 88 | * @throws InvalidKeySpecException 89 | * @throws NoSuchPaddingException 90 | * @throws InvalidKeyException 91 | * @throws BadPaddingException 92 | * @throws IllegalBlockSizeException 93 | * @throws IOException 94 | */ 95 | public String encryptPrivate(final String data, final String key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 96 | byte[] dataRaw = data == null ? null : data.getBytes(Encoding.UTF_8.getEncoding()); 97 | byte[] keyRaw = key == null ? null : Base64Util.decode(key.getBytes()); 98 | return encryptPrivate(dataRaw, keyRaw); 99 | } 100 | 101 | public String encryptPrivate(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 102 | checkData(data); 103 | return encryptPrivate(new ByteArrayInputStream(data), key); 104 | } 105 | 106 | public byte[] encryptPrivateAsBytes(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 107 | checkData(data); 108 | return encryptPrivateAsBytes(new ByteArrayInputStream(data), key); 109 | } 110 | 111 | public String encryptPrivate(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 112 | return new String(Base64Util.encode(encryptPrivateAsBytes(data, key))); 113 | } 114 | 115 | public byte[] encryptPrivateAsBytes(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 116 | checkData(data); 117 | checkKey(key); 118 | Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE, Boolean.FALSE); 119 | return multiSlot(data, cipher, maxEncSize); 120 | } 121 | 122 | /** 123 | * 公钥解密 124 | * 125 | * @param data 126 | * @param key 127 | * @return 128 | * @throws NoSuchAlgorithmException 129 | * @throws InvalidKeySpecException 130 | * @throws NoSuchPaddingException 131 | * @throws InvalidKeyException 132 | * @throws BadPaddingException 133 | * @throws IllegalBlockSizeException 134 | */ 135 | public String decryptPublic(final String data, final String key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 136 | byte[] dataRaw = data == null ? null : Base64Util.decode(data.getBytes()); 137 | byte[] keyRaw = key == null ? null : Base64Util.decode(key.getBytes()); 138 | return decryptPublic(dataRaw, keyRaw); 139 | } 140 | 141 | public String decryptPublic(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 142 | checkData(data); 143 | return decryptPublic(new ByteArrayInputStream(data), key); 144 | } 145 | 146 | public byte[] decryptPublicAsBytes(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 147 | checkData(data); 148 | return decryptPublicAsBytes(new ByteArrayInputStream(data), key); 149 | } 150 | 151 | public String decryptPublic(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 152 | return new String(decryptPublicAsBytes(data, key), Encoding.UTF_8.getEncoding()); 153 | } 154 | 155 | public byte[] decryptPublicAsBytes(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 156 | checkData(data); 157 | checkKey(key); 158 | Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE, Boolean.TRUE); 159 | return multiSlot(data, cipher, maxDecSize); 160 | } 161 | 162 | public String encryptPublic(final String data, final String key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 163 | byte[] dataRaw = data == null ? null : data.getBytes(Encoding.UTF_8.getEncoding()); 164 | byte[] keyRaw = key == null ? null : Base64Util.decode(key.getBytes()); 165 | return encryptPublic(dataRaw, keyRaw); 166 | } 167 | 168 | public String encryptPublic(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 169 | checkData(data); 170 | return encryptPublic(new ByteArrayInputStream(data), key); 171 | } 172 | 173 | public byte[] encryptPublicAsBytes(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 174 | checkData(data); 175 | return encryptPublicAsBytes(new ByteArrayInputStream(data), key); 176 | } 177 | 178 | public String encryptPublic(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 179 | return new String(Base64Util.encode(encryptPublicAsBytes(data, key))); 180 | } 181 | 182 | public byte[] encryptPublicAsBytes(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 183 | checkData(data); 184 | checkKey(key); 185 | Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE, Boolean.TRUE); 186 | return multiSlot(data, cipher, maxEncSize); 187 | } 188 | 189 | public String decryptPrivate(final String data, final String key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 190 | byte[] dataRaw = data == null ? null : Base64Util.decode(data.getBytes()); 191 | byte[] keyRaw = key == null ? null : Base64Util.decode(key.getBytes()); 192 | return decryptPrivate(dataRaw, keyRaw); 193 | } 194 | 195 | public String decryptPrivate(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 196 | checkData(data); 197 | return decryptPrivate(new ByteArrayInputStream(data), key); 198 | } 199 | 200 | public byte[] decryptPrivateAsBytes(final byte[] data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 201 | checkData(data); 202 | return decryptPrivateAsBytes(new ByteArrayInputStream(data), key); 203 | } 204 | 205 | public String decryptPrivate(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 206 | return new String(decryptPrivateAsBytes(data, key), Encoding.UTF_8.getEncoding()); 207 | } 208 | 209 | public byte[] decryptPrivateAsBytes(final InputStream data, final byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { 210 | checkData(data); 211 | checkKey(key); 212 | Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE, Boolean.FALSE); 213 | return multiSlot(data, cipher, maxDecSize); 214 | } 215 | 216 | public static void main(String[] args) { 217 | String data = "{\"method\":\"RSA\",\"randCode\":\"zz13TnLnvybZZhJ3\",\"time\":\"2019-09-11 17:50:53\",\"equno\":\"djTest\",\"key\":\"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVcnve8fER4+hzQFLBplRGkzA078vJbRKMKBH5eUdQsKS+i3LEInYpNmKY+mTe+igjt9+slFqpKpg7zAWKveG1HIps7yJ8+1jetGyVD4ppVlFoRRJTgsGKf0kbsc8aw/O2i20e084y58IW7iaQ0rLfyCEwgWKQX6pH1GXL5jwBzwIDAQAB\"}"; 218 | try { 219 | RsaOperator rsaOperator = new RsaOperator(); 220 | KeyPair keyPair = rsaOperator.genKey(); 221 | String publicKey = new String(Base64Util.encode(keyPair.getPublic().getEncoded())); 222 | String privateKey = new String(Base64Util.encode(keyPair.getPrivate().getEncoded())); 223 | System.out.println("publicKey:" + publicKey + "\n" + "privateKey:" + privateKey); 224 | String result = rsaOperator.encryptPrivate(data, privateKey); 225 | System.out.println(result); 226 | String result2 = rsaOperator.decryptPublic(result, publicKey); 227 | System.out.println(result2); 228 | String result3 = rsaOperator.encryptPublic(data, publicKey); 229 | System.out.println(result3); 230 | String result4 = rsaOperator.decryptPrivate(result3, privateKey); 231 | System.out.println(result4); 232 | } catch (Exception e) { 233 | e.printStackTrace(); 234 | } 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/encrypt/SHA.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.encrypt; 2 | 3 | import org.apache.commons.codec.digest.DigestUtils; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.nio.charset.StandardCharsets; 8 | 9 | /** 10 | * @author kesc 11 | * @ClassName SHA512 12 | * @Description 13 | * @date 2017年10月28日 下午12:23:57 14 | */ 15 | public class SHA { 16 | private static volatile SHA instance = null; 17 | 18 | private SHA() { 19 | super(); 20 | } 21 | 22 | public static SHA getInstance() { 23 | if (instance == null) { 24 | synchronized (SHA.class) { 25 | if (instance == null) { 26 | instance = new SHA(); 27 | } 28 | } 29 | } 30 | return instance; 31 | } 32 | 33 | public byte[] sha512(final byte[] src) { 34 | if (src == null) { 35 | return null; 36 | } 37 | return DigestUtils.sha512(src); 38 | } 39 | 40 | public String sha512Hex(final byte[] src) { 41 | if (src == null) { 42 | return null; 43 | } 44 | return DigestUtils.sha512Hex(src); 45 | } 46 | 47 | public byte[] sha512(final String src) { 48 | if (src == null) { 49 | return null; 50 | } 51 | return sha512(src.getBytes(StandardCharsets.UTF_8)); 52 | } 53 | 54 | public String sha512Hex(final String src) { 55 | if (src == null) { 56 | return null; 57 | } 58 | return sha512Hex(src.getBytes(StandardCharsets.UTF_8)); 59 | } 60 | 61 | public byte[] sha512(final InputStream src) throws IOException { 62 | if (src == null) { 63 | return null; 64 | } 65 | return DigestUtils.sha512(src); 66 | } 67 | 68 | public String sha512Hex(final InputStream src) throws IOException { 69 | if (src == null) { 70 | return null; 71 | } 72 | return DigestUtils.sha512Hex(src); 73 | } 74 | 75 | public byte[] sha384(final byte[] src) { 76 | if (src == null) { 77 | return null; 78 | } 79 | return DigestUtils.sha384(src); 80 | } 81 | 82 | public String sha384Hex(final byte[] src) { 83 | if (src == null) { 84 | return null; 85 | } 86 | return DigestUtils.sha384Hex(src); 87 | } 88 | 89 | public byte[] sha384(final String src) { 90 | if (src == null) { 91 | return null; 92 | } 93 | return sha384(src.getBytes(StandardCharsets.UTF_8)); 94 | } 95 | 96 | public String sha384Hex(final String src) { 97 | if (src == null) { 98 | return null; 99 | } 100 | return sha384Hex(src.getBytes(StandardCharsets.UTF_8)); 101 | } 102 | 103 | public byte[] sha384(final InputStream src) throws IOException { 104 | if (src == null) { 105 | return null; 106 | } 107 | return DigestUtils.sha384(src); 108 | } 109 | 110 | public String sha384Hex(final InputStream src) throws IOException { 111 | if (src == null) { 112 | return null; 113 | } 114 | return DigestUtils.sha384Hex(src); 115 | } 116 | 117 | public byte[] sha256(final byte[] src) { 118 | if (src == null) { 119 | return null; 120 | } 121 | return DigestUtils.sha256(src); 122 | } 123 | 124 | public String sha256Hex(final byte[] src) { 125 | if (src == null) { 126 | return null; 127 | } 128 | return DigestUtils.sha256Hex(src); 129 | } 130 | 131 | public byte[] sha256(final String src) { 132 | if (src == null) { 133 | return null; 134 | } 135 | return sha256(src.getBytes(StandardCharsets.UTF_8)); 136 | } 137 | 138 | public String sha256Hex(final String src) { 139 | if (src == null) { 140 | return null; 141 | } 142 | return sha256Hex(src.getBytes(StandardCharsets.UTF_8)); 143 | } 144 | 145 | public byte[] sha256(final InputStream src) throws IOException { 146 | if (src == null) { 147 | return null; 148 | } 149 | return DigestUtils.sha256(src); 150 | } 151 | 152 | public String sha256Hex(final InputStream src) throws IOException { 153 | if (src == null) { 154 | return null; 155 | } 156 | return DigestUtils.sha256Hex(src); 157 | } 158 | 159 | public byte[] sha1(final byte[] src) { 160 | if (src == null) { 161 | return null; 162 | } 163 | return DigestUtils.sha1(src); 164 | } 165 | 166 | public String sha1Hex(final byte[] src) { 167 | if (src == null) { 168 | return null; 169 | } 170 | return DigestUtils.sha1Hex(src); 171 | } 172 | 173 | public byte[] sha1(final String src) { 174 | if (src == null) { 175 | return null; 176 | } 177 | return sha1(src.getBytes(StandardCharsets.UTF_8)); 178 | } 179 | 180 | public String sha1Hex(final String src) { 181 | if (src == null) { 182 | return null; 183 | } 184 | return sha1Hex(src.getBytes(StandardCharsets.UTF_8)); 185 | } 186 | 187 | public byte[] sha1(final InputStream src) throws IOException { 188 | if (src == null) { 189 | return null; 190 | } 191 | return DigestUtils.sha1(src); 192 | } 193 | 194 | public String sha1Hex(final InputStream src) throws IOException { 195 | if (src == null) { 196 | return null; 197 | } 198 | return DigestUtils.sha1Hex(src); 199 | } 200 | 201 | public static void main(String[] args) { 202 | SHA sha = SHA.getInstance(); 203 | String src = "fds宿舍"; 204 | System.out.println(sha.sha1Hex(src)); 205 | System.out.println(sha.sha256Hex(src)); 206 | System.out.println(sha.sha384Hex(src)); 207 | System.out.println(sha.sha512Hex(src)); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/enums/DatePatternEnum.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.enums; 2 | 3 | /** 4 | * @author kesc 5 | * @since 2017/12/25 6 | */ 7 | public enum DatePatternEnum { 8 | YYYY("yyyy"), 9 | YYYYMM("yyyyMM"), 10 | YYYYMMDD("yyyyMMdd"), 11 | YYYYMMDDHH("yyyyMMddHH"), 12 | YYMMDDHHMMSS("yyMMddHHmmss"), 13 | YYYYMMDDHHMMSS("yyyyMMddHHmmss"), 14 | YYYYMMDDHHMM("yyyyMMddHHmm"), 15 | YYYYMMDDHHMMSSSSS("yyyyMMddHHmmssSSS"), 16 | YYYYMM_BYSEP("yyyy-MM"), 17 | YYYYMMDD_BYSEP("yyyy-MM-dd"), 18 | YYYYMMDDHH_BYSEP("yyyy-MM-dd HH"), 19 | MMDD_BYSEP("MM-dd"), 20 | YYYYMMDDHHMMSS_BYSEP("yyyy-MM-dd HH:mm:ss"), 21 | YYYYMMDDHHMM_BYSEP("yyyy-MM-dd HH:mm"), 22 | YYYYMMDDHHMMSSSSS_BYSEP("yyyy-MM-dd HH:mm:ss.SSS"), 23 | HHMMSS("HHmmss"), 24 | HHMM_BYSEP("HH:mm"), 25 | HHMMSS_BYSEP("HH:mm:ss"), 26 | YYYYMM_BYSLASH("yyyy/MM"), 27 | YYYYMMDD_BYSLASH("yyyy/MM/dd"), 28 | YYYYMMDDHH_BYSLASH("yyyy/MM/dd HH"), 29 | MMDD_BYSLASH("MM/dd"), 30 | YYYYMMDDHHMMSS_BYSLASH("yyyy/MM/dd HH:mm:ss"), 31 | YYYYMMDDHHMM_BYSLASH("yyyy/MM/dd HH:mm"), 32 | YYYYMMDDHHMMSSSSS_BYSLASH("yyyy/MM/dd HH:mm:ss.SSS"), 33 | MINYEAR("1900"), 34 | MAXYEAR("9999"), 35 | MINDATE("19000101"), 36 | MAXDATE("99991231"), 37 | MINDATE_BYSEP("1900-01-01"), 38 | MAXDATE_BYSEP("9999-12-31"); 39 | 40 | private String format = null; 41 | 42 | private DatePatternEnum(String format) { 43 | this.format = format; 44 | } 45 | 46 | public String getFormat() { 47 | return format; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/enums/Encoding.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author kesc 7 | * @since 2019/3/1 8 | */ 9 | @Getter 10 | public enum Encoding { 11 | UTF_8("UTF-8"), 12 | GBK("GBK"), 13 | ISO_8859_1("ISO-8859-1"),; 14 | private String encoding; 15 | 16 | Encoding(String encoding) { 17 | this.encoding = encoding; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/enums/EnvEnum.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author kesc 7 | * @since 2019/3/15 8 | */ 9 | @Getter 10 | public enum EnvEnum { 11 | PRD("prd"), LOCAL("local"), DEV("dev"), TEST("test"), DEMO("demo"); 12 | private String env; 13 | 14 | EnvEnum(String env) { 15 | this.env = env; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/enums/FlagEnum.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author kesc 7 | * @date 2020-07-02 10:48 8 | */ 9 | @Getter 10 | public enum FlagEnum { 11 | YES(1, "yes", "是"), 12 | NO(0, "no", "否"), 13 | 14 | SUCCESS(1, "success", "成功"), 15 | FAIL(0, "fail", "失败"), 16 | 17 | TRUE(1, "true", "正确"), 18 | FALSE(0, "false", "错误"), 19 | 20 | DELETED(0, "deleted", "已删除"), 21 | EXISTED(1, "existed", "未删除"), 22 | 23 | ENABLE(1, "enable", "启用"), 24 | DISABLE(0, "disable", "禁用"), 25 | 26 | STOPPED(0, "stopped", "停止"), 27 | RUNNING(1, "running", "运行中"); 28 | 29 | private int flag; 30 | private String text; 31 | private String desc; 32 | 33 | FlagEnum(int flag, String text, String desc) { 34 | this.flag = flag; 35 | this.text = text; 36 | this.desc = desc; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/http/client/HttpClientWrapper.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.http.client; 2 | 3 | import com.xjbg.java.sdk.http.config.HttpConnectionConfig; 4 | import com.xjbg.java.sdk.http.request.BaseHttpRequest; 5 | import com.xjbg.java.sdk.http.util.HttpClientUtil; 6 | import com.xjbg.java.sdk.util.CollectionUtil; 7 | import com.xjbg.java.sdk.util.JsonUtil; 8 | import com.xjbg.java.sdk.util.StringUtil; 9 | import lombok.Getter; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.apache.http.*; 12 | import org.apache.http.client.HttpClient; 13 | import org.apache.http.client.HttpResponseException; 14 | import org.apache.http.client.ResponseHandler; 15 | import org.apache.http.client.entity.UrlEncodedFormEntity; 16 | import org.apache.http.client.methods.*; 17 | import org.apache.http.entity.ContentType; 18 | import org.apache.http.entity.StringEntity; 19 | import org.apache.http.impl.client.AbstractResponseHandler; 20 | import org.apache.http.impl.client.BasicResponseHandler; 21 | import org.apache.http.message.BasicNameValuePair; 22 | import org.apache.http.util.EntityUtils; 23 | 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.util.*; 27 | 28 | /** 29 | * @author kesc 30 | * @since 2023-08-08 15:53 31 | */ 32 | @Getter 33 | @Slf4j 34 | @SuppressWarnings({"unchecked", "unused"}) 35 | public class HttpClientWrapper { 36 | private static final ResponseHandler BASIC_RESPONSE_HANDLER = new BasicResponseHandler(); 37 | private static final ResponseHandler STREAM_RESPONSE_HANDLER = new AbstractResponseHandler() { 38 | @Override 39 | public InputStream handleEntity(HttpEntity httpEntity) throws IOException { 40 | return httpEntity.getContent(); 41 | } 42 | }; 43 | private final HttpClient httpClient; 44 | 45 | public HttpClientWrapper() { 46 | this.httpClient = HttpClientUtil.createHttpClient(new HttpConnectionConfig()); 47 | } 48 | 49 | public HttpClientWrapper(HttpClient httpClient) { 50 | this.httpClient = httpClient; 51 | } 52 | 53 | private HttpResponse execute(HttpRequestBase requestBase) throws IOException { 54 | if (log.isDebugEnabled()) { 55 | log.debug("request url:{}, headers:{}", requestBase, Arrays.toString(requestBase.getAllHeaders())); 56 | } 57 | HttpResponse httpResponse = getHttpClient().execute(requestBase); 58 | if (httpResponse.getStatusLine().getStatusCode() >= 300) { 59 | String message = httpResponse.getEntity() != null ? EntityUtils.toString(httpResponse.getEntity()) : null; 60 | throw new HttpResponseException(httpResponse.getStatusLine().getStatusCode(), 61 | StringUtil.isBlank(message) ? httpResponse.getStatusLine().getReasonPhrase() : message); 62 | } 63 | return httpResponse; 64 | } 65 | 66 | private H execute(HttpRequestBase requestBase, ResponseHandler responseHandler) throws IOException { 67 | HttpResponse httpResponse = execute(requestBase); 68 | return responseHandler.handleResponse(httpResponse); 69 | } 70 | 71 | private T execute(HttpRequestBase requestBase, Class resultClazz, Class... parametricType) throws IOException { 72 | if (resultClazz.isAssignableFrom(InputStream.class)) { 73 | return (T) execute(requestBase, STREAM_RESPONSE_HANDLER); 74 | } 75 | String response = execute(requestBase, BASIC_RESPONSE_HANDLER); 76 | log.debug("response:{}", response); 77 | return CollectionUtil.isEmpty(parametricType) ? JsonUtil.toObject(response, resultClazz) : JsonUtil.toObject(response, resultClazz, parametricType); 78 | } 79 | 80 | public String get(String url) throws IOException { 81 | return get(BaseHttpRequest.builder().setHost(url).build()); 82 | } 83 | 84 | public String get(B request) throws IOException { 85 | return get(request, String.class); 86 | } 87 | 88 | public R get(B request, Class clazz, Class... parametricType) throws IOException { 89 | Map headers = request.getHeaders(); 90 | Map params = request.getParams(); 91 | 92 | HttpGet httpGet = new HttpGet(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 93 | headers.forEach(httpGet::addHeader); 94 | 95 | return execute(httpGet, clazz, parametricType); 96 | } 97 | 98 | public String post(B request) throws IOException { 99 | return post(request, String.class); 100 | } 101 | 102 | public R post(B request, Class clazz, Class... parametricType) throws IOException { 103 | Map headers = request.getHeaders(); 104 | Map params = request.getParams(); 105 | Object body = request.getBody(); 106 | 107 | headers.put(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType()); 108 | HttpPost httpPost = new HttpPost(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 109 | headers.forEach(httpPost::addHeader); 110 | 111 | String jsonBody = JsonUtil.toJsonString(body); 112 | if (jsonBody != null) { 113 | httpPost.setEntity(new StringEntity(jsonBody)); 114 | } 115 | 116 | return execute(httpPost, clazz, parametricType); 117 | } 118 | 119 | public String postForm(B request) throws IOException { 120 | return postForm(request, String.class); 121 | } 122 | 123 | public R postForm(B request, Class clazz, Class... parametricType) throws IOException { 124 | Map headers = request.getHeaders(); 125 | Map params = request.getParams(); 126 | Map body = Optional.ofNullable(JsonUtil.toMap(JsonUtil.toJsonString(request.getBody()), String.class, String.class)).orElse(new HashMap<>()); 127 | 128 | headers.put(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.getMimeType()); 129 | HttpPost httpPost = new HttpPost(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 130 | headers.forEach(httpPost::addHeader); 131 | 132 | List nameValuePairs = new ArrayList<>(); 133 | body.forEach((k, v) -> nameValuePairs.add(new BasicNameValuePair(k, v))); 134 | httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, ContentType.APPLICATION_FORM_URLENCODED.getCharset())); 135 | 136 | return execute(httpPost, clazz, parametricType); 137 | } 138 | 139 | public String put(B request) throws IOException { 140 | return put(request, String.class); 141 | } 142 | 143 | public R put(B request, Class clazz, Class... parametricType) throws IOException { 144 | Map headers = request.getHeaders(); 145 | Map params = request.getParams(); 146 | Object body = request.getBody(); 147 | 148 | headers.put(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType()); 149 | HttpPut httpPut = new HttpPut(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 150 | headers.forEach(httpPut::addHeader); 151 | 152 | String jsonBody = JsonUtil.toJsonString(body); 153 | if (jsonBody != null) { 154 | httpPut.setEntity(new StringEntity(jsonBody)); 155 | } 156 | 157 | return execute(httpPut, clazz, parametricType); 158 | } 159 | 160 | public String patch(B request) throws IOException { 161 | return patch(request, String.class); 162 | } 163 | 164 | public R patch(B request, Class clazz, Class... parametricType) throws IOException { 165 | Map headers = request.getHeaders(); 166 | Map params = request.getParams(); 167 | Object body = request.getBody(); 168 | 169 | headers.put(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType()); 170 | HttpPatch httpPatch = new HttpPatch(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 171 | headers.forEach(httpPatch::addHeader); 172 | 173 | String jsonBody = JsonUtil.toJsonString(body); 174 | if (jsonBody != null) { 175 | httpPatch.setEntity(new StringEntity(jsonBody)); 176 | } 177 | 178 | return execute(httpPatch, clazz, parametricType); 179 | } 180 | 181 | public String delete(String url) throws IOException { 182 | return delete(BaseHttpRequest.builder().setHost(url).build()); 183 | } 184 | 185 | public String delete(B request) throws IOException { 186 | return delete(request, String.class); 187 | } 188 | 189 | public R delete(B request, Class clazz, Class... parametricType) throws IOException { 190 | Map headers = request.getHeaders(); 191 | Map params = request.getParams(); 192 | 193 | HttpDelete httpDelete = new HttpDelete(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 194 | headers.forEach(httpDelete::addHeader); 195 | 196 | return execute(httpDelete, clazz, parametricType); 197 | } 198 | 199 | public Map options(String url) throws IOException { 200 | return options(BaseHttpRequest.builder().setHost(url).build()); 201 | } 202 | 203 | public Map options(B request) throws IOException { 204 | Map headers = request.getHeaders(); 205 | Map params = request.getParams(); 206 | 207 | HttpOptions httpOptions = new HttpOptions(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 208 | headers.forEach(httpOptions::addHeader); 209 | 210 | HttpResponse httpResponse = execute(httpOptions); 211 | if (httpResponse.getEntity() != null) { 212 | EntityUtils.toString(httpResponse.getEntity()); 213 | } 214 | return CollectionUtil.toMap(Arrays.asList(httpResponse.getAllHeaders()), Header::getName, Header::getValue); 215 | } 216 | 217 | public Map head(String url) throws IOException { 218 | return head(BaseHttpRequest.builder().setHost(url).build()); 219 | } 220 | 221 | public Map head(B request) throws IOException { 222 | Map headers = request.getHeaders(); 223 | Map params = request.getParams(); 224 | 225 | HttpHead httpHead = new HttpHead(HttpClientUtil.buildUrl(request.getHost(), request.getPath(), params)); 226 | headers.forEach(httpHead::addHeader); 227 | 228 | HttpResponse httpResponse = execute(httpHead); 229 | return CollectionUtil.toMap(Arrays.asList(httpResponse.getAllHeaders()), Header::getName, Header::getValue); 230 | } 231 | 232 | } 233 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/http/config/HttpConnectionConfig.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.http.config; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author kesc 8 | * @since 2023-10-25 10:13 9 | */ 10 | @Getter 11 | @Setter 12 | public class HttpConnectionConfig { 13 | /** 14 | * 连接存活时间 单位:毫秒 15 | */ 16 | private int keepAlive = 60_000; 17 | /** 18 | * 多久检查一次连接池失效的连接 单位:毫秒 19 | */ 20 | private int validateAfterInactivity = 300_000; 21 | /** 22 | * 自定义请求头的user-agent属性 23 | */ 24 | private String userAgent; 25 | /** 26 | * 获取连接超时 单位:毫秒 27 | */ 28 | private int connectTimeout = 10000; 29 | /** 30 | * socket超时 单位:毫秒 31 | */ 32 | private int socketTimeout = 10000; 33 | /** 34 | * 请求超时 单位:毫秒 35 | */ 36 | private int requestTimeout = 10000; 37 | /** 38 | * 最大连接数 39 | */ 40 | private int maxConnect = 60; 41 | /** 42 | * 每个路由最大连接数 43 | */ 44 | private int maxConnectPerRoute = 30; 45 | /** 46 | * https证书 47 | */ 48 | private String certFile; 49 | /** 50 | * 是否忽略https校验,无需证书也可以发起https请求,生产上不推荐开启,建议使用证书 51 | */ 52 | private boolean ignoreHttps = false; 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/http/request/BaseHttpRequest.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.http.request; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author kesc 11 | * @since 2023-11-07 14:07 12 | */ 13 | @Getter 14 | @Setter 15 | public class BaseHttpRequest { 16 | /** 17 | * 域名 18 | */ 19 | private String host; 20 | /** 21 | * 接口路径 22 | */ 23 | private String path; 24 | /** 25 | * 附加的请求头信息 26 | */ 27 | private final Map headers = new HashMap<>(); 28 | /** 29 | * 附加的url参数 30 | */ 31 | private final Map params = new HashMap<>(); 32 | /** 33 | * post请求附加的请求体 34 | */ 35 | private Object body; 36 | 37 | public static Builder builder() { 38 | return new Builder(); 39 | } 40 | 41 | public static class Builder { 42 | private final BaseHttpRequest request = new BaseHttpRequest(); 43 | 44 | public Builder setHost(String host) { 45 | request.setHost(host); 46 | return this; 47 | } 48 | 49 | public Builder setPath(String path) { 50 | request.setPath(path); 51 | return this; 52 | } 53 | 54 | public Builder setBody(Object body) { 55 | request.setBody(body); 56 | return this; 57 | } 58 | 59 | public Builder addParam(String key, String value) { 60 | request.getParams().put(key, value); 61 | return this; 62 | } 63 | 64 | public Builder addParams(Map params) { 65 | request.getParams().putAll(params); 66 | return this; 67 | } 68 | 69 | public Builder addHeader(String key, String value) { 70 | request.getHeaders().put(key, value); 71 | return this; 72 | } 73 | 74 | public Builder addHeaders(Map headers) { 75 | request.getHeaders().putAll(headers); 76 | return this; 77 | } 78 | 79 | public BaseHttpRequest build() { 80 | return request; 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/http/util/HttpClientUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.http.util; 2 | 3 | import com.xjbg.java.sdk.http.config.HttpConnectionConfig; 4 | import com.xjbg.java.sdk.util.StringUtil; 5 | import lombok.SneakyThrows; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.http.HeaderElement; 8 | import org.apache.http.HeaderElementIterator; 9 | import org.apache.http.client.HttpClient; 10 | import org.apache.http.client.config.RequestConfig; 11 | import org.apache.http.client.utils.URLEncodedUtils; 12 | import org.apache.http.conn.ConnectionKeepAliveStrategy; 13 | import org.apache.http.impl.client.HttpClientBuilder; 14 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 15 | import org.apache.http.message.BasicHeaderElementIterator; 16 | import org.apache.http.message.BasicNameValuePair; 17 | import org.apache.http.protocol.HTTP; 18 | 19 | import javax.net.ssl.*; 20 | import java.io.FileInputStream; 21 | import java.io.IOException; 22 | import java.nio.charset.StandardCharsets; 23 | import java.security.GeneralSecurityException; 24 | import java.security.KeyStore; 25 | import java.security.SecureRandom; 26 | import java.security.cert.Certificate; 27 | import java.security.cert.CertificateException; 28 | import java.security.cert.CertificateFactory; 29 | import java.security.cert.X509Certificate; 30 | import java.util.Collection; 31 | import java.util.List; 32 | import java.util.Map; 33 | import java.util.stream.Collectors; 34 | 35 | /** 36 | * @author kesc 37 | * @since 2019/6/24 38 | */ 39 | @Slf4j 40 | public final class HttpClientUtil { 41 | @SneakyThrows 42 | public static Object[] ignoreSslContext() { 43 | SSLContext sc = SSLContext.getInstance("TLS"); 44 | X509TrustManager x509TrustManager = new X509TrustManager() { 45 | @Override 46 | public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { 47 | } 48 | 49 | @Override 50 | public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { 51 | } 52 | 53 | @Override 54 | public X509Certificate[] getAcceptedIssuers() { 55 | return new X509Certificate[0]; 56 | } 57 | }; 58 | sc.init(null, new X509TrustManager[]{x509TrustManager}, new SecureRandom()); 59 | return new Object[]{sc, x509TrustManager}; 60 | } 61 | 62 | public static Object[] sslContext(String certFile) { 63 | if (StringUtil.isBlank(certFile)) { 64 | return null; 65 | } 66 | try { 67 | Collection certificates = null; 68 | try (FileInputStream fis = new FileInputStream(certFile)) { 69 | certificates = CertificateFactory.getInstance("X.509").generateCertificates(fis); 70 | } 71 | 72 | if (certificates == null || certificates.isEmpty()) { 73 | throw new IllegalArgumentException("expected non-empty set of trusted certificates"); 74 | } 75 | 76 | // Any password will work. 77 | char[] password = "password".toCharArray(); 78 | // Put the certificates a key store. 79 | KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 80 | // By convention, 'null' creates an empty key store. 81 | keyStore.load(null, password); 82 | 83 | int index = 0; 84 | for (Certificate certificate : certificates) { 85 | String certificateAlias = Integer.toString(index++); 86 | keyStore.setCertificateEntry(certificateAlias, certificate); 87 | } 88 | 89 | // Use it to build an X509 trust manager. 90 | KeyManagerFactory keyManagerFactory = 91 | KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 92 | keyManagerFactory.init(keyStore, password); 93 | TrustManagerFactory trustManagerFactory = 94 | TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 95 | trustManagerFactory.init(keyStore); 96 | 97 | final KeyManager[] keyManagers = keyManagerFactory.getKeyManagers(); 98 | final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); 99 | 100 | SSLContext sslContext = SSLContext.getInstance("TLS"); 101 | sslContext.init(keyManagers, trustManagers, new SecureRandom()); 102 | return new Object[]{sslContext, trustManagers[0]}; 103 | } catch (GeneralSecurityException | IOException e) { 104 | throw new RuntimeException(e); 105 | } 106 | } 107 | 108 | @SneakyThrows 109 | public static HttpClient createHttpClient(HttpConnectionConfig connectionProperties) { 110 | ConnectionKeepAliveStrategy keepAliveStrategy = (response, context) -> { 111 | HeaderElementIterator it = new BasicHeaderElementIterator 112 | (response.headerIterator(HTTP.CONN_KEEP_ALIVE)); 113 | while (it.hasNext()) { 114 | HeaderElement he = it.nextElement(); 115 | String param = he.getName(); 116 | String value = he.getValue(); 117 | if (value != null && "timeout".equalsIgnoreCase(param)) { 118 | return Long.parseLong(value) * 1000; 119 | } 120 | } 121 | return connectionProperties.getKeepAlive(); 122 | }; 123 | 124 | PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); 125 | connectionManager.setMaxTotal(Math.max(connectionProperties.getMaxConnect(), 10)); 126 | connectionManager.setDefaultMaxPerRoute(Math.max(connectionProperties.getMaxConnectPerRoute(), 5)); 127 | connectionManager.setValidateAfterInactivity(connectionProperties.getValidateAfterInactivity()); 128 | 129 | HttpClientBuilder httpClientBuilder = HttpClientBuilder.create() 130 | .setConnectionManager(connectionManager) 131 | .setKeepAliveStrategy(keepAliveStrategy) 132 | .setUserAgent(connectionProperties.getUserAgent()) 133 | .setDefaultRequestConfig(RequestConfig.custom().setSocketTimeout(connectionProperties.getSocketTimeout()) 134 | .setConnectTimeout(connectionProperties.getConnectTimeout()) 135 | .setConnectionRequestTimeout(connectionProperties.getRequestTimeout()).build()); 136 | 137 | if (connectionProperties.isIgnoreHttps()) { 138 | httpClientBuilder.setSSLContext((SSLContext) ignoreSslContext()[0]); 139 | } else { 140 | Object[] objects = sslContext(connectionProperties.getCertFile()); 141 | if (objects != null) { 142 | httpClientBuilder.setSSLContext((SSLContext) objects[0]); 143 | } 144 | } 145 | return httpClientBuilder.build(); 146 | } 147 | 148 | public static String buildQueryParam(Map params) { 149 | if (params != null && params.size() > 0) { 150 | List nameValuePairs = params.entrySet().stream().map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue())).collect(Collectors.toList()); 151 | return URLEncodedUtils.format(nameValuePairs, StandardCharsets.UTF_8); 152 | } 153 | return StringUtil.EMPTY; 154 | } 155 | 156 | public static String buildUrl(String host, String path, Map params) { 157 | StringBuilder sb = new StringBuilder(host); 158 | if (StringUtil.isNotBlank(path)) { 159 | if (!host.endsWith(StringUtil.VIRGULE) && !path.startsWith(StringUtil.VIRGULE)) { 160 | sb.append(StringUtil.VIRGULE); 161 | } 162 | sb.append(path); 163 | } 164 | String queryParam = buildQueryParam(params); 165 | if (StringUtil.isNotBlank(queryParam)) { 166 | if (sb.indexOf("?") > -1) { 167 | sb.append("&"); 168 | } else { 169 | sb.append("?"); 170 | } 171 | sb.append(queryParam); 172 | } 173 | return sb.toString(); 174 | } 175 | 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/lock/StripedLock.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.lock; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * 细粒度锁 7 | * 8 | * @author kesc 9 | * @since 2019/3/8 10 | */ 11 | public interface StripedLock { 12 | /** 13 | * 获取锁 一直阻塞 14 | * 15 | * @param key 16 | */ 17 | void lock(String key); 18 | 19 | /** 20 | * 获取锁 超时返回false 21 | * 22 | * @param key 23 | * @param time 24 | * @param timeUnit 25 | * @return 26 | * @throws InterruptedException 27 | */ 28 | boolean tryLock(String key, long time, TimeUnit timeUnit) throws InterruptedException; 29 | 30 | /** 31 | * 释放锁 32 | * 33 | * @param key 34 | */ 35 | void unlock(String key); 36 | 37 | /** 38 | * 强制释放锁 39 | * 40 | * @param key 41 | */ 42 | void forceUnlock(String key); 43 | 44 | /** 45 | * 当前线程是否持有锁 46 | * 47 | * @param key 48 | * @return 49 | */ 50 | boolean isHeldByCurrentThread(String key); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/lock/impl/DefaultRedisDistributedLock.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.lock.impl; 2 | 3 | import com.xjbg.java.sdk.lock.StripedLock; 4 | import com.xjbg.java.sdk.util.JsonUtil; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.data.redis.connection.DefaultStringRedisConnection; 9 | import org.springframework.data.redis.connection.StringRedisConnection; 10 | import org.springframework.data.redis.core.RedisCallback; 11 | import org.springframework.data.redis.core.StringRedisTemplate; 12 | import org.springframework.util.StopWatch; 13 | 14 | import java.util.Objects; 15 | import java.util.UUID; 16 | import java.util.concurrent.TimeUnit; 17 | 18 | /** 19 | * 基于redis的细粒度分布式锁 20 | * 21 | * @author kesc 22 | * @since 2019/3/8 23 | */ 24 | @Slf4j 25 | @Getter 26 | @Setter 27 | public final class DefaultRedisDistributedLock implements StripedLock { 28 | private static final long LONG_ZERO = 0L; 29 | private static final String PREFIX = "lock:"; 30 | private static final long DEFAULT_SLEEP_TIME = 10L; 31 | private int maxLeaseTime = 60000; 32 | private StringRedisTemplate stringRedisTemplate; 33 | private static final ThreadLocal THREAD_UUID = new ThreadLocal<>(); 34 | 35 | public DefaultRedisDistributedLock(StringRedisTemplate stringRedisTemplate) { 36 | this.stringRedisTemplate = stringRedisTemplate; 37 | } 38 | 39 | @Override 40 | public void lock(String key) { 41 | boolean isLocked = this.lockInner(key, this.maxLeaseTime, 0L); 42 | if (!isLocked) { 43 | throw new RuntimeException("error occur when lock"); 44 | } 45 | } 46 | 47 | @Override 48 | public boolean tryLock(String key, long time, TimeUnit unit) { 49 | long waitTime = unit.toMillis(time); 50 | return this.lockInner(key, this.maxLeaseTime, waitTime); 51 | } 52 | 53 | @Override 54 | public void unlock(String key) { 55 | if (this.isHeldByCurrentThread(key)) { 56 | this.unlockInner(key); 57 | THREAD_UUID.remove(); 58 | } 59 | 60 | } 61 | 62 | @Override 63 | public void forceUnlock(String key) { 64 | this.unlockInner(key); 65 | log.debug("force unlocked, key={}", key); 66 | } 67 | 68 | @Override 69 | public boolean isHeldByCurrentThread(String key) { 70 | DefaultRedisDistributedLock.LockValue lockValue = this.getCurrentLock(key); 71 | return lockValue != null && Objects.equals(THREAD_UUID.get(), lockValue.getId()); 72 | } 73 | 74 | private DefaultRedisDistributedLock.LockValue getCurrentLock(String key) { 75 | String lockKey = this.getKey(key); 76 | String value = this.stringRedisTemplate.opsForValue().get(lockKey); 77 | return value == null ? null : JsonUtil.toObject(value, DefaultRedisDistributedLock.LockValue.class); 78 | } 79 | 80 | private String getKey(String key) { 81 | return PREFIX + key; 82 | } 83 | 84 | private boolean lockInner(String key, int leaseTime, long timeout) { 85 | String lockKey = this.getKey(key); 86 | try { 87 | boolean isTry = timeout > LONG_ZERO; 88 | String value = JsonUtil.toJsonString(new DefaultRedisDistributedLock.LockValue()); 89 | log.debug("begin try lock, isTry={}, timeout={}, key={}", isTry, timeout, lockKey); 90 | StopWatch stopWatch = new StopWatch(); 91 | stopWatch.start(); 92 | stopWatch.stop(); 93 | while (!isTry || stopWatch.getTotalTimeMillis() <= timeout) { 94 | stopWatch.start(); 95 | Boolean success = setIfAbsent(this.stringRedisTemplate, lockKey, value, leaseTime, TimeUnit.MILLISECONDS); 96 | if (success) { 97 | log.debug("locked, key= {}, value={}", lockKey, value); 98 | return true; 99 | } 100 | stopWatch.stop(); 101 | Thread.sleep(DEFAULT_SLEEP_TIME); 102 | } 103 | log.info("fail to lock cause by timeout, key={}", lockKey); 104 | return false; 105 | } catch (Exception e) { 106 | log.error("error occur when lock, key=" + lockKey, e); 107 | return false; 108 | } 109 | } 110 | 111 | private void unlockInner(String key) { 112 | String lockKey = this.getKey(key); 113 | this.stringRedisTemplate.delete(lockKey); 114 | } 115 | 116 | private Boolean setIfAbsent(StringRedisTemplate stringRedisTemplate, String key, String value, long timeout, TimeUnit unit) { 117 | return stringRedisTemplate.execute((RedisCallback) connection -> { 118 | StringRedisConnection stringRedisConnection = new DefaultStringRedisConnection(connection); 119 | Object executeResult = stringRedisConnection.execute("set", key, value, "px", String.valueOf(unit.toMillis(timeout)), "NX"); 120 | return executeResult != null; 121 | }); 122 | } 123 | 124 | static class LockValue { 125 | private UUID id = UUID.randomUUID(); 126 | private Long threadId; 127 | 128 | public LockValue() { 129 | DefaultRedisDistributedLock.THREAD_UUID.set(this.id); 130 | this.threadId = Thread.currentThread().getId(); 131 | } 132 | 133 | public UUID getId() { 134 | return this.id; 135 | } 136 | 137 | public void setId(UUID id) { 138 | this.id = id; 139 | DefaultRedisDistributedLock.THREAD_UUID.set(this.id); 140 | } 141 | 142 | public Long getThreadId() { 143 | return this.threadId; 144 | } 145 | 146 | public void setThreadId(Long threadId) { 147 | this.threadId = threadId; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/lock/impl/DefaultReentrantStripedLock.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.lock.impl; 2 | 3 | import com.xjbg.java.sdk.lock.StripedLock; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.concurrent.TimeUnit; 9 | import java.util.concurrent.locks.ReentrantLock; 10 | 11 | /** 12 | * 细粒度的可重入锁 内存锁 不可用于分布式集群环境 13 | * 14 | * @author kesc 15 | * @date 2020-06-18 15:59 16 | */ 17 | @Slf4j 18 | public class DefaultReentrantStripedLock implements StripedLock { 19 | private static final byte[] LOCK = new byte[0]; 20 | private final Map lockMap = new HashMap<>(); 21 | 22 | private ReentrantLock computeLock(String key) { 23 | if (!lockMap.containsKey(key)) { 24 | synchronized (LOCK) { 25 | if (!lockMap.containsKey(key)) { 26 | lockMap.put(key, new ReentrantLock()); 27 | } 28 | } 29 | } 30 | return lockMap.get(key); 31 | } 32 | 33 | @Override 34 | public void lock(String key) { 35 | computeLock(key).lock(); 36 | log.debug("get lock by key:{}", key); 37 | } 38 | 39 | @Override 40 | public boolean tryLock(String key, long timeout, TimeUnit timeUnit) throws InterruptedException { 41 | boolean tryLock = computeLock(key).tryLock(timeout, timeUnit); 42 | log.debug("try lock by key:{},timeout:{},timeUnit:{},success:{}", key, timeout, timeUnit.toString(), 43 | tryLock); 44 | return tryLock; 45 | } 46 | 47 | @Override 48 | public void unlock(String key) { 49 | if (isHeldByCurrentThread(key)) { 50 | lockMap.get(key).unlock(); 51 | log.debug("unlock by key:{}", key); 52 | } 53 | } 54 | 55 | @Override 56 | public void forceUnlock(String key) { 57 | ReentrantLock lock = lockMap.get(key); 58 | if (lock == null) { 59 | return; 60 | } 61 | lock.unlock(); 62 | log.debug("force unlock by key:{}", key); 63 | } 64 | 65 | @Override 66 | public boolean isHeldByCurrentThread(String key) { 67 | ReentrantLock lock = lockMap.get(key); 68 | boolean flag = lock != null && lock.isHeldByCurrentThread(); 69 | log.debug("is held by current thread,flag:{}, key:{}", flag, key); 70 | return flag; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/monitor/VMInfo.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.monitor; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.lang.management.GarbageCollectorMXBean; 7 | import java.lang.management.MemoryPoolMXBean; 8 | import java.lang.management.OperatingSystemMXBean; 9 | import java.lang.management.RuntimeMXBean; 10 | import java.lang.reflect.Method; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author kesc 17 | * @since 2019/6/24 18 | */ 19 | public class VMInfo { 20 | private static final Logger LOG = LoggerFactory.getLogger(VMInfo.class); 21 | static final long MB = 1024 * 1024; 22 | static final long GB = 1024 * 1024 * 1024; 23 | public final static byte[] LOCK = new byte[0]; 24 | private static volatile VMInfo vmInfo; 25 | 26 | /** 27 | * @return null or vmInfo. null is something error, job no care it. 28 | */ 29 | public static VMInfo getVmInfo() { 30 | if (vmInfo == null) { 31 | synchronized (LOCK) { 32 | if (vmInfo == null) { 33 | try { 34 | vmInfo = new VMInfo(); 35 | } catch (Exception e) { 36 | LOG.warn("no need care, the fail is ignored : vmInfo init failed " + e.getMessage(), e); 37 | } 38 | } 39 | } 40 | 41 | } 42 | return vmInfo; 43 | } 44 | 45 | // 数据的MxBean 46 | private final OperatingSystemMXBean osMXBean; 47 | private final RuntimeMXBean runtimeMXBean; 48 | private final List garbageCollectorMXBeanList; 49 | private final List memoryPoolMXBeanList; 50 | /** 51 | * 静态信息 52 | */ 53 | private final String osInfo; 54 | private final String jvmInfo; 55 | 56 | /** 57 | * cpu个数 58 | */ 59 | private final int totalProcessorCount; 60 | 61 | /** 62 | * 机器的各个状态,用于中间打印和统计上报 63 | */ 64 | private final PhyOSStatus startPhyOSStatus; 65 | private final ProcessCpuStatus processCpuStatus = new ProcessCpuStatus(); 66 | private final ProcessGCStatus processGCStatus = new ProcessGCStatus(); 67 | private final ProcessMemoryStatus processMomoryStatus = new ProcessMemoryStatus(); 68 | //ms 69 | private long lastUpTime = 0; 70 | //nano 71 | private long lastProcessCpuTime = 0; 72 | 73 | 74 | private VMInfo() { 75 | //初始化静态信息 76 | osMXBean = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); 77 | runtimeMXBean = java.lang.management.ManagementFactory.getRuntimeMXBean(); 78 | garbageCollectorMXBeanList = java.lang.management.ManagementFactory.getGarbageCollectorMXBeans(); 79 | memoryPoolMXBeanList = java.lang.management.ManagementFactory.getMemoryPoolMXBeans(); 80 | 81 | osInfo = runtimeMXBean.getVmVendor() + " " + runtimeMXBean.getSpecVersion() + " " + runtimeMXBean.getVmVersion(); 82 | jvmInfo = osMXBean.getName() + " " + osMXBean.getArch() + " " + osMXBean.getVersion(); 83 | totalProcessorCount = osMXBean.getAvailableProcessors(); 84 | 85 | //构建startPhyOSStatus 86 | startPhyOSStatus = new PhyOSStatus(); 87 | LOG.info("VMInfo# operatingSystem class => " + osMXBean.getClass().getName()); 88 | if (VMInfo.isSunOsMBean(osMXBean)) { 89 | { 90 | startPhyOSStatus.totalPhysicalMemory = VMInfo.getLongFromOperatingSystem(osMXBean, "getTotalPhysicalMemorySize"); 91 | startPhyOSStatus.freePhysicalMemory = VMInfo.getLongFromOperatingSystem(osMXBean, "getFreePhysicalMemorySize"); 92 | startPhyOSStatus.maxFileDescriptorCount = VMInfo.getLongFromOperatingSystem(osMXBean, "getMaxFileDescriptorCount"); 93 | startPhyOSStatus.currentOpenFileDescriptorCount = VMInfo.getLongFromOperatingSystem(osMXBean, "getOpenFileDescriptorCount"); 94 | } 95 | } 96 | 97 | //初始化processGCStatus; 98 | for (GarbageCollectorMXBean garbage : garbageCollectorMXBeanList) { 99 | GCStatus gcStatus = new GCStatus(); 100 | gcStatus.name = garbage.getName(); 101 | processGCStatus.gcStatusMap.put(garbage.getName(), gcStatus); 102 | } 103 | 104 | //初始化processMemoryStatus 105 | if (memoryPoolMXBeanList != null && !memoryPoolMXBeanList.isEmpty()) { 106 | for (MemoryPoolMXBean pool : memoryPoolMXBeanList) { 107 | MemoryStatus memoryStatus = new MemoryStatus(); 108 | memoryStatus.name = pool.getName(); 109 | memoryStatus.initSize = pool.getUsage().getInit(); 110 | memoryStatus.maxSize = pool.getUsage().getMax(); 111 | processMomoryStatus.memoryStatusMap.put(pool.getName(), memoryStatus); 112 | } 113 | } 114 | } 115 | 116 | @Override 117 | public String toString() { 118 | return "the machine info => \n\n" 119 | + "\tosInfo:\t" + osInfo + "\n" 120 | + "\tjvmInfo:\t" + jvmInfo + "\n" 121 | + "\tcpu num:\t" + totalProcessorCount + "\n\n" 122 | + startPhyOSStatus.toString() + "\n" 123 | + processGCStatus.toString() + "\n" 124 | + processMomoryStatus.toString() + "\n"; 125 | } 126 | 127 | public String totalString() { 128 | return (processCpuStatus.getTotalString() + processGCStatus.getTotalString()); 129 | } 130 | 131 | public void getDelta() { 132 | getDelta(true); 133 | } 134 | 135 | public synchronized void getDelta(boolean print) { 136 | 137 | try { 138 | if (VMInfo.isSunOsMBean(osMXBean)) { 139 | long curUptime = runtimeMXBean.getUptime(); 140 | long curProcessTime = getLongFromOperatingSystem(osMXBean, "getProcessCpuTime"); 141 | //百分比, uptime是ms,processTime是nano 142 | if ((curUptime > lastUpTime) && (curProcessTime >= lastProcessCpuTime)) { 143 | float curDeltaCpu = (float) (curProcessTime - lastProcessCpuTime) / ((curUptime - lastUpTime) * totalProcessorCount * 10000); 144 | processCpuStatus.setMaxMinCpu(curDeltaCpu); 145 | processCpuStatus.averageCpu = (float) curProcessTime / (curUptime * totalProcessorCount * 10000); 146 | 147 | lastUpTime = curUptime; 148 | lastProcessCpuTime = curProcessTime; 149 | } 150 | } 151 | 152 | for (GarbageCollectorMXBean garbage : garbageCollectorMXBeanList) { 153 | 154 | GCStatus gcStatus = processGCStatus.gcStatusMap.get(garbage.getName()); 155 | if (gcStatus == null) { 156 | gcStatus = new GCStatus(); 157 | gcStatus.name = garbage.getName(); 158 | processGCStatus.gcStatusMap.put(garbage.getName(), gcStatus); 159 | } 160 | 161 | long curTotalGcCount = garbage.getCollectionCount(); 162 | gcStatus.setCurTotalGcCount(curTotalGcCount); 163 | 164 | long curtotalGcTime = garbage.getCollectionTime(); 165 | gcStatus.setCurTotalGcTime(curtotalGcTime); 166 | } 167 | 168 | if (memoryPoolMXBeanList != null && !memoryPoolMXBeanList.isEmpty()) { 169 | for (MemoryPoolMXBean pool : memoryPoolMXBeanList) { 170 | 171 | MemoryStatus memoryStatus = processMomoryStatus.memoryStatusMap.get(pool.getName()); 172 | if (memoryStatus == null) { 173 | memoryStatus = new MemoryStatus(); 174 | memoryStatus.name = pool.getName(); 175 | processMomoryStatus.memoryStatusMap.put(pool.getName(), memoryStatus); 176 | } 177 | memoryStatus.commitedSize = pool.getUsage().getCommitted(); 178 | memoryStatus.setMaxMinUsedSize(pool.getUsage().getUsed()); 179 | long maxMemory = memoryStatus.commitedSize > 0 ? memoryStatus.commitedSize : memoryStatus.maxSize; 180 | memoryStatus.setMaxMinPercent(maxMemory > 0 ? (float) 100 * memoryStatus.usedSize / maxMemory : -1); 181 | } 182 | } 183 | 184 | if (print) { 185 | LOG.info(processCpuStatus.getDeltaString() + processMomoryStatus.getDeltaString() + processGCStatus.getDeltaString()); 186 | } 187 | 188 | } catch (Exception e) { 189 | LOG.warn("no need care, the fail is ignored : vmInfo getDelta failed " + e.getMessage(), e); 190 | } 191 | } 192 | 193 | public static boolean isSunOsMBean(OperatingSystemMXBean operatingSystem) { 194 | final String className = operatingSystem.getClass().getName(); 195 | 196 | return "com.sun.management.UnixOperatingSystem".equals(className); 197 | } 198 | 199 | public static long getLongFromOperatingSystem(OperatingSystemMXBean operatingSystem, String methodName) { 200 | try { 201 | final Method method = operatingSystem.getClass().getMethod(methodName, (Class[]) null); 202 | method.setAccessible(true); 203 | return (Long) method.invoke(operatingSystem, (Object[]) null); 204 | } catch (final Exception e) { 205 | LOG.info(String.format("OperatingSystemMXBean %s failed, Exception = %s ", methodName, e.getMessage())); 206 | } 207 | 208 | return -1; 209 | } 210 | 211 | private class PhyOSStatus { 212 | long totalPhysicalMemory = -1; 213 | long freePhysicalMemory = -1; 214 | long maxFileDescriptorCount = -1; 215 | long currentOpenFileDescriptorCount = -1; 216 | 217 | @Override 218 | public String toString() { 219 | return String.format("\ttotalPhysicalMemory:\t%,.2fG\n" 220 | + "\tfreePhysicalMemory:\t%,.2fG\n" 221 | + "\tmaxFileDescriptorCount:\t%s\n" 222 | + "\tcurrentOpenFileDescriptorCount:\t%s\n", 223 | (float) totalPhysicalMemory / GB, (float) freePhysicalMemory / GB, maxFileDescriptorCount, currentOpenFileDescriptorCount); 224 | } 225 | } 226 | 227 | private class ProcessCpuStatus { 228 | // 百分比的值 比如30.0 表示30.0% 229 | float maxDeltaCpu = -1; 230 | float minDeltaCpu = -1; 231 | float curDeltaCpu = -1; 232 | float averageCpu = -1; 233 | 234 | public void setMaxMinCpu(float curCpu) { 235 | this.curDeltaCpu = curCpu; 236 | if (maxDeltaCpu < curCpu) { 237 | maxDeltaCpu = curCpu; 238 | } 239 | 240 | if (minDeltaCpu == -1 || minDeltaCpu > curCpu) { 241 | minDeltaCpu = curCpu; 242 | } 243 | } 244 | 245 | public String getDeltaString() { 246 | StringBuilder sb = new StringBuilder(); 247 | sb.append("\n\t [delta cpu info] => \n"); 248 | sb.append("\t\t"); 249 | sb.append(String.format("%-30s | %-30s | %-30s | %-30s \n", "curDeltaCpu", "averageCpu", "maxDeltaCpu", "minDeltaCpu")); 250 | sb.append("\t\t"); 251 | sb.append(String.format("%-30s | %-30s | %-30s | %-30s \n", 252 | String.format("%,.2f%%", processCpuStatus.curDeltaCpu), 253 | String.format("%,.2f%%", processCpuStatus.averageCpu), 254 | String.format("%,.2f%%", processCpuStatus.maxDeltaCpu), 255 | String.format("%,.2f%%\n", processCpuStatus.minDeltaCpu))); 256 | 257 | return sb.toString(); 258 | } 259 | 260 | public String getTotalString() { 261 | StringBuilder sb = new StringBuilder(); 262 | sb.append("\n\t [total cpu info] => \n"); 263 | sb.append("\t\t"); 264 | sb.append(String.format("%-30s | %-30s | %-30s \n", "averageCpu", "maxDeltaCpu", "minDeltaCpu")); 265 | sb.append("\t\t"); 266 | sb.append(String.format("%-30s | %-30s | %-30s \n", 267 | String.format("%,.2f%%", processCpuStatus.averageCpu), 268 | String.format("%,.2f%%", processCpuStatus.maxDeltaCpu), 269 | String.format("%,.2f%%\n", processCpuStatus.minDeltaCpu))); 270 | 271 | return sb.toString(); 272 | } 273 | 274 | } 275 | 276 | private class ProcessGCStatus { 277 | final Map gcStatusMap = new HashMap(); 278 | 279 | @Override 280 | public String toString() { 281 | return "\tGC Names\t" + gcStatusMap.keySet() + "\n"; 282 | } 283 | 284 | public String getDeltaString() { 285 | StringBuilder sb = new StringBuilder(); 286 | sb.append("\n\t [delta gc info] => \n"); 287 | sb.append("\t\t "); 288 | sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n", "NAME", "curDeltaGCCount", "totalGCCount", "maxDeltaGCCount", "minDeltaGCCount", "curDeltaGCTime", "totalGCTime", "maxDeltaGCTime", "minDeltaGCTime")); 289 | for (GCStatus gc : gcStatusMap.values()) { 290 | sb.append("\t\t "); 291 | sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n", 292 | gc.name, gc.curDeltaGCCount, gc.totalGCCount, gc.maxDeltaGCCount, gc.minDeltaGCCount, 293 | String.format("%,.3fs", (float) gc.curDeltaGCTime / 1000), 294 | String.format("%,.3fs", (float) gc.totalGCTime / 1000), 295 | String.format("%,.3fs", (float) gc.maxDeltaGCTime / 1000), 296 | String.format("%,.3fs", (float) gc.minDeltaGCTime / 1000))); 297 | 298 | } 299 | return sb.toString(); 300 | } 301 | 302 | public String getTotalString() { 303 | StringBuilder sb = new StringBuilder(); 304 | sb.append("\n\t [total gc info] => \n"); 305 | sb.append("\t\t "); 306 | sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n", "NAME", "totalGCCount", "maxDeltaGCCount", "minDeltaGCCount", "totalGCTime", "maxDeltaGCTime", "minDeltaGCTime")); 307 | for (GCStatus gc : gcStatusMap.values()) { 308 | sb.append("\t\t "); 309 | sb.append(String.format("%-20s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s \n", 310 | gc.name, gc.totalGCCount, gc.maxDeltaGCCount, gc.minDeltaGCCount, 311 | String.format("%,.3fs", (float) gc.totalGCTime / 1000), 312 | String.format("%,.3fs", (float) gc.maxDeltaGCTime / 1000), 313 | String.format("%,.3fs", (float) gc.minDeltaGCTime / 1000))); 314 | 315 | } 316 | return sb.toString(); 317 | } 318 | } 319 | 320 | private class ProcessMemoryStatus { 321 | final Map memoryStatusMap = new HashMap(); 322 | 323 | @Override 324 | public String toString() { 325 | StringBuilder sb = new StringBuilder(); 326 | sb.append("\t"); 327 | sb.append(String.format("%-30s | %-30s | %-30s \n", "MEMORY_NAME", "allocation_size", "init_size")); 328 | for (MemoryStatus ms : memoryStatusMap.values()) { 329 | sb.append("\t"); 330 | sb.append(String.format("%-30s | %-30s | %-30s \n", 331 | ms.name, String.format("%,.2fMB", (float) ms.maxSize / MB), String.format("%,.2fMB", (float) ms.initSize / MB))); 332 | } 333 | return sb.toString(); 334 | } 335 | 336 | public String getDeltaString() { 337 | StringBuilder sb = new StringBuilder(); 338 | sb.append("\n\t [delta memory info] => \n"); 339 | sb.append("\t\t "); 340 | sb.append(String.format("%-30s | %-30s | %-30s | %-30s | %-30s \n", "NAME", "used_size", "used_percent", "max_used_size", "max_percent")); 341 | for (MemoryStatus ms : memoryStatusMap.values()) { 342 | sb.append("\t\t "); 343 | sb.append(String.format("%-30s | %-30s | %-30s | %-30s | %-30s \n", 344 | ms.name, String.format("%,.2f", (float) ms.usedSize / MB) + "MB", 345 | String.format("%,.2f", (float) ms.percent) + "%", 346 | String.format("%,.2f", (float) ms.maxUsedSize / MB) + "MB", 347 | String.format("%,.2f", (float) ms.maxpercent) + "%")); 348 | 349 | } 350 | return sb.toString(); 351 | } 352 | } 353 | 354 | private class GCStatus { 355 | String name; 356 | long maxDeltaGCCount = -1; 357 | long minDeltaGCCount = -1; 358 | long curDeltaGCCount; 359 | long totalGCCount = 0; 360 | long maxDeltaGCTime = -1; 361 | long minDeltaGCTime = -1; 362 | long curDeltaGCTime; 363 | long totalGCTime = 0; 364 | 365 | public void setCurTotalGcCount(long curTotalGcCount) { 366 | this.curDeltaGCCount = curTotalGcCount - totalGCCount; 367 | this.totalGCCount = curTotalGcCount; 368 | 369 | if (maxDeltaGCCount < curDeltaGCCount) { 370 | maxDeltaGCCount = curDeltaGCCount; 371 | } 372 | 373 | if (minDeltaGCCount == -1 || minDeltaGCCount > curDeltaGCCount) { 374 | minDeltaGCCount = curDeltaGCCount; 375 | } 376 | } 377 | 378 | public void setCurTotalGcTime(long curTotalGcTime) { 379 | this.curDeltaGCTime = curTotalGcTime - totalGCTime; 380 | this.totalGCTime = curTotalGcTime; 381 | 382 | if (maxDeltaGCTime < curDeltaGCTime) { 383 | maxDeltaGCTime = curDeltaGCTime; 384 | } 385 | 386 | if (minDeltaGCTime == -1 || minDeltaGCTime > curDeltaGCTime) { 387 | minDeltaGCTime = curDeltaGCTime; 388 | } 389 | } 390 | } 391 | 392 | private class MemoryStatus { 393 | String name; 394 | long initSize; 395 | long maxSize; 396 | long commitedSize; 397 | long usedSize; 398 | float percent; 399 | long maxUsedSize = -1; 400 | float maxpercent = 0; 401 | 402 | void setMaxMinUsedSize(long curUsedSize) { 403 | if (maxUsedSize < curUsedSize) { 404 | maxUsedSize = curUsedSize; 405 | } 406 | this.usedSize = curUsedSize; 407 | } 408 | 409 | void setMaxMinPercent(float curPercent) { 410 | if (maxpercent < curPercent) { 411 | maxpercent = curPercent; 412 | } 413 | this.percent = curPercent; 414 | } 415 | } 416 | 417 | } 418 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/tree/BinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.tree; 2 | 3 | import com.xjbg.java.sdk.util.CollectionUtil; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | 12 | /** 13 | * @author kesc 14 | * @since 2019/6/25 15 | */ 16 | @EqualsAndHashCode(callSuper = true) 17 | @Getter 18 | @Setter 19 | public class BinaryTree extends DefaultTree { 20 | private T value; 21 | 22 | private List> children; 23 | 24 | public BinaryTree() { 25 | } 26 | 27 | public BinaryTree(T value) { 28 | this.value = value; 29 | } 30 | 31 | @Override 32 | public boolean isLeaf() { 33 | return CollectionUtil.isEmpty(children); 34 | } 35 | 36 | @Override 37 | public void setChildren(List> children) { 38 | if (CollectionUtil.isNotEmpty(children) && children.size() > 2) { 39 | throw new IllegalArgumentException("binary tree's children can't more than 2"); 40 | } 41 | this.children = children; 42 | } 43 | 44 | public List preOrder() { 45 | List result = new ArrayList<>(); 46 | preOrder(result, this); 47 | return result; 48 | } 49 | 50 | private void preOrder(List result, Tree tTree) { 51 | result.add(tTree.getValue()); 52 | List> children = tTree.getChildren(); 53 | if (!CollectionUtil.isEmpty(children)) { 54 | for (Tree child : children) { 55 | preOrder(result, child); 56 | } 57 | } 58 | } 59 | 60 | public List postOrder() { 61 | List result = new ArrayList<>(); 62 | postOrder(result, this); 63 | return result; 64 | } 65 | 66 | private void postOrder(List result, Tree tTree) { 67 | List> children = tTree.getChildren(); 68 | if (!CollectionUtil.isEmpty(children)) { 69 | for (Tree child : children) { 70 | postOrder(result, child); 71 | } 72 | } 73 | result.add(tTree.getValue()); 74 | } 75 | 76 | public List midOrder() { 77 | List result = new ArrayList<>(); 78 | midOrder(result, this); 79 | return result; 80 | } 81 | 82 | private void midOrder(List result, Tree tTree) { 83 | List> children = tTree.getChildren(); 84 | if (CollectionUtil.isNotEmpty(children)) { 85 | midOrder(result, children.get(0)); 86 | } 87 | result.add(tTree.getValue()); 88 | if (CollectionUtil.isNotEmpty(children) && children.size() == 2) { 89 | midOrder(result, children.get(1)); 90 | } 91 | } 92 | 93 | public static void main(String[] args) { 94 | BinaryTree tree = new BinaryTree<>("0"); 95 | BinaryTree tree1 = new BinaryTree<>("4"); 96 | tree1.setChildren(Arrays.asList(new BinaryTree<>("7"), new BinaryTree<>("8"))); 97 | tree.setChildren(Arrays.asList(new BinaryTree<>("1"), tree1)); 98 | for (String s : tree.iterate()) { 99 | System.out.println(s); 100 | } 101 | System.out.println("---------"); 102 | for (String s : tree.preOrder()) { 103 | System.out.println(s); 104 | } 105 | System.out.println("---------"); 106 | for (String s : tree.midOrder()) { 107 | System.out.println(s); 108 | } 109 | System.out.println("---------"); 110 | for (String s : tree.postOrder()) { 111 | System.out.println(s); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/tree/DefaultTree.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.tree; 2 | 3 | import com.xjbg.java.sdk.util.CollectionUtil; 4 | import lombok.Data; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | /** 11 | * @author: huangpp02 12 | * @time: 2018-02-26 11:24 13 | */ 14 | @Data 15 | public class DefaultTree implements Tree { 16 | private T value; 17 | 18 | private List> children; 19 | 20 | public DefaultTree() { 21 | } 22 | 23 | public DefaultTree(T value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public boolean isLeaf() { 29 | return CollectionUtil.isEmpty(children); 30 | } 31 | 32 | /** 33 | * 先根后依次遍历每棵子树 34 | * 35 | * @return 36 | */ 37 | public List iterate() { 38 | List result = new ArrayList<>(); 39 | iterate(this, result); 40 | return result; 41 | } 42 | 43 | private void iterate(Tree tTree, List result) { 44 | result.add(tTree.getValue()); 45 | List> children = tTree.getChildren(); 46 | if (!CollectionUtil.isEmpty(children)) { 47 | for (Tree child : children) { 48 | iterate(child, result); 49 | } 50 | } 51 | } 52 | 53 | public static void main(String[] args) { 54 | DefaultTree tree = new DefaultTree<>("0"); 55 | DefaultTree tree1 = new DefaultTree<>("4"); 56 | tree1.setChildren(Arrays.asList(new DefaultTree<>("7"), new DefaultTree<>("8"), new DefaultTree<>("5"))); 57 | tree.setChildren(Arrays.asList(new DefaultTree<>("1"), tree1, new DefaultTree<>("3"))); 58 | for (String s : tree.iterate()) { 59 | System.out.println(s); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/tree/Tree.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.tree; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author: huangpp02 7 | * @time: 2018-02-26 11:18 8 | */ 9 | public interface Tree { 10 | /** 11 | * 自身属性 12 | * 13 | * @return 14 | */ 15 | T getValue(); 16 | 17 | /** 18 | * 子属性 19 | * 20 | * @return 21 | */ 22 | List> getChildren(); 23 | 24 | /** 25 | * 是否是叶子节点 26 | * @return 27 | */ 28 | boolean isLeaf(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/tree/TreeUtils.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.tree; 2 | 3 | 4 | import com.xjbg.java.sdk.util.CollectionUtil; 5 | 6 | import java.util.List; 7 | import java.util.function.BiFunction; 8 | import java.util.function.Consumer; 9 | import java.util.function.Function; 10 | import java.util.function.Predicate; 11 | 12 | /** 13 | * @author: huangpp02 14 | * @time: 2018-02-26 11:21 15 | */ 16 | public class TreeUtils { 17 | /** 18 | * @param initValue 树初始化节点 19 | * @param childrenFunc 根据自身获取子节点列表 20 | * @param tree对应的value值 21 | * @return 树 22 | */ 23 | public static Tree buildTree(T initValue, Function> childrenFunc) { 24 | DefaultTree result = new DefaultTree<>(); 25 | result.setValue(initValue); 26 | List children = childrenFunc.apply(initValue); 27 | if (!CollectionUtil.isEmpty(children)) { 28 | result.setChildren(CollectionUtil.map(children, child -> buildTree(child, childrenFunc))); 29 | } 30 | return result; 31 | } 32 | 33 | public static Tree transform(Tree from, Function func) { 34 | DefaultTree result = new DefaultTree<>(); 35 | if (from == null) { 36 | return result; 37 | } 38 | result.setValue(func.apply(from.getValue())); 39 | List> children = from.getChildren(); 40 | if (!CollectionUtil.isEmpty(children)) { 41 | result.setChildren(CollectionUtil.map(children, child -> transform(child, func))); 42 | } 43 | return result; 44 | } 45 | 46 | public static R reduce(Tree tree, R initValue, BiFunction resultBuilder) { 47 | if (tree == null) { 48 | return initValue; 49 | } 50 | R result = initValue; 51 | result = resultBuilder.apply(tree.getValue(), result); 52 | if (!tree.isLeaf()) { 53 | for (Tree child : tree.getChildren()) { 54 | result = reduce(child, result, resultBuilder); 55 | } 56 | } 57 | return result; 58 | } 59 | 60 | /** 61 | * 查找子树 62 | */ 63 | public static Tree findChildTree(Tree tree, Predicate predicate) { 64 | T value = tree.getValue(); 65 | if (predicate.test(value)) { 66 | return tree; 67 | } 68 | List> children = tree.getChildren(); 69 | if (!CollectionUtil.isEmpty(children)) { 70 | for (Tree child : children) { 71 | return findChildTree(child, predicate); 72 | } 73 | } 74 | return null; 75 | } 76 | 77 | public static void forEach(Tree tree, Consumer> treeConsumer) { 78 | if (tree == null) { 79 | return; 80 | } 81 | if (!tree.isLeaf()) { 82 | CollectionUtil.forEach(tree.getChildren(), child -> forEach(child, treeConsumer)); 83 | } 84 | treeConsumer.accept(tree); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/Base64Util.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import java.nio.charset.Charset; 4 | import java.nio.charset.StandardCharsets; 5 | import java.util.Base64; 6 | 7 | /** 8 | * @author kesc 9 | * @since 2019/6/24 10 | */ 11 | public final class Base64Util { 12 | private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; 13 | 14 | public static byte[] encode(byte[] src) { 15 | return src == null || src.length == 0 ? src : Base64.getEncoder().encode(src); 16 | } 17 | 18 | public static String encodeToString(byte[] src) { 19 | return encodeToString(src, DEFAULT_CHARSET); 20 | } 21 | 22 | public static String encodeToString(byte[] src, Charset charset) { 23 | if (src == null) { 24 | return null; 25 | } 26 | if (src.length == 0) { 27 | return ""; 28 | } 29 | return charset == null ? new String(encode(src)) : new String(encode(src), charset); 30 | } 31 | 32 | public static byte[] decode(byte[] src) { 33 | return src == null || src.length == 0 ? src : Base64.getDecoder().decode(src); 34 | } 35 | 36 | public static byte[] decodeFromString(String src) { 37 | return decodeFromString(src, DEFAULT_CHARSET); 38 | } 39 | 40 | public static byte[] decodeFromString(String src, Charset charset) { 41 | if (src == null) { 42 | return null; 43 | } 44 | if (src.isEmpty()) { 45 | return new byte[0]; 46 | } 47 | return charset == null ? decode(src.getBytes()) : decode(src.getBytes(charset)); 48 | } 49 | 50 | public static byte[] encodeUrlSafe(byte[] src) { 51 | return src == null || src.length == 0 ? src : Base64.getUrlEncoder().encode(src); 52 | } 53 | 54 | public static byte[] decodeUrlSafe(byte[] src) { 55 | return src == null || src.length == 0 ? src : Base64.getUrlDecoder().decode(src); 56 | } 57 | 58 | public static String encodeToUrlSafeString(byte[] src) { 59 | return encodeToUrlSafeString(src, DEFAULT_CHARSET); 60 | } 61 | 62 | public static String encodeToUrlSafeString(byte[] src, Charset charset) { 63 | if (charset == null) { 64 | return new String(encodeUrlSafe(src)); 65 | } 66 | return new String(encodeUrlSafe(src), charset); 67 | } 68 | 69 | public static byte[] decodeFromUrlSafeString(String src) { 70 | if (src == null) { 71 | return null; 72 | } 73 | return decodeUrlSafe(src.getBytes(DEFAULT_CHARSET)); 74 | } 75 | 76 | public static byte[] decodeFromUrlSafeString(String src, Charset charset) { 77 | if (src == null) { 78 | return null; 79 | } 80 | if (charset == null) { 81 | return decodeUrlSafe(src.getBytes()); 82 | } 83 | return decodeUrlSafe(src.getBytes(charset)); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/BeanUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.BeanUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | /** 11 | * @author kesc 12 | * @since 2018/1/17 13 | */ 14 | @Slf4j 15 | public final class BeanUtil extends BeanUtils { 16 | 17 | public static List convert(List source, Class clazz) { 18 | if (CollectionUtil.isEmpty(source)) { 19 | return Collections.emptyList(); 20 | } 21 | List result = new ArrayList<>(); 22 | source.forEach(x -> { 23 | R instance = instantiateClass(clazz); 24 | BeanUtils.copyProperties(x, instance); 25 | result.add(instance); 26 | }); 27 | return result; 28 | } 29 | 30 | public static R convert(S source, Class clazz) { 31 | R instance = instantiateClass(clazz); 32 | if (source == null) { 33 | return instance; 34 | } 35 | BeanUtils.copyProperties(source, instance); 36 | return instance; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/CollectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import org.apache.commons.collections.CollectionUtils; 4 | 5 | import java.util.*; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | import java.util.function.BiFunction; 8 | import java.util.function.Consumer; 9 | import java.util.function.Function; 10 | import java.util.function.Predicate; 11 | 12 | /** 13 | * @author kesc 14 | * @since 2018/1/27 15 | */ 16 | 17 | public final class CollectionUtil extends CollectionUtils { 18 | 19 | /** 20 | * Return {@code true} if the supplied Map is {@code null} or empty. 21 | * Otherwise, return {@code false}. 22 | * 23 | * @param map the Map to check 24 | * @return whether the given Map is empty 25 | */ 26 | public static boolean isEmpty(Map map) { 27 | return (map == null || map.isEmpty()); 28 | } 29 | 30 | public static boolean isNotEmpty(Map map) { 31 | return !isEmpty(map); 32 | } 33 | 34 | public static boolean isEmpty(T[] array) { 35 | return (array == null || array.length == 0); 36 | } 37 | 38 | public static boolean isNotEmpty(T[] array) { 39 | return !isEmpty(array); 40 | } 41 | 42 | /** 43 | * Merge the given Properties instance into the given Map, 44 | * copying all properties (key-value pairs) over. 45 | *

Uses {@code Properties.propertyNames()} to even catch 46 | * default properties linked into the original Properties instance. 47 | * 48 | * @param props the Properties instance to merge (may be {@code null}) 49 | * @param map the target Map to merge the properties into 50 | */ 51 | @SuppressWarnings("unchecked") 52 | public static void mergePropertiesIntoMap(Properties props, Map map) { 53 | if (map == null) { 54 | throw new IllegalArgumentException("Map must not be null"); 55 | } 56 | if (props != null) { 57 | for (Enumeration en = props.propertyNames(); en.hasMoreElements(); ) { 58 | String key = (String) en.nextElement(); 59 | Object value = props.getProperty(key); 60 | if (value == null) { 61 | // Potentially a non-String value... 62 | value = props.get(key); 63 | } 64 | map.put((K) key, (V) value); 65 | } 66 | } 67 | } 68 | 69 | /** 70 | * Check whether the given Collection contains the given element instance. 71 | *

Enforces the given instance to be present, rather than returning 72 | * {@code true} for an equal element as well. 73 | * 74 | * @param collection the Collection to check 75 | * @param element the element to look for 76 | * @return {@code true} if found, {@code false} else 77 | */ 78 | public static boolean containsInstance(Collection collection, Object element) { 79 | if (collection != null) { 80 | for (Object candidate : collection) { 81 | if (candidate == element) { 82 | return true; 83 | } 84 | } 85 | } 86 | return false; 87 | } 88 | 89 | /** 90 | * Return the first element in '{@code candidates}' that is contained in 91 | * '{@code source}'. If no element in '{@code candidates}' is present in 92 | * '{@code source}' returns {@code null}. Iteration order is 93 | * {@link Collection} implementation specific. 94 | * 95 | * @param source the source Collection 96 | * @param candidates the candidates to likeSearch for 97 | * @return the first present object, or {@code null} if not found 98 | */ 99 | @SuppressWarnings("unchecked") 100 | public static E findFirstMatch(Collection source, Collection candidates) { 101 | if (isEmpty(source) || isEmpty(candidates)) { 102 | return null; 103 | } 104 | for (Object candidate : candidates) { 105 | if (source.contains(candidate)) { 106 | return (E) candidate; 107 | } 108 | } 109 | return null; 110 | } 111 | 112 | /** 113 | * Find a single value of the given type in the given Collection. 114 | * 115 | * @param collection the Collection to likeSearch 116 | * @param type the type to look for 117 | * @return a value of the given type found if there is a clear match, 118 | * or {@code null} if none or more than one such value found 119 | */ 120 | @SuppressWarnings("unchecked") 121 | public static T findValueOfType(Collection collection, Class type) { 122 | if (isEmpty(collection)) { 123 | return null; 124 | } 125 | T value = null; 126 | for (Object element : collection) { 127 | if (type == null || type.isInstance(element)) { 128 | if (value != null) { 129 | // More than one value found... no clear single value. 130 | return null; 131 | } 132 | value = (T) element; 133 | } 134 | } 135 | return value; 136 | } 137 | 138 | /** 139 | * Find a single value of one of the given types in the given Collection: 140 | * searching the Collection for a value of the first type, then 141 | * searching for a value of the second type, etc. 142 | * 143 | * @param collection the collection to likeSearch 144 | * @param types the types to look for, in prioritized order 145 | * @return a value of one of the given types found if there is a clear match, 146 | * or {@code null} if none or more than one such value found 147 | */ 148 | public static Object findValueOfType(Collection collection, Class[] types) { 149 | if (isEmpty(collection) || isEmpty(types)) { 150 | return null; 151 | } 152 | for (Class type : types) { 153 | Object value = findValueOfType(collection, type); 154 | if (value != null) { 155 | return value; 156 | } 157 | } 158 | return null; 159 | } 160 | 161 | /** 162 | * Determine whether the given Collection only contains a single unique object. 163 | * 164 | * @param collection the Collection to check 165 | * @return {@code true} if the collection contains a single reference or 166 | * multiple references to the same instance, {@code false} else 167 | */ 168 | public static boolean hasUniqueObject(Collection collection) { 169 | if (isEmpty(collection)) { 170 | return false; 171 | } 172 | boolean hasCandidate = false; 173 | Object candidate = null; 174 | for (Object elem : collection) { 175 | if (!hasCandidate) { 176 | hasCandidate = true; 177 | candidate = elem; 178 | } else if (candidate != elem) { 179 | return false; 180 | } 181 | } 182 | return true; 183 | } 184 | 185 | /** 186 | * Find the common element type of the given Collection, if any. 187 | * 188 | * @param collection the Collection to check 189 | * @return the common element type, or {@code null} if no clear 190 | * common type has been found (or the collection was empty) 191 | */ 192 | public static Class findCommonElementType(Collection collection) { 193 | if (isEmpty(collection)) { 194 | return null; 195 | } 196 | Class candidate = null; 197 | for (Object val : collection) { 198 | if (val != null) { 199 | if (candidate == null) { 200 | candidate = val.getClass(); 201 | } else if (candidate != val.getClass()) { 202 | return null; 203 | } 204 | } 205 | } 206 | return candidate; 207 | } 208 | 209 | /** 210 | * Marshal the elements from the given enumeration into an array of the given type. 211 | * Enumeration elements must be assignable to the type of the given array. The array 212 | * returned will be a different instance than the array given. 213 | */ 214 | public static A[] toArray(Enumeration enumeration, A[] array) { 215 | ArrayList elements = new ArrayList<>(); 216 | while (enumeration.hasMoreElements()) { 217 | elements.add(enumeration.nextElement()); 218 | } 219 | return elements.toArray(array); 220 | } 221 | 222 | public static Map toMap(Collection elements, Function keyBuilder) { 223 | return toMap(elements, keyBuilder, Function.identity()); 224 | } 225 | 226 | public static Map toMap(Collection elements, Function keyBuilder, Function valueFunc) { 227 | if (isEmpty(elements) || keyBuilder == null || valueFunc == null) { 228 | return Collections.emptyMap(); 229 | } 230 | Map result = new HashMap<>(elements.size() * 3 / 2); 231 | for (E element : elements) { 232 | result.put(keyBuilder.apply(element), valueFunc.apply(element)); 233 | } 234 | return result; 235 | } 236 | 237 | public static Map> toMapList(Collection elements, Function keyFunc) { 238 | return toMapList(elements, keyFunc, Function.identity()); 239 | } 240 | 241 | public static Map> toMapList(Collection elements, Function keyFunc, Function valueFunc) { 242 | if (isEmpty(elements) || keyFunc == null || valueFunc == null) { 243 | return Collections.emptyMap(); 244 | } 245 | Map> result = new HashMap<>(elements.size() * 3 / 2); 246 | for (E element : elements) { 247 | K key = keyFunc.apply(element); 248 | List values = result.computeIfAbsent(key, k -> new ArrayList<>()); 249 | values.add(valueFunc.apply(element)); 250 | } 251 | return result; 252 | } 253 | 254 | public static void forEach(Collection collection, Consumer action) { 255 | if (isEmpty(collection) || action == null) { 256 | return; 257 | } 258 | collection.forEach(action); 259 | } 260 | 261 | public static List filter(Collection source, Predicate predicate) { 262 | if (isEmpty(source) || predicate == null) { 263 | return Collections.emptyList(); 264 | } 265 | List result = new ArrayList<>(); 266 | for (E element : source) { 267 | if (predicate.test(element)) { 268 | result.add(element); 269 | } 270 | } 271 | return result; 272 | } 273 | 274 | 275 | public static List selectList(Collection source, Function func) { 276 | return selectList(source, func, true); 277 | } 278 | 279 | public static List selectNotNullList(Collection source, Function func) { 280 | return selectList(source, func, false); 281 | } 282 | 283 | public static List selectList(Collection source, Function func, boolean isAllowNullValue) { 284 | if (isEmpty(source)) { 285 | return Collections.emptyList(); 286 | } 287 | List resultList = new ArrayList<>(source.size()); 288 | for (F f : source) { 289 | T t = func.apply(f); 290 | if (t != null || isAllowNullValue) { 291 | resultList.add(t); 292 | } 293 | } 294 | return resultList; 295 | } 296 | 297 | public static List selectListWithIndex(Collection source, BiFunction func) { 298 | if (isEmpty(source)) { 299 | return Collections.emptyList(); 300 | } 301 | List resultList = new ArrayList<>(source.size()); 302 | AtomicInteger index = new AtomicInteger(); 303 | for (F f : source) { 304 | resultList.add(func.apply(f, index.getAndIncrement())); 305 | } 306 | return resultList; 307 | } 308 | 309 | public static R reduce(Collection elements, R initValue, BiFunction reduceFunc) { 310 | if (isEmpty(elements)) { 311 | return initValue; 312 | } 313 | R result = initValue; 314 | for (E element : elements) { 315 | if (null != element) { 316 | result = reduceFunc.apply(result, element); 317 | } 318 | } 319 | return result; 320 | } 321 | 322 | public static Map groupBy(Collection elements, Function keyFunc, BiFunction, R> resultBuilder) { 323 | if (isEmpty(elements) || keyFunc == null || resultBuilder == null) { 324 | return Collections.emptyMap(); 325 | } 326 | Map> map = toMapList(elements, keyFunc, Function.identity()); 327 | 328 | Map resultMap = new HashMap<>((int) (elements.size() * 1.75) + 1); 329 | for (Map.Entry> entry : map.entrySet()) { 330 | resultMap.put(entry.getKey(), resultBuilder.apply(entry.getKey(), entry.getValue())); 331 | } 332 | return resultMap; 333 | } 334 | 335 | public static List map(Collection source, Function func) { 336 | if (isEmpty(source)) { 337 | return Collections.emptyList(); 338 | } 339 | List resultList = new ArrayList<>(source.size()); 340 | for (F f : source) { 341 | T t = func.apply(f); 342 | resultList.add(t); 343 | } 344 | return resultList; 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import com.xjbg.java.sdk.enums.DatePatternEnum; 4 | import org.joda.time.*; 5 | import org.joda.time.format.DateTimeFormat; 6 | import org.joda.time.format.DateTimeFormatter; 7 | 8 | import java.text.Format; 9 | import java.text.SimpleDateFormat; 10 | import java.util.*; 11 | 12 | /** 13 | * @author kesc 14 | * @since 2019/6/24 15 | */ 16 | public final class DateUtil { 17 | private static final int[] CHINESE_WEEK = new int[]{0, 7, 1, 2, 3, 4, 5, 6}; 18 | 19 | 20 | public static long getCurrentTimestamp() { 21 | return System.currentTimeMillis(); 22 | } 23 | 24 | public static Date parseDateTime(String dateTime) { 25 | return parse(dateTime, DatePatternEnum.YYYYMMDDHHMMSS_BYSEP); 26 | } 27 | 28 | public static Date parseDate(String date) { 29 | return parse(date, DatePatternEnum.YYYYMMDD_BYSEP); 30 | } 31 | 32 | public static Date parseDateTime(String dateTime, TimeZone timeZone) { 33 | return parse(dateTime, DatePatternEnum.YYYYMMDDHHMMSS_BYSEP.getFormat(), timeZone); 34 | } 35 | 36 | public static Date parseDate(String date, TimeZone timeZone) { 37 | return parse(date, DatePatternEnum.YYYYMMDD_BYSEP.getFormat(), timeZone); 38 | } 39 | 40 | public static Date parse(String date, DatePatternEnum pattern) { 41 | return parse(date, pattern.getFormat()); 42 | } 43 | 44 | public static Date parse(String date, String pattern) { 45 | return parse(date, pattern, TimeZone.getDefault()); 46 | } 47 | 48 | public static Date parse(String date, DatePatternEnum pattern, TimeZone timeZone) { 49 | return parse(date, pattern.getFormat(), timeZone); 50 | } 51 | 52 | public static Date parse(String date, String pattern, TimeZone timeZone) { 53 | DateTimeFormatter dateFormatter = DateTimeFormat.forPattern(pattern); 54 | DateTimeZone dateTimeZone = timeZone == null ? DateTimeZone.getDefault() : DateTimeZone.forTimeZone(timeZone); 55 | return dateFormatter.withZone(dateTimeZone).parseDateTime(date).toDate(); 56 | } 57 | 58 | public static String format(Date date, String pattern) { 59 | return format(date, pattern, TimeZone.getDefault()); 60 | } 61 | 62 | public static String format(Date date, DatePatternEnum datePatternEnum) { 63 | return format(date, datePatternEnum.getFormat()); 64 | } 65 | 66 | public static String formatDateTime(Date date) { 67 | return format(date, DatePatternEnum.YYYYMMDDHHMMSS_BYSEP); 68 | } 69 | 70 | public static String formatDate(Date date) { 71 | return format(date, DatePatternEnum.YYYYMMDD_BYSEP); 72 | } 73 | 74 | public static String formatDateTime(Date date, TimeZone timeZone) { 75 | return format(date, DatePatternEnum.YYYYMMDDHHMMSS_BYSEP.getFormat(), timeZone); 76 | } 77 | 78 | public static String formatDate(Date date, TimeZone timeZone) { 79 | return format(date, DatePatternEnum.YYYYMMDD_BYSEP.getFormat(), timeZone); 80 | } 81 | 82 | public static String format(Date date, DatePatternEnum pattern, TimeZone timeZone) { 83 | return format(date, pattern.getFormat(), timeZone); 84 | } 85 | 86 | public static String format(Date date, String pattern, TimeZone timeZone) { 87 | DateTimeZone dateTimeZone = timeZone == null ? DateTimeZone.getDefault() : DateTimeZone.forTimeZone(timeZone); 88 | DateTime dateTime = new DateTime(date, dateTimeZone); 89 | return dateTime.toString(pattern); 90 | } 91 | 92 | public static Date getMinDate(Date date) { 93 | if (date == null) { 94 | return null; 95 | } else { 96 | DateTime dateTime = new DateTime(date); 97 | return dateTime.withTimeAtStartOfDay().toDate(); 98 | } 99 | } 100 | 101 | public static Date getMaxDate(Date date) { 102 | if (date == null) { 103 | return null; 104 | } else { 105 | DateTime dateTime = new DateTime(date); 106 | return dateTime.millisOfDay().withMaximumValue().toDate(); 107 | } 108 | } 109 | 110 | public static int betweenOfHours(Date firstDate, Date nextDate) { 111 | if (firstDate != null && nextDate != null) { 112 | LocalDateTime fist = new LocalDateTime(firstDate); 113 | LocalDateTime next = new LocalDateTime(nextDate); 114 | return Hours.hoursBetween(next, fist).getHours(); 115 | } else { 116 | return 0; 117 | } 118 | } 119 | 120 | public static boolean inBetween(Date date, Date start, Date end) { 121 | if (date != null && start != null && end != null) { 122 | long st = start.getTime(); 123 | long ed = end.getTime(); 124 | long cur = date.getTime(); 125 | return cur < ed && cur > st; 126 | } else { 127 | return false; 128 | } 129 | } 130 | 131 | public static boolean before(Date start, Date end) { 132 | DateTime startTime = new DateTime(start); 133 | DateTime endTime = new DateTime(end); 134 | return startTime.isBefore(endTime); 135 | } 136 | 137 | public static boolean after(Date start, Date end) { 138 | return !before(start, end); 139 | } 140 | 141 | public static String getMonthWithMaxDate(Date date) { 142 | DateTime dateTime = new DateTime(date); 143 | return dateTime.dayOfMonth().withMaximumValue().toString(DatePatternEnum.YYYYMMDD_BYSEP.getFormat()); 144 | } 145 | 146 | public static String getYearWithMaxDate(Date date) { 147 | DateTime dateTime = new DateTime(date); 148 | return dateTime.monthOfYear().withMaximumValue().dayOfMonth().withMaximumValue().toString(DatePatternEnum.YYYYMMDD_BYSEP.getFormat()); 149 | } 150 | 151 | public static String getMonthWithMinDate(Date date) { 152 | DateTime dateTime = new DateTime(date); 153 | return dateTime.dayOfMonth().withMinimumValue().toString(DatePatternEnum.YYYYMMDD_BYSEP.getFormat()); 154 | } 155 | 156 | public static String getYearWithMinDate(Date date) { 157 | DateTime dateTime = new DateTime(date); 158 | return dateTime.monthOfYear().withMinimumValue().toString(DatePatternEnum.YYYYMMDD_BYSEP.getFormat()); 159 | } 160 | 161 | 162 | public static int betweenOfDays(Date firstDate, Date nextDate) { 163 | if (firstDate != null && nextDate != null) { 164 | LocalDateTime fist = new LocalDateTime(firstDate); 165 | LocalDateTime next = new LocalDateTime(nextDate); 166 | return Days.daysBetween(next, fist).getDays() + 1; 167 | } else { 168 | return 0; 169 | } 170 | } 171 | 172 | public static Date addMilliSecond(Date date, int amount) { 173 | return (new DateTime(date)).plusMillis(amount).toDate(); 174 | } 175 | 176 | public static Date addSecond(Date date, int amount) { 177 | return (new DateTime(date)).plusSeconds(amount).toDate(); 178 | } 179 | 180 | public static Date addMinute(Date date, int amount) { 181 | return (new DateTime(date)).plusMinutes(amount).toDate(); 182 | } 183 | 184 | public static Date addHour(Date date, int amount) { 185 | return (new DateTime(date)).plusHours(amount).toDate(); 186 | } 187 | 188 | public static Date addDay(Date date, int amount) { 189 | return (new DateTime(date)).plusDays(amount).toDate(); 190 | } 191 | 192 | public static Date addWeek(Date date, int amount) { 193 | return (new DateTime(date)).plusWeeks(amount).toDate(); 194 | } 195 | 196 | 197 | public static Date addMonth(Date date, int amount) { 198 | return (new DateTime(date)).plusMonths(amount).toDate(); 199 | } 200 | 201 | public static Date addYear(Date date, int amount) { 202 | return (new DateTime(date)).plusYears(amount).toDate(); 203 | } 204 | 205 | public static Date minusMilliSecond(Date date, int amount) { 206 | return (new DateTime(date)).minusMillis(amount).toDate(); 207 | } 208 | 209 | public static Date minusSecond(Date date, int amount) { 210 | return (new DateTime(date)).minusSeconds(amount).toDate(); 211 | } 212 | 213 | public static Date minusMinute(Date date, int amount) { 214 | return (new DateTime(date)).minusMinutes(amount).toDate(); 215 | } 216 | 217 | public static Date minusHour(Date date, int amount) { 218 | return (new DateTime(date)).minusHours(amount).toDate(); 219 | } 220 | 221 | public static Date minusDay(Date date, int amount) { 222 | return (new DateTime(date)).minusDays(amount).toDate(); 223 | } 224 | 225 | public static Date minusWeek(Date date, int amount) { 226 | return (new DateTime(date)).minusWeeks(amount).toDate(); 227 | } 228 | 229 | 230 | public static Date minusMonth(Date date, int amount) { 231 | return (new DateTime(date)).minusMonths(amount).toDate(); 232 | } 233 | 234 | public static Date minusYear(Date date, int amount) { 235 | return (new DateTime(date)).minusYears(amount).toDate(); 236 | } 237 | 238 | 239 | public static Date now() { 240 | return new Date(getCurrentTimestamp()); 241 | } 242 | 243 | public static long getDistanceMills(Date one, Date two) { 244 | long time1 = one.getTime(); 245 | long time2 = two.getTime(); 246 | long diff; 247 | if (time1 < time2) { 248 | diff = time2 - time1; 249 | } else { 250 | diff = time1 - time2; 251 | } 252 | 253 | return diff; 254 | } 255 | 256 | public static Date changeDate(Date date, DatePatternEnum from, DatePatternEnum to) { 257 | if (null == date) { 258 | return null; 259 | } else { 260 | DateTimeFormatter dateFormatter = DateTimeFormat.forPattern(to.getFormat()); 261 | return dateFormatter.parseDateTime((new DateTime(date)).toString(from.getFormat())).toDate(); 262 | } 263 | } 264 | 265 | public static int getMinutesToEndDay(Date date) { 266 | DateTime startDate = new DateTime(date); 267 | DateTime endDate = (new DateTime(startDate.getYear(), startDate.getMonthOfYear(), startDate.getDayOfMonth(), 23, 59, 59, 59)).plusSeconds(1); 268 | Minutes minutes = Minutes.minutesBetween(startDate, endDate); 269 | return minutes.getMinutes(); 270 | } 271 | 272 | /*** 273 | * 获取时间在月份的天数 274 | * @param date 275 | * @return 276 | */ 277 | public static int getDayOfMonth(Date date) { 278 | DateTime dateTime = new DateTime(date); 279 | return dateTime.getDayOfMonth(); 280 | } 281 | 282 | /*** 283 | * 月份的天数 284 | * @param date 285 | * @return 286 | */ 287 | public static int daysOfMonth(Date date) { 288 | DateTime dateTime = new DateTime(date); 289 | return dateTime.dayOfMonth().getMaximumValue(); 290 | } 291 | 292 | /** 293 | * 去年的最后一天 294 | * 295 | * @param date 296 | * @return 297 | */ 298 | public static Date lastDayOfLastYear(Date date) { 299 | DateTime dateTime = new DateTime(date); 300 | DateTime lastYearDateTime = dateTime.minusYears(1); 301 | return lastYearDateTime.monthOfYear().withMaximumValue().dayOfMonth().withMaximumValue().toDate(); 302 | } 303 | 304 | /*** 305 | * 年的第一个天 306 | * @param date 307 | * @return 308 | */ 309 | public static Date firstDayOfYear(Date date) { 310 | DateTime dateTime = new DateTime(date); 311 | return dateTime.monthOfYear().withMinimumValue().dayOfMonth().withMinimumValue().toDate(); 312 | } 313 | 314 | /*** 315 | * 年的最后一个天 316 | * @param date 317 | * @return 318 | */ 319 | public static Date lastDayOfYear(Date date) { 320 | DateTime dateTime = new DateTime(date); 321 | return dateTime.monthOfYear().withMaximumValue().dayOfMonth().withMaximumValue().toDate(); 322 | } 323 | 324 | /** 325 | * 获取从传入日期间隔中包含一年中的周数 326 | */ 327 | public static List getBetweenWeeks(Date start, Date end) { 328 | if (end.before(start)) { 329 | return Collections.emptyList(); 330 | } 331 | List list = new ArrayList<>(); 332 | Format f = new SimpleDateFormat(DatePatternEnum.YYYYMMDD_BYSEP.getFormat()); 333 | while (f.format(start).compareTo(f.format(end)) <= 0) { 334 | list.add(getWeekOfYear(start)); 335 | start = DateUtil.addDay(start, 7); 336 | } 337 | return list; 338 | } 339 | 340 | public static String getWeekOfYear(Date date) { 341 | if (date == null) { 342 | return null; 343 | } 344 | DateTime dateTime = new DateTime(date); 345 | return dateTime.getYear() + StringUtil.MINUS + dateTime.getWeekOfWeekyear(); 346 | } 347 | 348 | /** 349 | * 获取从传入日期间隔中包含一年中的月份数 350 | */ 351 | public static List getBetweenMonth(Date start, Date end) { 352 | if (end.before(start)) { 353 | return Collections.emptyList(); 354 | } 355 | List list = new ArrayList<>(); 356 | Format f = new SimpleDateFormat(DatePatternEnum.YYYYMM_BYSEP.getFormat()); 357 | while (f.format(start).compareTo(f.format(end)) <= 0) { 358 | list.add(f.format(start)); 359 | start = DateUtil.addMonth(start, 1); 360 | } 361 | return list; 362 | } 363 | 364 | public static List getBetweenDates(Date start, Date end) { 365 | if (end.before(start)) { 366 | return Collections.emptyList(); 367 | } 368 | List result = new ArrayList<>(); 369 | Format f = new SimpleDateFormat(DatePatternEnum.YYYYMMDD_BYSEP.getFormat()); 370 | while (f.format(start).compareTo(f.format(end)) <= 0) { 371 | result.add(f.format(start)); 372 | start = DateUtil.addDay(start, 1); 373 | } 374 | return result; 375 | } 376 | 377 | public static List getBetweenHours(Date start, Date end) { 378 | if (end.before(start)) { 379 | return Collections.emptyList(); 380 | } 381 | List result = new ArrayList<>(); 382 | Format f = new SimpleDateFormat(DatePatternEnum.YYYYMMDDHH_BYSEP.getFormat()); 383 | while (f.format(start).compareTo(f.format(end)) <= 0) { 384 | result.add(f.format(start)); 385 | start = DateUtil.addHour(start, 1); 386 | } 387 | return result; 388 | } 389 | 390 | public static int getDayOfChineseWeek(Date date) { 391 | return CHINESE_WEEK[getDayOfWeek(date)]; 392 | } 393 | 394 | public static int getDayOfWeek(Date date) { 395 | return new DateTime(date).getDayOfWeek(); 396 | } 397 | } 398 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/ExceptionUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | import java.io.Writer; 6 | 7 | /** 8 | * @author kesc 9 | * @since 2023-04-23 16:44 10 | */ 11 | public class ExceptionUtil { 12 | 13 | public static String getTraceInfo(Throwable t) { 14 | if (t == null) { 15 | return null; 16 | } 17 | try (Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer)) { 18 | t.printStackTrace(printWriter); 19 | return writer.toString(); 20 | } catch (Exception e) { 21 | return t.getMessage(); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import com.xjbg.java.sdk.enums.Encoding; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.io.*; 7 | import java.net.URI; 8 | import java.net.URL; 9 | import java.nio.channels.Channels; 10 | import java.nio.channels.ReadableByteChannel; 11 | import java.nio.file.*; 12 | import java.util.ArrayList; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | /** 17 | * @author kesc 18 | * @date 2020-08-17 11:08 19 | */ 20 | @Slf4j 21 | public class FileUtil { 22 | 23 | public static boolean exist(String path) { 24 | return getFile(path).exists(); 25 | } 26 | 27 | public static boolean isFile(String path) { 28 | return getFile(path).isFile(); 29 | } 30 | 31 | public static boolean isDirectory(String path) { 32 | return getFile(path).isDirectory(); 33 | } 34 | 35 | public static boolean isAbsolute(String path) { 36 | return getFile(path).isAbsolute(); 37 | } 38 | 39 | public static boolean isHidden(String path) { 40 | return getFile(path).isHidden(); 41 | } 42 | 43 | public static Path getPath(String first, String... more) { 44 | return Paths.get(first, more); 45 | } 46 | 47 | public static File getFile(String first, String... more) { 48 | return getPath(first, more).toFile(); 49 | } 50 | 51 | public static URI getURI(String first, String... more) { 52 | return getPath(first, more).toUri(); 53 | } 54 | 55 | public static String getPathString(String first, String... more) { 56 | return Paths.get(first, more).toString(); 57 | } 58 | 59 | public static boolean createFile(File file) throws IOException { 60 | File parentFile = file.getParentFile(); 61 | if (parentFile != null) { 62 | parentFile.mkdirs(); 63 | } 64 | return file.createNewFile(); 65 | } 66 | 67 | public static boolean createFile(String path) throws IOException { 68 | return createFile(getFile(path)); 69 | } 70 | 71 | public static Path copy(File src, File target) throws IOException { 72 | return copy(src, target, StandardCopyOption.REPLACE_EXISTING); 73 | } 74 | 75 | public static Path copy(File src, File target, CopyOption... options) throws IOException { 76 | return Files.copy(src.toPath(), target.toPath(), options); 77 | } 78 | 79 | public static Path copy(String src, String target, CopyOption... options) throws IOException { 80 | return copy(getFile(src), getFile(target), options); 81 | } 82 | 83 | public static Path copy(String src, String target) throws IOException { 84 | return copy(src, target, StandardCopyOption.REPLACE_EXISTING); 85 | } 86 | 87 | public static Path move(File src, File target, CopyOption... options) throws IOException { 88 | return Files.move(src.toPath(), target.toPath(), options); 89 | } 90 | 91 | public static Path move(String src, String target, CopyOption... options) throws IOException { 92 | return move(getFile(src), getFile(target), options); 93 | } 94 | 95 | public static Path move(File src, File target) throws IOException { 96 | return move(src, target, StandardCopyOption.REPLACE_EXISTING); 97 | } 98 | 99 | public static Path move(String src, String target) throws IOException { 100 | return move(src, target, StandardCopyOption.REPLACE_EXISTING); 101 | } 102 | 103 | public static boolean delete(String path) { 104 | return getFile(path).delete(); 105 | } 106 | 107 | public static List listFiles(String path) throws FileNotFoundException { 108 | return listFiles(path, false); 109 | } 110 | 111 | public static List listFiles(File file) throws FileNotFoundException { 112 | return listFiles(file, false); 113 | } 114 | 115 | public static List listFiles(File file, boolean isRecursive) throws FileNotFoundException { 116 | if (!file.exists()) { 117 | throw new FileNotFoundException(String.format("%s not exist", file.getAbsolutePath())); 118 | } 119 | if (!file.isDirectory()) { 120 | return Collections.emptyList(); 121 | } 122 | List responses = new ArrayList<>(); 123 | listFiles(responses, file, isRecursive); 124 | return responses; 125 | } 126 | 127 | public static List listFiles(String path, boolean isRecursive) throws FileNotFoundException { 128 | return listFiles(getFile(path), isRecursive); 129 | } 130 | 131 | private static void listFiles(List responses, File file, boolean isRecursive) { 132 | File[] files = file.listFiles(); 133 | if (files == null || files.length == 0) { 134 | return; 135 | } 136 | for (File f : files) { 137 | responses.add(f); 138 | if (f.isDirectory() && isRecursive) { 139 | listFiles(responses, f, true); 140 | } 141 | } 142 | } 143 | 144 | public static void write(String path, InputStream inputStream) throws IOException { 145 | write(path, inputStream, Boolean.FALSE); 146 | } 147 | 148 | public static void write(String path, InputStream inputStream, boolean append) throws IOException { 149 | write(getFile(path), inputStream, append); 150 | } 151 | 152 | public static void write(File file, InputStream inputStream) throws IOException { 153 | write(file, inputStream, Boolean.FALSE); 154 | } 155 | 156 | public static void write(File file, InputStream inputStream, boolean append) throws IOException { 157 | if (!file.exists()) { 158 | createFile(file); 159 | } 160 | write(new FileOutputStream(file, append), inputStream); 161 | } 162 | 163 | public static void write(OutputStream outputStream, InputStream inputStream) throws IOException { 164 | try (InputStream input = new BufferedInputStream(inputStream); 165 | OutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) { 166 | int index; 167 | byte[] bytes = new byte[2048]; 168 | while ((index = input.read(bytes)) != -1) { 169 | bufferedOutputStream.write(bytes, 0, index); 170 | } 171 | } 172 | } 173 | 174 | public static void download(String url, String file) throws IOException { 175 | download(url, getFile(file)); 176 | } 177 | 178 | public static void download(String url, File file) throws IOException { 179 | if (!file.exists()) { 180 | createFile(file); 181 | } 182 | URL website = new URL(url); 183 | try (ReadableByteChannel rbc = Channels.newChannel(website.openStream()); 184 | FileOutputStream fos = new FileOutputStream(file)) { 185 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 186 | } 187 | } 188 | 189 | public static boolean rename(String src, String target) { 190 | return rename(getFile(src), getFile(target)); 191 | } 192 | 193 | public static boolean rename(File src, File target) { 194 | return src.renameTo(target); 195 | } 196 | 197 | public static void write(String file, String content) throws IOException { 198 | write(file, content, Boolean.FALSE); 199 | } 200 | 201 | public static void write(String file, String content, boolean append) throws IOException { 202 | write(file, content, Encoding.UTF_8, append); 203 | } 204 | 205 | public static void write(String file, String content, Encoding encoding) throws IOException { 206 | write(file, content, encoding, Boolean.FALSE); 207 | } 208 | 209 | public static void write(String file, String content, Encoding encoding, boolean append) throws IOException { 210 | write(file, new ByteArrayInputStream(content.getBytes(encoding.getEncoding())), append); 211 | } 212 | 213 | public static void write(String file, byte[] content) throws IOException { 214 | write(file, content, Boolean.FALSE); 215 | } 216 | 217 | public static void write(String file, byte[] content, boolean append) throws IOException { 218 | write(file, new ByteArrayInputStream(content), append); 219 | } 220 | 221 | public static String readAsString(String file) throws IOException { 222 | return readAsString(file, Encoding.UTF_8); 223 | } 224 | 225 | public static String readAsString(String file, Encoding encoding) throws IOException { 226 | return new String(readAsBytes(file), encoding.getEncoding()); 227 | } 228 | 229 | public static String readAsString(InputStream inputStream) throws IOException { 230 | return readAsString(inputStream, Encoding.UTF_8); 231 | } 232 | 233 | public static String readAsString(InputStream inputStream, Encoding encoding) throws IOException { 234 | return new String(readAsBytes(inputStream), encoding.getEncoding()); 235 | } 236 | 237 | public static byte[] readAsBytes(String file) throws IOException { 238 | return readAsBytes(new FileInputStream(getFile(file))); 239 | } 240 | 241 | public static byte[] readAsBytes(InputStream input) throws IOException { 242 | try (InputStream bufferedInputStream = new BufferedInputStream(input); 243 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { 244 | int index; 245 | byte[] bytes = new byte[2048]; 246 | while ((index = bufferedInputStream.read(bytes)) != -1) { 247 | outputStream.write(bytes, 0, index); 248 | } 249 | return outputStream.toByteArray(); 250 | } catch (IOException e) { 251 | log.error(e.getMessage(), e); 252 | throw e; 253 | } 254 | } 255 | 256 | public static String getSuffix(String file) { 257 | int index = file.lastIndexOf("."); 258 | return index > -1 ? file.substring(index) : StringUtil.EMPTY; 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/HexUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | 5 | /** 6 | * @author kesc 7 | * @since 2023-06-29 15:27 8 | */ 9 | public class HexUtil { 10 | private static final char[] HEX_DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 11 | private static final char[] HEX_DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 12 | 13 | private static String bytes2Hex(byte[] input, char[] HEX_DIGITS) { 14 | char[] str = new char[16 * 2]; 15 | byte temp; 16 | int k = 0; 17 | for (int i = 0; i < 16; i++) { 18 | temp = input[i]; 19 | str[k++] = HEX_DIGITS[temp >>> 4 & 0xf]; 20 | str[k++] = HEX_DIGITS[temp & 0xf]; 21 | } 22 | return new String(str); 23 | } 24 | 25 | public static String bytes2HexUpper(byte[] input) { 26 | return bytes2Hex(input, HEX_DIGITS_UPPER); 27 | } 28 | 29 | public static String bytes2HexLower(byte[] input) { 30 | return bytes2Hex(input, HEX_DIGITS_LOWER); 31 | } 32 | 33 | public static byte[] hex2Bytes(String input) { 34 | return hex2Bytes(input.getBytes(StandardCharsets.ISO_8859_1)); 35 | } 36 | 37 | public static byte[] hex2Bytes(byte[] bytes) { 38 | int iLen = bytes.length; 39 | byte[] hexBytes = new byte[iLen / 2]; 40 | for (int i = 0; i < iLen; i = i + 2) { 41 | String strTmp = new String(bytes, i, 2, StandardCharsets.ISO_8859_1); 42 | hexBytes[i / 2] = (byte) Integer.parseInt(strTmp, 16); 43 | } 44 | return hexBytes; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import com.fasterxml.jackson.databind.JavaType; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.xjbg.java.sdk.customize.jackson.CustomObjectMapper; 6 | 7 | import java.io.IOException; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author kesc 13 | * @since 2018/1/27 14 | */ 15 | @SuppressWarnings({"unchecked", "unused"}) 16 | public final class JsonUtil { 17 | private static final ObjectMapper DEFAULT_OBJECT_MAPPER = new CustomObjectMapper(); 18 | private static volatile ObjectMapper OBJECT_MAPPER; 19 | 20 | public static void setObjectMapper(ObjectMapper objectMapper) { 21 | OBJECT_MAPPER = objectMapper; 22 | } 23 | 24 | private static ObjectMapper getObjectMapper() { 25 | return OBJECT_MAPPER == null ? DEFAULT_OBJECT_MAPPER : OBJECT_MAPPER; 26 | } 27 | 28 | private static String toJsonString(T source, boolean pretty) { 29 | try { 30 | if (source == null) { 31 | return null; 32 | } 33 | if (source instanceof String) { 34 | return (String) source; 35 | } 36 | ObjectMapper objectMapper = getObjectMapper(); 37 | if (pretty) { 38 | return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(source); 39 | } 40 | return objectMapper.writeValueAsString(source); 41 | } catch (Exception var3) { 42 | throw new RuntimeException(var3); 43 | } 44 | } 45 | 46 | public static String toJsonString(T source) { 47 | return toJsonString(source, Boolean.FALSE); 48 | } 49 | 50 | public static String toJsonStringPretty(T source) { 51 | return toJsonString(source, Boolean.TRUE); 52 | } 53 | 54 | @SuppressWarnings("unchecked") 55 | public static T toObject(String source, Class clazz) { 56 | try { 57 | if (source == null) { 58 | return null; 59 | } 60 | if (clazz.isAssignableFrom(String.class)) { 61 | return (T) source; 62 | } 63 | return getObjectMapper().readValue(source, clazz); 64 | } catch (Exception var4) { 65 | throw new RuntimeException(var4); 66 | } 67 | } 68 | 69 | public static T toObject(String source, Class clazz, Class... parametricType) { 70 | try { 71 | if (source == null) { 72 | return null; 73 | } 74 | JavaType javaType = getObjectMapper().getTypeFactory().constructParametricType(clazz, parametricType); 75 | return getObjectMapper().readValue(source, javaType); 76 | } catch (Exception var4) { 77 | throw new RuntimeException(var4); 78 | } 79 | } 80 | 81 | public static List toList(String source, Class tClass) { 82 | try { 83 | if (source == null) { 84 | return null; 85 | } 86 | JavaType javaType = getObjectMapper().getTypeFactory().constructCollectionLikeType(List.class, tClass); 87 | return getObjectMapper().readValue(source, javaType); 88 | } catch (IOException e) { 89 | throw new RuntimeException(e); 90 | } 91 | } 92 | 93 | public static List toList(String source, Class valueType, Class... valueParametricType) { 94 | try { 95 | if (source == null) { 96 | return null; 97 | } 98 | JavaType elementType = getObjectMapper().getTypeFactory().constructParametricType(valueType, valueParametricType); 99 | JavaType listType = getObjectMapper().getTypeFactory().constructCollectionType(List.class, elementType); 100 | return getObjectMapper().readValue(source, listType); 101 | } catch (IOException e) { 102 | throw new RuntimeException(e); 103 | } 104 | } 105 | 106 | public static Map toMap(String source, Class valueClazz) { 107 | return toMap(source, String.class, valueClazz); 108 | } 109 | 110 | public static Map toMap(String source) { 111 | return toMap(source, Object.class, Object.class); 112 | } 113 | 114 | public static Map toMap(String source, Class keyType, Class valueType) { 115 | try { 116 | if (source == null) { 117 | return null; 118 | } 119 | JavaType javaType = getObjectMapper().getTypeFactory().constructMapLikeType(Map.class, keyType, valueType); 120 | return getObjectMapper().readValue(source, javaType); 121 | } catch (IOException var5) { 122 | throw new RuntimeException(var5); 123 | } 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/Levenshtein.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | /** 4 | * @author kesc 5 | * @ClassName Levenshtein 6 | * @Description 字符串匹配算法 7 | * @date 2017年5月31日 上午11:58:04 8 | */ 9 | public class Levenshtein { 10 | private static volatile Levenshtein instance = null; 11 | 12 | private Levenshtein() { 13 | super(); 14 | } 15 | 16 | public static Levenshtein getInstance() { 17 | if (instance == null) { 18 | synchronized (Levenshtein.class) { 19 | if (instance == null) { 20 | instance = new Levenshtein(); 21 | } 22 | } 23 | } 24 | return instance; 25 | } 26 | 27 | public double compare(final String s1, final String s2) { 28 | double retval; 29 | int n = s1.length(); 30 | int m = s2.length(); 31 | if (0 == n) { 32 | retval = m; 33 | } else if (0 == m) { 34 | retval = n; 35 | } else { 36 | retval = 1.0 - (compare(s1, n, s2, m) / (Math.max(n, m))); 37 | } 38 | return retval; 39 | } 40 | 41 | private double compare(final String s1, final int n, final String s2, final int m) { 42 | int matrix[][] = new int[n + 1][m + 1]; 43 | for (int i = 0; i <= n; i++) { 44 | matrix[i][0] = i; 45 | } 46 | for (int i = 0; i <= m; i++) { 47 | matrix[0][i] = i; 48 | } 49 | for (int i = 1; i <= n; i++) { 50 | int s1i = s1.codePointAt(i - 1); 51 | for (int j = 1; j <= m; j++) { 52 | int s2j = s2.codePointAt(j - 1); 53 | final int cost = s1i == s2j ? 0 : 1; 54 | matrix[i][j] = min3(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost); 55 | } 56 | } 57 | return matrix[n][m]; 58 | } 59 | 60 | private int min3(final int a, final int b, final int c) { 61 | return Math.min(Math.min(a, b), c); 62 | } 63 | 64 | public static void main(String[] args) { 65 | String a = "85°C"; 66 | String b = "85°C"; 67 | System.out.println(Levenshtein.getInstance().compare(a, b)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/NumberUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import org.apache.commons.lang3.math.NumberUtils; 4 | 5 | /** 6 | * @author kesc 7 | * @since 2023-11-06 17:23 8 | */ 9 | public class NumberUtil extends NumberUtils { 10 | 11 | public static Integer toInteger(String s) { 12 | return toInteger(s, null); 13 | } 14 | 15 | public static Integer toInteger(String str, Integer defaultValue) { 16 | if (StringUtil.isBlank(str)) { 17 | return defaultValue; 18 | } 19 | try { 20 | return Integer.valueOf(str); 21 | } catch (final NumberFormatException nfe) { 22 | return defaultValue; 23 | } 24 | } 25 | 26 | public static Long toLongWrap(String s) { 27 | return toLongWrap(s, null); 28 | } 29 | 30 | public static Long toLongWrap(String str, Long defaultValue) { 31 | if (StringUtil.isBlank(str)) { 32 | return defaultValue; 33 | } 34 | try { 35 | return Long.valueOf(str); 36 | } catch (final NumberFormatException nfe) { 37 | return defaultValue; 38 | } 39 | } 40 | 41 | public static Float toFloatWrap(String s) { 42 | return toFloatWrap(s, null); 43 | } 44 | 45 | public static Float toFloatWrap(String str, Float defaultValue) { 46 | if (StringUtil.isBlank(str)) { 47 | return defaultValue; 48 | } 49 | try { 50 | return Float.valueOf(str); 51 | } catch (final NumberFormatException nfe) { 52 | return defaultValue; 53 | } 54 | } 55 | 56 | public static Double toDoubleWrap(String s) { 57 | return toDoubleWrap(s, null); 58 | } 59 | 60 | public static Double toDoubleWrap(String str, Double defaultValue) { 61 | if (StringUtil.isBlank(str)) { 62 | return defaultValue; 63 | } 64 | try { 65 | return Double.valueOf(str); 66 | } catch (final NumberFormatException nfe) { 67 | return defaultValue; 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/PinYinUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import net.sourceforge.pinyin4j.PinyinHelper; 5 | import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; 6 | import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; 7 | import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; 8 | import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; 9 | import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; 10 | 11 | /** 12 | * @author kesc 13 | * @since 2023-11-06 10:48 14 | */ 15 | @Slf4j 16 | @SuppressWarnings("unused") 17 | public class PinYinUtil { 18 | 19 | public static String getPinYin(String inputString) throws BadHanyuPinyinOutputFormatCombination { 20 | HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); 21 | format.setCaseType(HanyuPinyinCaseType.LOWERCASE); 22 | format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); 23 | format.setVCharType(HanyuPinyinVCharType.WITH_V); 24 | 25 | char[] input = inputString.trim().toCharArray(); 26 | StringBuilder output = new StringBuilder(); 27 | 28 | for (char anInput : input) { 29 | if (Character.toString(anInput).matches("[\\u4E00-\\u9FA5]+")) { 30 | String[] temp = PinyinHelper.toHanyuPinyinStringArray(anInput, format); 31 | output.append(temp[0]); 32 | } else { 33 | output.append(anInput); 34 | } 35 | } 36 | return output.toString(); 37 | } 38 | 39 | public static String getFirstSpell(String chinese) throws BadHanyuPinyinOutputFormatCombination { 40 | StringBuilder sb = new StringBuilder(); 41 | char[] arr = chinese.toCharArray(); 42 | HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); 43 | defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE); 44 | defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); 45 | for (char anArr : arr) { 46 | if (anArr > 128) { 47 | String[] temp = PinyinHelper.toHanyuPinyinStringArray(anArr, defaultFormat); 48 | if (temp != null && temp.length > 0) { 49 | sb.append(temp[0].charAt(0)); 50 | } 51 | } else { 52 | sb.append(anArr); 53 | } 54 | } 55 | return sb.toString().replaceAll("\\W", "").trim(); 56 | } 57 | 58 | public static String getFullSpell(String chinese) throws BadHanyuPinyinOutputFormatCombination { 59 | StringBuilder sb = new StringBuilder(); 60 | char[] arr = chinese.toCharArray(); 61 | HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); 62 | defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); 63 | defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); 64 | for (char anArr : arr) { 65 | if (anArr > 128) { 66 | sb.append(PinyinHelper.toHanyuPinyinStringArray(anArr, defaultFormat)[0]); 67 | } else { 68 | sb.append(anArr); 69 | } 70 | } 71 | return sb.toString(); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/RandomUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import org.apache.commons.lang3.Validate; 4 | 5 | import java.security.SecureRandom; 6 | 7 | /** 8 | * @author kesc 9 | * @since 2019/6/24 10 | */ 11 | public final class RandomUtil { 12 | private static final SecureRandom RANDOM = new SecureRandom(); 13 | 14 | public static String random(int count) { 15 | return random(count, false, false); 16 | } 17 | 18 | public static String randomAscii(int count) { 19 | return random(count, 32, 127, false, false); 20 | } 21 | 22 | public static String randomAlphabetic(int count) { 23 | return random(count, true, false); 24 | } 25 | 26 | public static String randomAlphanumeric(int count) { 27 | return random(count, true, true); 28 | } 29 | 30 | public static String randomNumeric(int count) { 31 | return random(count, false, true); 32 | } 33 | 34 | public static String random(int count, boolean letters, boolean numbers) { 35 | return random(count, 0, 0, letters, numbers); 36 | } 37 | 38 | public static String random(int count, int start, int end, boolean letters, boolean numbers) { 39 | return random(count, start, end, letters, numbers, null, RANDOM); 40 | } 41 | 42 | public static String random(int count, int start, int end, boolean letters, boolean numbers, char... chars) { 43 | return random(count, start, end, letters, numbers, chars, RANDOM); 44 | } 45 | 46 | public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars, SecureRandom random) { 47 | if (count == 0) { 48 | return ""; 49 | } else if (count < 0) { 50 | throw new IllegalArgumentException("Requested RANDOM string length " + count + " is less than 0."); 51 | } else if (chars != null && chars.length == 0) { 52 | throw new IllegalArgumentException("The chars array must not be empty"); 53 | } else { 54 | if (start == 0 && end == 0) { 55 | if (chars != null) { 56 | end = chars.length; 57 | } else if (!letters && !numbers) { 58 | end = 2147483647; 59 | } else { 60 | end = 123; 61 | start = 32; 62 | } 63 | } else if (end <= start) { 64 | throw new IllegalArgumentException("Parameter end (" + end + ") must be greater than start (" + start + ")"); 65 | } 66 | 67 | char[] buffer = new char[count]; 68 | int gap = end - start; 69 | 70 | while (true) { 71 | while (true) { 72 | while (count-- != 0) { 73 | char ch; 74 | if (chars == null) { 75 | ch = (char) (random.nextInt(gap) + start); 76 | } else { 77 | ch = chars[random.nextInt(gap) + start]; 78 | } 79 | 80 | if (letters && Character.isLetter(ch) || numbers && Character.isDigit(ch) || !letters && !numbers) { 81 | if (ch >= '\udc00' && ch <= '\udfff') { 82 | if (count == 0) { 83 | ++count; 84 | } else { 85 | buffer[count] = ch; 86 | --count; 87 | buffer[count] = (char) ('\ud800' + random.nextInt(128)); 88 | } 89 | } else if (ch >= '\ud800' && ch <= '\udb7f') { 90 | if (count == 0) { 91 | ++count; 92 | } else { 93 | buffer[count] = (char) ('\udc00' + random.nextInt(128)); 94 | --count; 95 | buffer[count] = ch; 96 | } 97 | } else if (ch >= '\udb80' && ch <= '\udbff') { 98 | ++count; 99 | } else { 100 | buffer[count] = ch; 101 | } 102 | } else { 103 | ++count; 104 | } 105 | } 106 | 107 | return new String(buffer); 108 | } 109 | } 110 | } 111 | } 112 | 113 | public static String random(int count, String chars) { 114 | return chars == null ? random(count, 0, 0, false, false, null, RANDOM) : random(count, chars.toCharArray()); 115 | } 116 | 117 | public static String random(int count, char... chars) { 118 | return chars == null ? random(count, 0, 0, false, false, null, RANDOM) : random(count, 0, chars.length, false, false, chars, RANDOM); 119 | } 120 | 121 | public static byte[] nextBytes(int seed) { 122 | byte[] result = new byte[seed]; 123 | RANDOM.nextBytes(result); 124 | return result; 125 | } 126 | 127 | public static int nextInt(int seed) { 128 | return RANDOM.nextInt(seed); 129 | } 130 | 131 | public static int nextInt(int seed, int base) { 132 | return RANDOM.nextInt(seed) + base; 133 | } 134 | 135 | public static long nextLong() { 136 | return RANDOM.nextLong(); 137 | } 138 | 139 | public static float nextFloat() { 140 | return RANDOM.nextFloat(); 141 | } 142 | 143 | public static double nextDouble() { 144 | return RANDOM.nextDouble(); 145 | } 146 | 147 | public static double nextGaussian() { 148 | return RANDOM.nextGaussian(); 149 | } 150 | 151 | public static long nextLong(long startInclusive, long endExclusive) { 152 | Validate.isTrue(endExclusive >= startInclusive, "Start value must be smaller or equal to end value.", new Object[0]); 153 | Validate.isTrue(startInclusive >= 0L, "Both range values must be non-negative.", new Object[0]); 154 | return startInclusive == endExclusive ? startInclusive : (long) nextDouble((double) startInclusive, (double) endExclusive); 155 | } 156 | 157 | public static double nextDouble(double startInclusive, double endInclusive) { 158 | Validate.isTrue(endInclusive >= startInclusive, "Start value must be smaller or equal to end value.", new Object[0]); 159 | Validate.isTrue(startInclusive >= 0.0D, "Both range values must be non-negative.", new Object[0]); 160 | return startInclusive == endInclusive ? startInclusive : startInclusive + (endInclusive - startInclusive) * RANDOM.nextDouble(); 161 | } 162 | 163 | public static float nextFloat(float startInclusive, float endInclusive) { 164 | Validate.isTrue(endInclusive >= startInclusive, "Start value must be smaller or equal to end value.", new Object[0]); 165 | Validate.isTrue(startInclusive >= 0.0F, "Both range values must be non-negative.", new Object[0]); 166 | return startInclusive == endInclusive ? startInclusive : startInclusive + (endInclusive - startInclusive) * RANDOM.nextFloat(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/ReflectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import com.esotericsoftware.reflectasm.MethodAccess; 4 | import com.google.common.cache.LoadingCache; 5 | import com.xjbg.java.sdk.cache.LocalCacheHelper; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.lang.annotation.Annotation; 9 | import java.lang.reflect.Field; 10 | import java.util.*; 11 | import java.util.concurrent.TimeUnit; 12 | import java.util.function.Predicate; 13 | 14 | /** 15 | * @author kesc 16 | * @since 2019/6/24 17 | */ 18 | @Slf4j 19 | public final class ReflectionUtil { 20 | /** 21 | * could not be modify 22 | */ 23 | private final static LoadingCache, Field[]> CACHE_FIELD = LocalCacheHelper.buildCache(100, 1, TimeUnit.DAYS, Class::getDeclaredFields); 24 | /** 25 | * could not be modify 26 | */ 27 | private final static LoadingCache, MethodAccess> CACHE_METHOD = LocalCacheHelper.buildCache(100, 1, TimeUnit.DAYS, MethodAccess::get); 28 | 29 | public static Field[] getField(Class clazz) { 30 | try { 31 | return CACHE_FIELD.getUnchecked(clazz); 32 | } catch (Exception e) { 33 | return null; 34 | } 35 | } 36 | 37 | public static List getAllField(Class tClass) { 38 | List fieldList = new ArrayList<>(); 39 | for (Class clazz = tClass; clazz != Object.class && clazz != null; clazz = clazz.getSuperclass()) { 40 | Field[] fields = getField(clazz); 41 | if (CollectionUtil.isEmpty(fields)) { 42 | continue; 43 | } 44 | Collections.addAll(fieldList, fields); 45 | } 46 | return fieldList; 47 | } 48 | 49 | /** 50 | * java bean 转成map 51 | * 52 | * @param obj java bean with getter setter 53 | * @return 54 | */ 55 | public static Map beanToMap(Object obj) { 56 | List fields = getAllField(obj.getClass()); 57 | Map map = new HashMap<>((int) (fields.size() * 1.75) + 1); 58 | CollectionUtil.forEach(fields, x -> { 59 | try { 60 | map.put(x.getName(), invoke(obj, "get" + StringUtil.capitalize(x.getName()))); 61 | } catch (Exception e) { 62 | log.error(e.getMessage(), e); 63 | } 64 | }); 65 | return map; 66 | } 67 | 68 | public static MethodAccess getMethodAccess(Class clazz) { 69 | try { 70 | return CACHE_METHOD.getUnchecked(clazz); 71 | } catch (Exception e) { 72 | throw new RuntimeException(e.getMessage()); 73 | } 74 | } 75 | 76 | public static Object invoke(Object obj, String methodName, Object... args) { 77 | MethodAccess methodAccess = getMethodAccess(obj.getClass()); 78 | return methodAccess.invoke(obj, methodName, args); 79 | } 80 | 81 | public static Object invoke(Object obj, String methodName, Class[] paramTypes, Object... args) { 82 | MethodAccess methodAccess = getMethodAccess(obj.getClass()); 83 | return methodAccess.invoke(obj, methodName, paramTypes, args); 84 | } 85 | 86 | public static Field getField(Class tClass, Class annotationClass) { 87 | for (Class clazz = tClass; clazz != Object.class && clazz != null; clazz = clazz.getSuperclass()) { 88 | Field[] fields = getField(clazz); 89 | if (fields != null && fields.length > 0) { 90 | for (Field f : fields) { 91 | if (f.isAnnotationPresent(annotationClass)) { 92 | return f; 93 | } 94 | } 95 | } 96 | } 97 | return null; 98 | } 99 | 100 | public static List getFields(Class tClass, Class annotationClass) { 101 | List fields = getAllField(tClass); 102 | return CollectionUtil.filter(fields, (Predicate) field -> field.isAnnotationPresent(annotationClass)); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/RetryUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.Callable; 8 | import java.util.concurrent.Future; 9 | import java.util.concurrent.ThreadPoolExecutor; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * @author kesc 14 | * @since 2019/6/24 15 | */ 16 | public final class RetryUtil { 17 | 18 | private static final Logger LOG = LoggerFactory.getLogger(RetryUtil.class); 19 | 20 | private static final long MAX_SLEEP_MILLISECOND = 256 * 1000; 21 | 22 | /** 23 | * 重试次数工具方法. 24 | * 25 | * @param callable 实际逻辑 26 | * @param retryTimes 最大重试次数(>1) 27 | * @param sleepTimeInMilliSecond 运行失败后休眠对应时间再重试 28 | * @param exponential 休眠时间是否指数递增 29 | * @param 返回值类型 30 | * @return 经过重试的callable的执行结果 31 | */ 32 | public static T executeWithRetry(Callable callable, 33 | int retryTimes, 34 | long sleepTimeInMilliSecond, 35 | boolean exponential) throws Exception { 36 | Retry retry = new Retry(); 37 | return retry.doRetry(callable, retryTimes, sleepTimeInMilliSecond, exponential, null); 38 | } 39 | 40 | /** 41 | * 重试次数工具方法. 42 | * 43 | * @param callable 实际逻辑 44 | * @param retryTimes 最大重试次数(>1) 45 | * @param sleepTimeInMilliSecond 运行失败后休眠对应时间再重试 46 | * @param exponential 休眠时间是否指数递增 47 | * @param 返回值类型 48 | * @param retryExceptionClasss 出现指定的异常类型时才进行重试 49 | * @return 经过重试的callable的执行结果 50 | */ 51 | public static T executeWithRetry(Callable callable, 52 | int retryTimes, 53 | long sleepTimeInMilliSecond, 54 | boolean exponential, 55 | List> retryExceptionClasss) throws Exception { 56 | Retry retry = new Retry(); 57 | return retry.doRetry(callable, retryTimes, sleepTimeInMilliSecond, exponential, retryExceptionClasss); 58 | } 59 | 60 | /** 61 | * 在外部线程执行并且重试。每次执行需要在timeoutMs内执行完,不然视为失败。 62 | * 执行异步操作的线程池从外部传入,线程池的共享粒度由外部控制。比如,HttpClientUtil共享一个线程池。 63 | *

64 | * 限制条件:仅仅能够在阻塞的时候interrupt线程 65 | * 66 | * @param callable 实际逻辑 67 | * @param retryTimes 最大重试次数(>1) 68 | * @param sleepTimeInMilliSecond 运行失败后休眠对应时间再重试 69 | * @param exponential 休眠时间是否指数递增 70 | * @param timeoutMs callable执行超时时间,毫秒 71 | * @param executor 执行异步操作的线程池 72 | * @param 返回值类型 73 | * @return 经过重试的callable的执行结果 74 | */ 75 | public static T asyncExecuteWithRetry(Callable callable, 76 | int retryTimes, 77 | long sleepTimeInMilliSecond, 78 | boolean exponential, 79 | long timeoutMs, 80 | ThreadPoolExecutor executor) throws Exception { 81 | Retry retry = new AsyncRetry(timeoutMs, executor); 82 | return retry.doRetry(callable, retryTimes, sleepTimeInMilliSecond, exponential, null); 83 | } 84 | 85 | 86 | private static class Retry { 87 | 88 | public T doRetry(Callable callable, int retryTimes, long sleepTimeInMilliSecond, boolean exponential, List> retryExceptionClasss) 89 | throws Exception { 90 | 91 | if (null == callable) { 92 | throw new IllegalArgumentException("系统编程错误, 入参callable不能为空 ! "); 93 | } 94 | 95 | if (retryTimes < 1) { 96 | throw new IllegalArgumentException(String.format( 97 | "系统编程错误, 入参retrytime[%d]不能小于1 !", retryTimes)); 98 | } 99 | 100 | Exception saveException = null; 101 | for (int i = 0; i < retryTimes; i++) { 102 | try { 103 | return call(callable); 104 | } catch (Exception e) { 105 | saveException = e; 106 | if (i == 0) { 107 | LOG.error(String.format("Exception when calling callable, 异常Msg:%s", saveException.getMessage()), saveException); 108 | } 109 | 110 | if (null != retryExceptionClasss && !retryExceptionClasss.isEmpty()) { 111 | boolean needRetry = false; 112 | for (Class eachExceptionClass : retryExceptionClasss) { 113 | if (eachExceptionClass == e.getClass()) { 114 | needRetry = true; 115 | break; 116 | } 117 | } 118 | if (!needRetry) { 119 | throw saveException; 120 | } 121 | } 122 | 123 | if (i + 1 < retryTimes && sleepTimeInMilliSecond > 0) { 124 | long startTime = System.currentTimeMillis(); 125 | 126 | long timeToSleep; 127 | if (exponential) { 128 | timeToSleep = sleepTimeInMilliSecond * (long) Math.pow(2, i); 129 | if (timeToSleep >= MAX_SLEEP_MILLISECOND) { 130 | timeToSleep = MAX_SLEEP_MILLISECOND; 131 | } 132 | } else { 133 | timeToSleep = sleepTimeInMilliSecond; 134 | if (timeToSleep >= MAX_SLEEP_MILLISECOND) { 135 | timeToSleep = MAX_SLEEP_MILLISECOND; 136 | } 137 | } 138 | 139 | try { 140 | Thread.sleep(timeToSleep); 141 | } catch (InterruptedException ignored) { 142 | } 143 | 144 | long realTimeSleep = System.currentTimeMillis() - startTime; 145 | 146 | LOG.error(String.format("Exception when calling callable, 即将尝试执行第%s次重试.本次重试计划等待[%s]ms,实际等待[%s]ms, 异常Msg:[%s]", 147 | i + 1, timeToSleep, realTimeSleep, e.getMessage())); 148 | 149 | } 150 | } 151 | } 152 | throw saveException; 153 | } 154 | 155 | protected T call(Callable callable) throws Exception { 156 | return callable.call(); 157 | } 158 | } 159 | 160 | private static class AsyncRetry extends Retry { 161 | 162 | private long timeoutMs; 163 | private ThreadPoolExecutor executor; 164 | 165 | public AsyncRetry(long timeoutMs, ThreadPoolExecutor executor) { 166 | this.timeoutMs = timeoutMs; 167 | this.executor = executor; 168 | } 169 | 170 | /** 171 | * 使用传入的线程池异步执行任务,并且等待。 172 | *

173 | * future.get()方法,等待指定的毫秒数。如果任务在超时时间内结束,则正常返回。 174 | * 如果抛异常(可能是执行超时、执行异常、被其他线程cancel或interrupt),都记录日志并且网上抛异常。 175 | * 正常和非正常的情况都会判断任务是否结束,如果没有结束,则cancel任务。cancel参数为true,表示即使 176 | * 任务正在执行,也会interrupt线程。 177 | * 178 | * @param callable 179 | * @param 180 | * @return 181 | * @throws Exception 182 | */ 183 | @Override 184 | protected T call(Callable callable) throws Exception { 185 | Future future = executor.submit(callable); 186 | try { 187 | return future.get(timeoutMs, TimeUnit.MILLISECONDS); 188 | } catch (Exception e) { 189 | LOG.warn("Try once failed", e); 190 | throw e; 191 | } finally { 192 | if (!future.isDone()) { 193 | future.cancel(true); 194 | LOG.warn("Try once task not done, cancel it, active count: " + executor.getActiveCount()); 195 | } 196 | } 197 | } 198 | } 199 | 200 | } 201 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/SnowFlake.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | 6 | /** 7 | * @author kesc 8 | * @date 2017年5月31日 上午11:57:17 9 | * @ClassName SnowFlake 10 | * @Description Twitter_Snowflake
11 | * SnowFlake的结构如下(每部分用-分开):
12 | * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 13 | * 00000 - 000000000000
14 | * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
15 | * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) 16 | * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的( 17 | * 如下下面程序IdWorker类的startTime属性)。 41位的时间截,可以使用69年,年T = (1L << 41) / 18 | * (1000L * 60 * 60 * 24 * 365) = 69
19 | * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
20 | * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
21 | * 加起来刚好64位,为一个Long型。
22 | * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分), 23 | * 并且效率较高,经测试, SnowFlake每秒能够产生26万ID左右。 24 | */ 25 | public class SnowFlake { 26 | 27 | /** 28 | * 开始时间截 (2017-05-31 14:30:00) 29 | */ 30 | private final long twepoch = 1496217866185L; 31 | 32 | /** 33 | * 机器id所占的位数 34 | */ 35 | private static final long workerIdBits = 5L; 36 | 37 | /** 38 | * 数据标识id所占的位数 39 | */ 40 | private static final long datacenterIdBits = 5L; 41 | 42 | /** 43 | * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) 44 | */ 45 | private static final long maxWorkerId = ~(-1L << workerIdBits); 46 | 47 | /** 48 | * 支持的最大数据标识id,结果是31 49 | */ 50 | private static final long maxDatacenterId = ~(-1L << datacenterIdBits); 51 | 52 | /** 53 | * 序列在id中占的位数 54 | */ 55 | private final long sequenceBits = 12L; 56 | 57 | /** 58 | * 机器ID向左移12位 59 | */ 60 | private final long workerIdShift = sequenceBits; 61 | 62 | /** 63 | * 数据标识id向左移17位(12+5) 64 | */ 65 | private final long datacenterIdShift = sequenceBits + workerIdBits; 66 | 67 | /** 68 | * 时间截向左移22位(5+5+12) 69 | */ 70 | private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; 71 | 72 | /** 73 | * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) 74 | */ 75 | private final long sequenceMask = ~(-1L << sequenceBits); 76 | 77 | /** 78 | * 工作机器ID(0~31) 79 | */ 80 | private long workerId; 81 | 82 | /** 83 | * 数据中心ID(0~31) 84 | */ 85 | private long datacenterId; 86 | 87 | /** 88 | * 毫秒内序列(0~4095) 89 | */ 90 | private long sequence = 0L; 91 | 92 | /** 93 | * 上次生成ID的时间截 94 | */ 95 | private long lastTimestamp = -1L; 96 | 97 | public SnowFlake() { 98 | this(generateWorkerId(), generateDataCenterId()); 99 | } 100 | 101 | /** 102 | * 构造函数 103 | * 104 | * @param workerId 工作ID (0~31) 105 | * @param datacenterId 数据中心ID (0~31) 106 | */ 107 | public SnowFlake(long workerId, long datacenterId) { 108 | if (workerId > maxWorkerId || workerId < 0) { 109 | throw new IllegalArgumentException( 110 | String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); 111 | } 112 | if (datacenterId > maxDatacenterId || datacenterId < 0) { 113 | throw new IllegalArgumentException( 114 | String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); 115 | } 116 | this.workerId = workerId; 117 | this.datacenterId = datacenterId; 118 | } 119 | 120 | private static long mod(byte[] bytes, long max) { 121 | int count = 0; 122 | for (byte b : bytes) { 123 | count += b; 124 | } 125 | return Math.abs(count % (max + 1)); 126 | } 127 | 128 | private static long generateWorkerId() { 129 | try { 130 | byte[] bytes = InetAddress.getLocalHost().getHostName().getBytes(); 131 | return mod(bytes, maxWorkerId); 132 | } catch (UnknownHostException e) { 133 | return RandomUtil.nextLong(0, maxWorkerId + 1); 134 | } 135 | } 136 | 137 | private static long generateDataCenterId() { 138 | try { 139 | byte[] bytes = InetAddress.getLocalHost().getAddress(); 140 | return mod(bytes, maxDatacenterId); 141 | } catch (UnknownHostException e) { 142 | return RandomUtil.nextLong(0, maxDatacenterId + 1); 143 | } 144 | } 145 | 146 | /** 147 | * 获得下一个ID (该方法是线程安全的) 148 | * 149 | * @return SnowflakeId 150 | */ 151 | public synchronized long nextId() { 152 | long timestamp = timeGen(); 153 | // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 154 | if (timestamp < lastTimestamp) { 155 | throw new RuntimeException(String.format( 156 | "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); 157 | } 158 | // 如果是同一时间生成的,则进行毫秒内序列 159 | if (lastTimestamp == timestamp) { 160 | sequence = (sequence + 1) & sequenceMask; 161 | // 毫秒内序列溢出 162 | if (sequence == 0) { 163 | // 阻塞到下一个毫秒,获得新的时间戳 164 | timestamp = tilNextMillis(lastTimestamp); 165 | } 166 | } else { // 时间戳改变,毫秒内序列重置 167 | sequence = 0L; 168 | } 169 | // 上次生成ID的时间截 170 | lastTimestamp = timestamp; 171 | // 移位并通过或运算拼到一起组成64位的ID 172 | return ((timestamp - twepoch) << timestampLeftShift) 173 | | (datacenterId << datacenterIdShift) 174 | | (workerId << workerIdShift) 175 | | sequence; 176 | } 177 | 178 | /** 179 | * 阻塞到下一个毫秒,直到获得新的时间戳 180 | * 181 | * @param lastTimestamp 上次生成ID的时间截 182 | * @return 当前时间戳 183 | */ 184 | private long tilNextMillis(long lastTimestamp) { 185 | long timestamp = timeGen(); 186 | while (timestamp <= lastTimestamp) { 187 | timestamp = timeGen(); 188 | } 189 | return timestamp; 190 | } 191 | 192 | /** 193 | * 返回以毫秒为单位的当前时间 194 | * 195 | * @return 当前时间(毫秒) 196 | */ 197 | private long timeGen() { 198 | return System.currentTimeMillis(); 199 | } 200 | 201 | public static void main(String[] args) { 202 | SnowFlake idWorker = new SnowFlake(0, 0); 203 | long start = System.currentTimeMillis(); 204 | System.out.println("开始时间戳:" + start); 205 | for (int i = 0; i < 10; i++) { 206 | long id = idWorker.nextId(); 207 | System.out.println(id); 208 | } 209 | long end = System.currentTimeMillis(); 210 | System.out.println("结束时间戳:" + end + ",花费时间(毫秒):" + (end - start)); 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import java.nio.charset.Charset; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.UUID; 9 | 10 | 11 | /** 12 | * @author kesc 13 | * @since 2017/12/25 14 | */ 15 | public final class StringUtil extends StringUtils { 16 | public static final String COMMA = ","; 17 | public static final String UNDER_LINE = "_"; 18 | public static final String DOT = "."; 19 | public static final String MINUS = "-"; 20 | public static final String VIRGULE = "/"; 21 | public static final String COLON = ":"; 22 | public static final String PLUS = "+"; 23 | public static final String EQUIVALENT = "="; 24 | public static final String GT = ">"; 25 | public static final String LT = "<"; 26 | public static final String VERTICAL_LINE = "|"; 27 | public static final String STAR = "*"; 28 | public static final String PERCENT = "%"; 29 | public static final String AND = "&"; 30 | public static final String DOLOR = "$"; 31 | public static final String L_QUOT = "("; 32 | public static final String R_QUOT = ")"; 33 | public static final String SEMICOLON = ";"; 34 | public static final String AT = "@"; 35 | public static final String EXCLAMATION = "!"; 36 | 37 | public static String uuid() { 38 | return UUID.randomUUID().toString(); 39 | } 40 | 41 | public static String latterUuid() { 42 | return UUID.randomUUID().toString().replace(MINUS, EMPTY); 43 | } 44 | 45 | public static String camel2Underline(String str) { 46 | if (isBlank(str)) { 47 | return str; 48 | } 49 | str = str.trim(); 50 | StringBuilder result = new StringBuilder(str.length()); 51 | result.append(Character.toLowerCase(str.charAt(0))); 52 | for (int i = 1; i < str.length(); i++) { 53 | char ch = str.charAt(i); 54 | if (Character.isUpperCase(ch)) { 55 | result.append('_').append(Character.toLowerCase(ch)); 56 | } else { 57 | result.append(ch); 58 | } 59 | } 60 | return result.toString(); 61 | } 62 | 63 | public static String underline2Camel(String str) { 64 | if (isBlank(str)) { 65 | return str; 66 | } 67 | str = str.trim(); 68 | StringBuilder result = new StringBuilder(str.length()); 69 | boolean flag = false; 70 | for (int i = 0; i < str.length(); i++) { 71 | char ch = str.charAt(i); 72 | if ('_' == ch) { 73 | flag = true; 74 | } else { 75 | if (flag) { 76 | result.append(Character.toUpperCase(ch)); 77 | flag = false; 78 | } else { 79 | result.append(ch); 80 | } 81 | } 82 | } 83 | return result.toString(); 84 | } 85 | 86 | public static byte[] getBytes(String src) { 87 | if (src == null) { 88 | return null; 89 | } 90 | return src.getBytes(); 91 | } 92 | 93 | public static byte[] getBytes(String src, String charset) { 94 | return getBytes(src, Charset.forName(charset)); 95 | } 96 | 97 | public static byte[] getBytes(String src, Charset charset) { 98 | if (src == null) { 99 | return null; 100 | } 101 | return src.getBytes(charset); 102 | } 103 | 104 | public static byte[] getUTF8Bytes(String src) { 105 | return getBytes(src, StandardCharsets.UTF_8); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/ThreadPoolUtils.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * @author: kesc 7 | * @time: 2017-12-19 20:05 8 | */ 9 | public class ThreadPoolUtils { 10 | private static final ThreadPoolExecutor POOL = create(); 11 | private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = createScheduledPool(Runtime.getRuntime().availableProcessors() * 2); 12 | 13 | static { 14 | POOL.allowCoreThreadTimeOut(true); 15 | } 16 | 17 | public static ThreadPoolExecutor create() { 18 | return create(Runtime.getRuntime().availableProcessors() * 2); 19 | } 20 | 21 | public static ThreadPoolExecutor create(int coreSize) { 22 | return create(coreSize, coreSize * 2); 23 | } 24 | 25 | public static ThreadPoolExecutor create(int coreSize, int maxSize) { 26 | return create(coreSize, maxSize, 1000); 27 | } 28 | 29 | public static ThreadPoolExecutor create(int coreSize, int maxSize, int queueSize) { 30 | return create(coreSize, maxSize, queueSize, Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy()); 31 | } 32 | 33 | public static ThreadPoolExecutor create(int coreSize, int maxSize, 34 | int queueSize, 35 | RejectedExecutionHandler rejectedExecutionHandler) { 36 | return create(coreSize, maxSize, queueSize, Executors.defaultThreadFactory(), rejectedExecutionHandler); 37 | } 38 | 39 | public static ThreadPoolExecutor create(int coreSize, int maxSize, 40 | int queueSize, 41 | ThreadFactory threadFactory, 42 | RejectedExecutionHandler rejectedExecutionHandler) { 43 | return create(coreSize, maxSize, queueSize, 300L, TimeUnit.SECONDS, threadFactory, rejectedExecutionHandler); 44 | } 45 | 46 | public static ThreadPoolExecutor create(int coreSize, int maxSize, 47 | int queueSize, 48 | long keepAliveTime, TimeUnit keepAliveTimeUnit, 49 | ThreadFactory threadFactory, 50 | RejectedExecutionHandler rejectedExecutionHandler) { 51 | return new ThreadPoolExecutor(coreSize, 52 | maxSize, 53 | keepAliveTime, keepAliveTimeUnit, 54 | new LinkedBlockingQueue<>(queueSize), 55 | threadFactory, 56 | rejectedExecutionHandler); 57 | } 58 | 59 | public static ScheduledThreadPoolExecutor createScheduledPool(int size) { 60 | return createScheduledPool(size, new ThreadPoolExecutor.CallerRunsPolicy()); 61 | } 62 | 63 | public static ScheduledThreadPoolExecutor createScheduledPool(int size, RejectedExecutionHandler rejectedExecutionHandler) { 64 | return createScheduledPool(size, Executors.defaultThreadFactory(), rejectedExecutionHandler); 65 | } 66 | 67 | public static ScheduledThreadPoolExecutor createScheduledPool(int size, 68 | ThreadFactory threadFactory, 69 | RejectedExecutionHandler rejectedExecutionHandler) { 70 | return new ScheduledThreadPoolExecutor(size, threadFactory, rejectedExecutionHandler); 71 | } 72 | 73 | public static void execute(Runnable runnable) { 74 | POOL.execute(runnable); 75 | } 76 | 77 | public static Future submit(Runnable runnable) { 78 | return POOL.submit(runnable); 79 | } 80 | 81 | public static Future submit(Callable callable) { 82 | return POOL.submit(callable); 83 | } 84 | 85 | public static Future submitSchedule(Runnable runnable) { 86 | return SCHEDULED_POOL.submit(runnable); 87 | } 88 | 89 | public static Future submitSchedule(Callable callable) { 90 | return SCHEDULED_POOL.submit(callable); 91 | } 92 | 93 | public static ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { 94 | return SCHEDULED_POOL.schedule(command, delay, unit); 95 | } 96 | 97 | public static ScheduledFuture scheduleAtFixedRate(Runnable command, 98 | long initialDelay, 99 | long period, 100 | TimeUnit unit) { 101 | return SCHEDULED_POOL.scheduleAtFixedRate(command, initialDelay, period, unit); 102 | } 103 | 104 | public static ScheduledFuture scheduleWithFixedDelay(Runnable command, 105 | long initialDelay, 106 | long delay, 107 | TimeUnit unit) { 108 | return SCHEDULED_POOL.scheduleWithFixedDelay(command, initialDelay, delay, unit); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/xjbg/java/sdk/util/XmlUtils.java: -------------------------------------------------------------------------------- 1 | package com.xjbg.java.sdk.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import javax.xml.bind.JAXBContext; 6 | import javax.xml.bind.JAXBException; 7 | import javax.xml.bind.Marshaller; 8 | import javax.xml.bind.Unmarshaller; 9 | import java.io.IOException; 10 | import java.io.StringReader; 11 | import java.io.StringWriter; 12 | import java.nio.charset.StandardCharsets; 13 | 14 | /** 15 | * xml处理工具类 16 | * 17 | * @author kesc 18 | * @since 2018-08-10 14:29 19 | */ 20 | @Slf4j 21 | public class XmlUtils { 22 | 23 | public static String format(Object obj) throws IOException, JAXBException { 24 | return format(obj, obj.getClass()); 25 | } 26 | 27 | public static String format(Object obj, Class... classesToBeBound) throws IOException, JAXBException { 28 | return format(obj, Boolean.FALSE, classesToBeBound); 29 | } 30 | 31 | public static String formatPretty(Object obj) throws IOException, JAXBException { 32 | return formatPretty(obj, obj.getClass()); 33 | } 34 | 35 | public static String formatPretty(Object obj, Class... classesToBeBound) throws IOException, JAXBException { 36 | return format(obj, Boolean.TRUE, classesToBeBound); 37 | } 38 | 39 | private static String format(Object obj, boolean pretty, Class... classesToBeBound) throws IOException, JAXBException { 40 | try (StringWriter writer = new StringWriter()) { 41 | JAXBContext context = JAXBContext.newInstance(classesToBeBound); 42 | Marshaller marshaller = context.createMarshaller(); 43 | marshaller.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.name()); 44 | marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, pretty); 45 | marshaller.marshal(obj, writer); 46 | return writer.toString(); 47 | } 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | public static T parse(String xml, Class targetClass) throws JAXBException { 52 | return (T) parse(xml, new Class[]{targetClass}); 53 | } 54 | 55 | public static Object parse(String xml, Class... classesToBeBound) throws JAXBException { 56 | JAXBContext context = JAXBContext.newInstance(classesToBeBound); 57 | Unmarshaller unmarshaller = context.createUnmarshaller(); 58 | return unmarshaller.unmarshal(new StringReader(xml)); 59 | } 60 | } 61 | --------------------------------------------------------------------------------