Compare commits

...

102 Commits

Author SHA1 Message Date
dadf47f151 Merge branch 'master' of github.com:ehlxr/budd 2023-07-18 13:59:06 +08:00
ad72033f7e update 2023-07-18 13:58:55 +08:00
f86b055ecb update 2023-07-18 13:58:24 +08:00
2235c45510 budd-utils module 2023-07-15 20:29:51 +08:00
d4dd16ef96 update at 2022-12-04 22:58:59 by ehlxr 2022-12-04 22:58:59 +08:00
301a8b3911 Palindrome Linked List 2022-12-04 22:25:27 +08:00
ba50b612d8 Merge branch 'master' of github.com:ehlxr/budd 2022-12-03 23:28:09 +08:00
f251d5601a update at 2022-12-03 23:27:52 by ehlxr 2022-12-03 23:27:52 +08:00
21a23ee07e Update README.md 2022-09-06 16:38:55 +08:00
a91655bac5 Add files via upload 2022-09-06 16:38:32 +08:00
c665ca3b1f update string match 2022-06-19 12:55:01 +08:00
c1da2bd955 Merge branch 'master' of github.com:ehlxr/budd 2022-06-16 23:20:49 +08:00
e298c3a1a5 update kmp comment 2022-06-16 23:20:12 +08:00
5edfe37a46 update at 2022-05-04 19:31:51 by ehlxr 2022-05-04 19:31:51 +08:00
81c9ce2995 update at 2022-05-01 15:32:14 by ehlxr 2022-05-01 15:32:14 +08:00
545e3df7c0 update at 2022-04-29 13:34:49 by ehlxr 2022-04-29 13:34:49 +08:00
4160b02787 permutaion 2022-04-20 19:04:20 +08:00
fe1d9d913c Merge branch 'master' of github.com:ehlxr/budd 2022-04-15 08:53:20 +08:00
166fe7fe9a update at 2022-04-15 08:53:01 by ehlxr 2022-04-15 08:53:01 +08:00
aaccb2114b update at 2022-03-24 09:32:13 by ehlxr 2022-03-24 09:32:13 +08:00
b7da6e9537 update at 2022-03-18 22:38:16 by ehlxr 2022-03-18 22:38:16 +08:00
1b2a33d72d quick sort 2022-03-18 22:32:56 +08:00
bbd5275855 update at 2022-03-17 20:46:06 by ehlxr 2022-03-17 20:46:06 +08:00
b254db3bc0 heap sort 2022-03-16 22:14:53 +08:00
e575b8b94b Merge branch 'master' of github.com:ehlxr/budd 2022-03-16 12:02:31 +08:00
850c0d3dc3 update at 2022-03-16 12:02:20 by ehlxr 2022-03-16 12:02:20 +08:00
10e6dbf415 update at 2022-03-15 08:05:53 by ehlxr 2022-03-15 08:05:53 +08:00
497732614d reverse linkedlist 2022-03-14 09:35:04 +08:00
f1a6584fcd reverse linkedlist 2022-03-14 08:05:27 +08:00
db57411ca1 kmp 2022-03-13 16:26:12 +08:00
09d2c4899b update at 2022-03-13 16:05:38 by ehlxr 2022-03-13 16:05:38 +08:00
19d4bf9dee update at 2022-03-13 16:05:01 by ehlxr 2022-03-13 16:05:01 +08:00
4cd72cd4f2 update at 2022-03-12 23:18:23 by ehlxr 2022-03-12 23:18:23 +08:00
6cfb4fd37e update at 2022-03-12 16:13:15 by ehlxr 2022-03-12 16:13:15 +08:00
4c3ee5fcf4 update at 2022-03-07 07:37:20 by ehlxr 2022-03-07 07:37:20 +08:00
3c8752be70 update at 2022-03-05 17:05:21 by ehlxr 2022-03-05 17:05:21 +08:00
226c572e59 update at 2022-03-04 10:14:44 by ehlxr 2022-03-04 10:14:44 +08:00
4a6bd38732 update at 2022-03-04 09:59:22 by ehlxr 2022-03-04 09:59:22 +08:00
beb3a22fdd add binary search algo 2022-01-02 00:25:11 +08:00
0f081ad1db update at 2022-01-01 22:41:42 by ehlxr 2022-01-01 22:41:42 +08:00
de07e89bb8 binary search 2022-01-01 18:18:30 +08:00
e230636a54 update at 2021-12-29 00:21:10 by ehlxr 2021-12-29 00:21:10 +08:00
83d334356b update at 2021-12-28 20:33:27 by ehlxr 2021-12-28 20:33:27 +08:00
f69a0267c4 update at 2021-12-28 10:08:53 by ehlxr 2021-12-28 10:08:53 +08:00
987e56909c update at 2021-12-25 23:23:33 by ehlxr 2021-12-25 23:23:33 +08:00
3aaabd8b6d update at 2021-12-25 22:49:21 by ehlxr 2021-12-25 22:49:21 +08:00
1b10985030 update at 2021-12-25 21:55:15 by ehlxr 2021-12-25 21:55:15 +08:00
c72ced990f refactor 2021-12-25 17:02:00 +08:00
9107b0c4ba update at 2021-12-23 22:20:16 by ehlxr 2021-12-23 22:20:16 +08:00
4bacec63a3 update at 2021-12-23 22:17:46 by ehlxr 2021-12-23 22:17:46 +08:00
78d8ad252b update at 2021-11-01 10:07:28 by ehlxr 2021-11-01 10:07:28 +08:00
d51106271e add dp 2021-10-31 23:22:24 +08:00
947d81a5b5 update at 2021-09-22 16:57:07 by ehlxr 2021-09-22 16:57:07 +08:00
af2221682c add function class 2021-09-16 14:02:08 +08:00
8f2e5d0b62 update at 2021-09-15 09:13:10 by ehlxr 2021-09-15 09:13:10 +08:00
dba3de0be2 update at 2021-09-12 21:03:19 by ehlxr 2021-09-12 21:03:19 +08:00
42da65cf47 refactor 2021-09-01 10:58:56 +08:00
aa73622a34 okhttp add trust all client 2021-08-31 18:35:35 +08:00
f601c051d4 add redis lock test 2021-08-30 10:14:08 +08:00
9d6a001b85 refactor 2021-08-29 23:16:35 +08:00
cc5cbc1ebb change to springboot 2021-08-29 12:23:13 +08:00
e76d89f774 update at 2021-08-12 23:15:14 by ehlxr 2021-08-12 23:15:14 +08:00
ee6f67a6ab add sort coast time test 2021-08-01 20:55:49 +08:00
b3dbc9f668 update at 2021-07-16 10:48:40 by ehlxr 2021-07-16 10:48:40 +08:00
163882bb4d update at 2021-07-16 09:37:58 by ehlxr 2021-07-16 09:37:58 +08:00
3947896a04 Merge branch 'master' of github.com:ehlxr/budd 2021-07-16 09:35:26 +08:00
d3b548c8b4 add SlideWindow 2021-07-15 23:01:08 +08:00
cc013f3b86 add SlideWindow 2021-07-15 22:05:54 +08:00
e106affde0 add SlideWindow 2021-07-15 22:04:29 +08:00
7aca97aa2e update at 2021-07-15 21:46:50 by ehlxr 2021-07-15 21:46:50 +08:00
2f74ee2c8c update at 2021-07-15 18:35:46 by ehlxr 2021-07-15 18:35:46 +08:00
0b5acb84ab add mergesort time test 2021-07-03 13:11:51 +08:00
dccb21493b add quicksort time test 2021-07-02 22:40:15 +08:00
7cfdaab3d0 add sort coast time test 2021-06-29 21:21:03 +08:00
bf4d8c5fb9 add sort coast time test 2021-06-29 18:39:19 +08:00
5865722a7d add sort coast time test 2021-06-29 18:20:12 +08:00
165f099240 add sort test 2021-06-28 22:13:54 +08:00
f581b143dc update at 2021-06-09 09:14:40 by ehlxr 2021-06-09 09:14:40 +08:00
8d2f0d57b5 update at 2021-06-08 23:36:39 by ehlxr 2021-06-08 23:36:39 +08:00
1fb0c52138 update at 2021-05-28 22:48:00 by ehlxr 2021-05-28 22:48:00 +08:00
3b5b3b50a9 update at 2021-05-24 23:12:21 by ehlxr 2021-05-24 23:12:21 +08:00
f5ff83737c Merge branch 'master' of github.com:ehlxr/budd 2021-05-14 16:26:08 +08:00
59c2bd2e3c update at 2021-05-14 16:25:51 by ehlxr 2021-05-14 16:25:51 +08:00
367798c0dc Create SECURITY.md 2021-04-23 09:26:59 +08:00
d194341936 Merge pull request #14 from ehlxr/dependabot/maven/org.mybatis-mybatis-3.5.6
Bump mybatis from 3.2.7 to 3.5.6
2021-04-23 09:26:08 +08:00
dependabot[bot]
3ee99909b8 Bump mybatis from 3.2.7 to 3.5.6
Bumps [mybatis](https://github.com/mybatis/mybatis-3) from 3.2.7 to 3.5.6.
- [Release notes](https://github.com/mybatis/mybatis-3/releases)
- [Commits](https://github.com/mybatis/mybatis-3/compare/mybatis-3.2.7...mybatis-3.5.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-22 16:43:53 +00:00
2584e13e20 add linked list stack 2021-04-16 09:27:46 +08:00
612feb1e9e add linked list stack 2021-04-16 09:05:48 +08:00
6c8b22b204 add linked list stack 2021-04-15 23:43:44 +08:00
fa4748c57c add josephu question 2021-04-13 22:16:11 +08:00
lixiangrong
16dad8f7b6 add jsephu 2021-04-09 22:35:08 +08:00
lixiangrong
d8a328c472 update at 2021-04-07 22:21:36 by ehlxr 2021-04-07 22:21:36 +08:00
lixiangrong
b83d324c54 add doubleLinkedList 2021-04-07 21:14:47 +08:00
lixiangrong
522969e077 update at 2021-04-06 09:36:50 by ehlxr 2021-04-06 09:36:50 +08:00
lixiangrong
19161217b7 update at 2021-04-05 22:30:28 by ehlxr 2021-04-05 22:30:28 +08:00
lixiangrong
2953e48009 reverse linkedlist 2021-04-04 22:32:26 +08:00
lixiangrong
69d714f19a update at 2021-04-04 16:31:55 by ehlxr 2021-04-04 16:31:55 +08:00
de91226dba Merge pull request #12 from ehlxr/dependabot/maven/com.fasterxml.jackson.core-jackson-databind-2.10.5.1
Bump jackson-databind from 2.10.3 to 2.10.5.1
2021-04-02 12:50:40 +08:00
7403cea6a7 Merge pull request #13 from ehlxr/dependabot/maven/com.google.guava-guava-29.0-jre
Bump guava from 28.2-jre to 29.0-jre
2021-04-02 12:50:30 +08:00
dependabot[bot]
6a59bac8b9 Bump guava from 28.2-jre to 29.0-jre
Bumps [guava](https://github.com/google/guava) from 28.2-jre to 29.0-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-31 18:50:49 +00:00
7697a84edf add array queue 2021-03-30 23:17:07 +08:00
dependabot[bot]
9f737f1a45 Bump jackson-databind from 2.10.3 to 2.10.5.1
Bumps [jackson-databind](https://github.com/FasterXML/jackson) from 2.10.3 to 2.10.5.1.
- [Release notes](https://github.com/FasterXML/jackson/releases)
- [Commits](https://github.com/FasterXML/jackson/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-02-18 21:47:29 +00:00
229 changed files with 6111 additions and 15904 deletions

5
.gitignore vendored
View File

@@ -7,9 +7,10 @@
target
*.project
*.classpath
/.settings
**/.settings
/bin
/useful-code.iml
/.idea
/resources/debug.log
*.iml
*.iml
budd-common/.settings

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright © 2020 xrv <xrg@live.com>
Copyright © 2022 xrv <xrv@live.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -6,3 +6,7 @@
[![](https://badgen.net/github/releases/ehlxr/budd)](https://github.com/ehlxr/budd/releases)
常用的一些 Java 代码
## Thanks to the following organizations for providing open source licenses
[<img src="https://github.com/ehlxr/budd/blob/master/jetbrains.svg" width = "200" height = "217" alt="jetbrains" align=center />](https://jb.gg/OpenSource)

55
budd-common/pom.xml Normal file
View File

@@ -0,0 +1,55 @@
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>budd-common</artifactId>
<name>budd-common</name>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,123 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm;
/**
* @author ehlxr
* @since 2021-12-28 23:16.
*/
public class FindKthLargest {
public static void main(String[] args) {
int[] nums = new int[]{3, 2, 1, 5, 6, 4};
System.out.println(findKthLargest(nums, 2));
}
public static int findKthLargest2(int[] nums, int k) {
for (int i = nums.length / 2 - 1; i >= 0; i--) {
// 从第一个非叶子结点从下至上,从右至左调整结构
adjustHeap(nums, i, nums.length);
}
for (int j = nums.length - 1; j >= 0; j--) {
k--;
if (k == 0) {
return nums[0];
}
swap(nums, 0, j);
adjustHeap(nums, 0, j);
}
return 0;
}
public static void adjustHeap(int[] arr, int i, int length) {
// 先取出当前元素 i
int temp = arr[i];
// 从 i 结点的左子结点开始,也就是 2i+1 处开始
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
// 如果左子结点小于右子结点k 指向右子结点
if (k + 1 < length && arr[k] < arr[k + 1]) {
k++;
}
// 如果子节点大于父节点,将子节点和父节点交换
// if (arr[k] > arr[i]) {
// swap(arr, k, i);
if (arr[k] > temp) {
// 不用进行交换
arr[i] = arr[k];
i = k;
} else {
break;
}
}
// 将 temp 值放到最终的位置
arr[i] = temp;
}
public static int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length < k) {
return -1;
}
int q = partition(nums, 0, nums.length - 1);
while (q + 1 != k) {
if (k < q + 1) {
q = partition(nums, 0, q - 1);
} else {
q = partition(nums, q + 1, nums.length - 1);
}
}
return nums[q];
}
public static int partition(int[] a, int p, int r) {
int pivot = a[r];
int i = p;
for (int j = p; j < r; j++) {
if (a[j] >= pivot) {
swap(a, i++, j);
}
}
swap(a, i, r);
return i;
}
private static void swap(int[] a, int i, int j) {
if (i == j) {
return;
}
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}

View File

@@ -0,0 +1,86 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm;
import java.util.HashMap;
import java.util.Map;
/**
* @author ehlxr
* @since 2022-04-29 11:07.
*/
public class MinWindow {
public static void main(String[] args) {
System.out.println(minWindow("cabwefgewcwaefgcf", "cae"));
System.out.println(minWindow("bba", "ab"));
System.out.println(minWindow("ADOBECODEBANC", "ABC"));
System.out.println(minWindow("a", "a"));
System.out.println(minWindow("a", "b"));
System.out.println(minWindow("", "a"));
System.out.println(minWindow("", ""));
System.out.println(minWindow("a", "aa"));
System.out.println(minWindow("aa", "a"));
}
public static String minWindow(String s, String t) {
Map<Character, Integer> windows = new HashMap<>();
Map<Character, Integer> needs = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
needs.put(t.charAt(i), needs.getOrDefault(t.charAt(i), 0) + 1);
}
int left = 0, right = 0, valid = 0, start = -1, len = Integer.MAX_VALUE;
while (right < s.length()) {
char r = s.charAt(right);
if (needs.containsKey(r)) {
windows.put(r, windows.getOrDefault(r, 0) + 1);
if (windows.get(r).equals(needs.get(r))) {
valid++;
}
}
right++;
while (valid == needs.size()) {
if (right - left < len) {
len = right - left;
start = left;
}
char l = s.charAt(left);
left++;
if (windows.containsKey(l)) {
if (windows.get(l).equals(needs.get(l))) {
valid--;
}
windows.put(l, windows.get(l) - 1);
}
}
}
return start > -1 ? s.substring(start, start + len) : "";
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,45 +22,49 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.proxy;
package io.github.ehlxr.algorithm;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
* 全排列
*
* @author ehlxr
* @since 2019-06-28.
* @since 2022-04-20 16:42.
*/
public class Main {
public class Permutation {
static List<List<Integer>> res = new ArrayList<>();
public static void main(String[] args) {
Flyable proxy = (Flyable) Proxy.newProxyInstance(Flyable.class.getClassLoader(),
new Class[]{Flyable.class}, new MyInvocationHandler(new Bird()));
// 动态代理会生成类似以下的 Java 代码
/*
package me.ehlxr.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Proxy implements Flyable {
private InvocationHandler handler;
public Proxy(InvocationHandler handler) {
this.handler = handler;
}
@Override
public void fly() {
try {
Method method = Flyable.class.getMethod("fly");
this.handler.invoke(this, method, null);
} catch (Throwable e) {
e.printStackTrace();
}
int[] arr = {1, 2, 3};
for (List<Integer> r : permute(arr)) {
for (int i : r) {
System.out.print(i + " ");
}
System.out.println();
}
*/
}
proxy.fly();
public static List<List<Integer>> permute(int[] nums) {
List<Integer> track = new ArrayList<>();
backtrack(nums, track);
return res;
}
public static void backtrack(int[] nums, List<Integer> track) {
// 回溯结束条件
if (track.size() == nums.length) {
res.add(new ArrayList<>(track));
return;
}
for (int num : nums) {
if (track.contains(num)) {
continue;
}
track.add(num);
backtrack(nums, track);
track.remove(track.size() - 1);
}
}
}

View File

@@ -0,0 +1,106 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.binarytree.heap;
import java.util.Arrays;
/**
* @author ehlxr
* @since 2022-03-15 07:40.
*/
public class Heap {
private static void createHeap(int[] a) {
int n = a.length - 1; // 最后一个叶子节点下标
buildHeap(a, n);
}
private static void buildHeap(int[] a, int n) {
// (n - 1) / 2 表示最后一个叶子节点父节点,即为最后一个非叶子节点
for (int i = (n - 1) / 2; i >= 0; --i) {
heapify(a, n, i);
}
}
/**
* 堆化
*
* @param a 数组
* @param n 最后一个元素下标
* @param i 需要调整的父节点下标
*/
private static void heapify(int[] a, int n, int i) {
while (true) {
int max = i;
// 从当前节点和左右叶子节点中找出最大的
int l = 2 * i + 1;
if (l <= n && a[l] > a[max]) {
max = l;
}
int r = 2 * i + 2;
if (r <= n && a[r] > a[max]) {
max = r;
}
// 当前节点最大时退出
if (max == i) {
break;
}
swap(a, i, max);
// 最大节点和当前节点交换后,继续以当前节点为父节点堆化
i = max;
}
}
/**
* 堆排序
*/
private static void sort(int[] a) {
for (int i = a.length - 1; i > 0; i--) {
buildHeap(a, i);
// 堆顶元素和最后一个元素交换,除过最后一个元素外其它元素再次构建大顶堆
swap(a, 0, i);
}
}
public static void main(String[] args) {
int[] arr = new int[]{1, 2, 3, 4, 5, 6};
createHeap(arr);
System.out.println(Arrays.toString(arr));
sort(arr);
System.out.println(Arrays.toString(arr));
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}

View File

@@ -0,0 +1,65 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.dp;
/**
* 在一个数组 arr 中,找出一组不相邻的数字,使得最后的和最大
* <p>
* 图解 https://cdn.jsdelivr.net/gh/0vo/oss/images/dp.jpg
*
* @author ehlxr
* @since 2021-10-31 22:46.
*/
public class FindMaxSum {
public static int recOpt(int[] arr, int i) {
if (i == 0) {
return arr[0];
} else if (i == 1) {
return Math.max(arr[0], arr[1]);
} else {
int a = recOpt(arr, i - 2) + arr[i];
int b = recOpt(arr, i - 1);
return Math.max(a, b);
}
}
public static int dpOpt(int[] arr) {
int[] opt = new int[arr.length];
opt[0] = arr[0];
opt[1] = Math.max(arr[0], arr[1]);
for (int i = 2; i < opt.length; i++) {
int a = opt[i - 2] + arr[i];
int b = opt[i - 1];
opt[i] = Math.max(a, b);
}
return opt[arr.length - 1];
}
public static void main(String[] args) {
int[] arr = {4, 1, 1, 9, 1};
System.out.println(dpOpt(arr));
System.out.println(recOpt(arr, arr.length - 1));
}
}

View File

@@ -0,0 +1,126 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.dp;
/**
* 对于一组不同重量、不同价值、不可分割的物品,我们选择将某些物品装入背包,在满足背包最大重量限制的前提下,背包中可装入物品的总价值最大是多少呢?
*
* @author ehlxr
* @since 2022-03-05 14:31.
*/
public class KnapSack {
private final int[] weight = {2, 2, 4, 6, 3}; // 物品的重量
private final int[] value = {3, 4, 8, 9, 6}; // 物品的价值
private final int n = 5; // 物品个数
private final int w = 9; // 背包承受的最大重量
private int maxV = Integer.MIN_VALUE; // 结果放到 maxV 中
public static void main(String[] args) {
System.out.println(knapsack3(new int[]{2, 2, 4, 6, 3}, new int[]{3, 4, 8, 9, 6}, 5, 9));
// System.out.println(knapsack(new int[]{2, 2, 4, 6, 3}, new int[]{3, 4, 8, 9, 6}, 5, 9));
}
/**
* 动态规划方式
*
* @param weight 物品重量
* @param value 物品的价值
* @param n 物品个数
* @param w 背包可承载重量
* @return 最大价值
*/
// public static int knapsack(int[] weight, int[] value, int n, int w) {
// int[][] dp = new int[][];
// }
/**
* 动态规划方式
*
* @param weight 物品重量
* @param value 物品的价值
* @param n 物品个数
* @param w 背包可承载重量
* @return 最大价值
*/
public static int knapsack3(int[] weight, int[] value, int n, int w) {
int[][] states = new int[n][w + 1];
for (int i = 0; i < n; ++i) { // 初始化 states,默认 -1
for (int j = 0; j < w + 1; ++j) {
states[i][j] = -1;
}
}
states[0][0] = 0;
if (weight[0] <= w) {
states[0][weight[0]] = value[0];
}
for (int i = 1; i < n; ++i) { // 动态规划,状态转移
for (int j = 0; j <= w; ++j) { // 不选择第 i 个物品
if (states[i - 1][j] >= 0) {
// 复制上一层状态
states[i][j] = states[i - 1][j];
}
}
// 下面的 j 表示重量
for (int j = 0; j <= w - weight[i]; ++j) { // 选择第 i 个物品
if (states[i - 1][j] >= 0) { // 表示上一层存在重量为 j 的状态
int v = states[i - 1][j] + value[i]; // 上一层重量为 j 的价值 + i 物品的价值
if (v > states[i][j + weight[i]]) { // states[i][j + weight[i]]:存储当前重量 j + 物品 i 的重量所在位置的价值
states[i][j + weight[i]] = v;
}
}
}
}
// 找出最大值
int maxvalue = -1;
for (int j = 0; j <= w; ++j) {
if (states[n - 1][j] > maxvalue) {
maxvalue = states[n - 1][j];
}
}
return maxvalue;
}
/**
* 回溯方式
*
* @param i 第几个物品
* @param cw 物品的重量
* @param cv 物品的价值
*/
public void f(int i, int cw, int cv) { // 调用 f (0, 0, 0)
if (cw == w || i == n) { //cw==w 表示装满了,i==n 表示物品都考察完了
if (cv > maxV) {
maxV = cv;
}
return;
}
f(i + 1, cw, cv); // 选择不装第 i 个物品
if (cw + weight[i] <= w) {
f(i + 1, cw + weight[i], cv + value[i]); // 选择装第 i 个物品
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.dp;
/**
* 假设我们有一个 n 乘以 n 的矩阵 w [n][n]。矩阵存储的都是正整数。棋子起始位置在左上角,终止位置在右下角。
* 我们将棋子从左上角移动到右下角。每次只能向右或者向下移动一位。从左上角到右下角,会有很多不同的路径可以走。
* 我们把每条路径经过的数字加起来看作路径的长度。那从左上角移动到右下角的最短路径长度是多少呢?
*
* @author ehlxr
* @since 2022-03-05 16:46.
*/
public class MinDist {
private final int[][] matrix = {{1, 3, 5, 9}, {2, 1, 3, 4}, {5, 2, 6, 7}, {6, 8, 4, 3}};
private final int[][] mem = new int[4][4];
private int minDist = Integer.MAX_VALUE; // 全局变量或者成员变量
/**
* 动态规划:状态转移表法
*/
public int minDistDP(int[][] matrix, int n) {
int[][] states = new int[n][n];
int sum = 0;
for (int j = 0; j < n; ++j) { // 初始化states的第一行数据
sum += matrix[0][j];
states[0][j] = sum;
}
sum = 0;
for (int i = 0; i < n; ++i) { // 初始化states的第一列数据
sum += matrix[i][0];
states[i][0] = sum;
}
for (int i = 1; i < n; ++i) {
for (int j = 1; j < n; ++j) {
states[i][j] = matrix[i][j] + Math.min(states[i][j - 1], states[i - 1][j]);
}
}
return states[n - 1][n - 1];
}
/**
* 动态规划:状态转移方程法
*/
public int minDist(int i, int j) { // 调用minDist(n-1, n-1);
if (i == 0 && j == 0) {
return matrix[0][0];
}
// 备忘录,如果计算过,即有数字存在,则直接返回
if (mem[i][j] > 0) {
return mem[i][j];
}
int minLeft = Integer.MAX_VALUE;
if (j - 1 >= 0) {
minLeft = minDist(i, j - 1);
}
int minUp = Integer.MAX_VALUE;
if (i - 1 >= 0) {
minUp = minDist(i - 1, j);
}
int currMinDist = matrix[i][j] + Math.min(minLeft, minUp);
mem[i][j] = currMinDist;
return currMinDist;
}
/**
* 回溯方式
*/
public void minDistBacktracing(int i, int j, int dist, int[][] w, int n) {
// 到达了n-1, n-1这个位置了这里看着有点奇怪哈你自己举个例子看下
if (i == n && j == n) {
if (dist < minDist) {
minDist = dist;
}
return;
}
if (i < n) { // 往下走更新i=i+1, j=j
minDistBacktracing(i + 1, j, dist + w[i][j], w, n);
}
if (j < n) { // 往右走更新i=i, j=j+1
minDistBacktracing(i, j + 1, dist + w[i][j], w, n);
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.linkedlist;
/**
* @author ehlxr
* @since 2022-05-01 14:18.
*/
public class FindKthFromEnd {
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
head.next.next.next.next.next = new ListNode(6);
System.out.println(head);
System.out.println(findKthFromEnd(head, 1));
System.out.println(findKthFromEnd2(head, 1));
}
public static ListNode findKthFromEnd(ListNode head, int k) {
int n = 0;
ListNode node = head;
ListNode p = null;
while (node != null) {
if (p != null) {
p = p.next;
}
n++;
if (n == k) {
p = head;
}
node = node.next;
}
return p;
}
public static ListNode findKthFromEnd2(ListNode head, int k) {
ListNode p = head;
ListNode q = head;
for (int i = 0; i < k; i++) {
q = q.next;
}
while (q != null) {
p = p.next;
q = q.next;
}
return p;
}
}

View File

@@ -0,0 +1,105 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.linkedlist;
/**
* @author ehlxr
* @since 2022-04-15 08:41.
*/
public class Leecode21 {
public static void main(String[] args) {
ListNode list1 = new ListNode(1);
ListNode list2 = new ListNode(2);
ListNode list3 = new ListNode(4);
list1.next = list2;
list2.next = list3;
ListNode list4 = new ListNode(1);
ListNode list5 = new ListNode(3);
ListNode list6 = new ListNode(4);
list4.next = list5;
list5.next = list6;
ListNode list7 = mergeTwoLists(list1, list4);
while (list7 != null) {
System.out.println(list7.val);
list7 = list7.next;
}
}
public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode res = new ListNode();
ListNode tmp = res;
while (list1 != null || list2 != null) {
if (list1 == null) {
tmp.next = list2;
break;
}
if (list2 == null) {
tmp.next = list1;
break;
}
if (list1.val < list2.val) {
tmp.next = list1;
list1 = list1.next;
} else {
tmp.next = list2;
list2 = list2.next;
}
tmp = tmp.next;
}
return res.next;
}
public static ListNode mergeTwoLists2(ListNode l1, ListNode l2) {
// 虚拟头结点
ListNode dummy = new ListNode(-1), p = dummy;
ListNode p1 = l1, p2 = l2;
while (p1 != null && p2 != null) {
// 比较 p1 和 p2 两个指针
// 将值较小的的节点接到 p 指针
if (p1.val > p2.val) {
p.next = p2;
p2 = p2.next;
} else {
p.next = p1;
p1 = p1.next;
}
// p 指针不断前进
p = p.next;
}
if (p1 != null) {
p.next = p1;
}
if (p2 != null) {
p.next = p2;
}
return dummy.next;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +22,11 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.leetcode;
package io.github.ehlxr.algorithm.linkedlist;
/**
* 链表结构
*
* @author ehlxr
* @since 2021-02-27 21:09.
* @since 2022-12-04 22:25.
*/
public class ListNode {
int val;
@@ -53,4 +51,4 @@ public class ListNode {
", next=" + next +
'}';
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.linkedlist;
/**
* 判断单链表是否是回文
*
* @author ehlxr
* @since 2022-12-03 23:11.
*/
public class Palindrome {
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(2);
head.next.next.next.next = new ListNode(1);
System.out.println(head);
System.out.println(isPalindrome(head));
head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(3);
head.next.next.next.next = new ListNode(2);
head.next.next.next.next.next = new ListNode(1);
System.out.println(head);
System.out.println(isPalindrome(head));
}
/**
* slow, fast 双指针slow 前进一步fast 前进两步,当 fast 到达链表尾部时slow 处于链表中间
* 与此同时反转链表前半部分head 到中间节点部分)
*/
public static boolean isPalindrome(ListNode head) {
if (head == null) {
return false;
}
ListNode slow = head, fast = head, pre = null;
while (fast != null && fast.next != null) {
fast = fast.next.next;
ListNode tmp = slow.next;
slow.next = pre;
pre = slow;
slow = tmp;
// slow = slow.next;
}
if (fast != null) {
// 节点个数为奇数
slow = slow.next;
}
System.out.println("中间节点:" + slow);
System.out.println("中位点反转:" + pre);
while (pre != null) {
if (pre.val != slow.val) {
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,42 +22,47 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.leetcode;
import java.util.Arrays;
import java.util.PriorityQueue;
package io.github.ehlxr.algorithm.linkedlist;
/**
* @author ehlxr
* @since 2020-10-20 17:54.
* @since 2022-05-03 14:26.
*/
public class Solution5 {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
for (int val : nums) {
queue.add(val);
if (queue.size() > k) {
queue.poll();
}
}
return queue.peek();
}
public class ReverseKGroup {
public static void main(String[] args) {
int[] arr = {4, 6, 8, 5, 9};
// PriorityQueue<Integer> queue = new PriorityQueue<>();
// for (int val : arr) {
// queue.add(val);
// }
// System.out.println(Arrays.toString(queue.toArray()));
//
//
// arr = new int[]{4, 6, 8, 5, 9};
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(arr.length, (o1, o2) -> o2 - o1);
for (int val : arr) {
maxHeap.add(val);
}
System.out.println(Arrays.toString(maxHeap.toArray()));
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
System.out.println(head);
System.out.println(reverseKGroup(head, 2));
}
public static ListNode reverseKGroup(ListNode head, int k) {
ListNode p = head;
for (int i = 0; i < k; i++) {
if (p == null) {
return head;
}
p = p.next;
}
ListNode r = reverseN(head, p);
head.next = reverseKGroup(p, k);
return r;
}
public static ListNode reverseN(ListNode head, ListNode n) {
ListNode cur = head, pre = null;
while (cur != n) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}

View File

@@ -0,0 +1,101 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.linkedlist;
/**
* 反转单链表
*
* @author ehlxr
* @since 2022-03-14 07:05.
*/
public class ReverseLinkedList {
public static void main(String[] args) {
ListNode ListNode5 = new ListNode(5, null);
ListNode ListNode4 = new ListNode(4, ListNode5);
ListNode ListNode3 = new ListNode(3, ListNode4);
ListNode ListNode2 = new ListNode(2, ListNode3);
ListNode head = new ListNode(1, ListNode2);
// ListNode reverse = reverse(root);
// reverse.print();
// System.out.println(reverseToN(head, ListNode3));
// System.out.println(reverseToN(head, 2));
System.out.println(reverseFm2N(head, 2, 4));
}
public static ListNode reverseToN(ListNode root, ListNode n) {
ListNode pre = null, cur = root, tmp = root;
while (cur != n) {
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
static ListNode next = null;
public static ListNode reverseToN(ListNode root, int n) {
if (n == 1) {
next = root.next;
return root;
}
ListNode h = reverseToN(root.next, n - 1);
root.next.next = root;
root.next = next;
return h;
}
public static ListNode reverseFm2N(ListNode root, int m, int n) {
if (m == 1) {
return reverseToN(root, n);
}
root.next = reverseFm2N(root.next, m - 1, n - 1);
return root;
}
public static ListNode reverse(ListNode root) {
ListNode pre = null;
ListNode cur = root;
while (cur != null) {
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
// tmp = cur.next;
}
return pre;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,33 +22,45 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
package io.github.ehlxr.algorithm.match;
/**
* 字符串匹配暴力匹配
*
* @author ehlxr
* @date 2016/12/22
* @since 2022-03-12 13:36.
*/
//@SuppressWarnings({"AlibabaRemoveCommentedCode", "Convert2Lambda", "UnnecessaryLocalVariable"})
public class ThreadPoolExecutorTest {
public class BruteForce {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
//try {
// Thread.sleep(index * 1000);
//} catch (InterruptedException e) {
// e.printStackTrace();
//}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
//System.out.println(index);
System.out.println("Thread: " + Thread.currentThread().getName());
String s = "abdcfhjudfadf";
String p = "dcf";
System.out.println(bf(s, p));
}
public static int bf(String s, String p) {
int m = s.length();
int n = p.length();
for (int i = 0; i <= m - n; i++) {
int j = 0;
for (; j < n; j++) {
// if (s.charAt(i) == p.charAt(j)) {
// i++;
// } else {
// break;
// }
// 如果主串与模式串不匹配则主串向右移动一个字符,模式串从头开始匹配
if (s.charAt(i + j) != p.charAt(j)) {
break;
}
});
}
if (j == n) {
// return i - n;
return i;
}
}
return -1;
}
}

View File

@@ -0,0 +1,123 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.match;
import java.util.Arrays;
/**
* 字符串匹配算法 KPM
*
* @author ehlxr
* @since 2022-03-13 10:06.
*/
public class Kmp {
public static void main(String[] args) {
String s = "bacbababaabcbab";
String p = "abab";
System.out.println(Arrays.toString(getNexts(p)));
System.out.println(kmp(s, p));
}
public static int kmp(String s, String p) {
char[] scs = s.toCharArray();
char[] pcs = p.toCharArray();
int m = s.length();
int n = p.length();
int[] next = getNexts(p);
for (int i = 0; i <= m - n; i++) {
int j = 0;
// while (j < n) {
// if (scs[i] == pcs[j]) {
// i++;
// j++;
// } else {
// // 当模式串与主串不匹配时,如果**不匹配字符**对应模式串下标大于 j > 0 (非首个模式串字符)
// // 并且此字符前一个字符对应字符串部分匹配表中的值 next[j - 1] 也大于 0
// // j - next[j - 1] 即模式串为后移的位数,等价于 j 置为 next[j - 1]
// if (j > 0 && next[j - 1] > 0) {
// j = next[j - 1];
// } else {
// break;
// }
// }
// }
// if (j == n) {
// return i - n;
// }
for (; j < n; j++) {
if (scs[i + j] != pcs[j]) {
// 暴力匹配算法当模式串和主串不匹配时,主串匹配下标 +1模式串匹配下标置为 0
// KMP 算法优化点在于将模式串下标置为不匹配字符前一个字符对应 next 数组的值
if (j > 0 && next[j - 1] > 0) {
// 当模式串与主串不匹配时,如果**不匹配字符**对应模式串下标大于 j > 0 (非首个模式串字符)
// 并且此字符前一个字符对应字符串部分匹配表中的值 next[j - 1] 也大于 0
// j - next[j - 1] 即模式串为后移的位数,等价于 j 置为 next[j - 1]
j = next[j - 1];
} else {
break;
}
}
}
if (j == n) {
return i;
}
}
return -1;
}
private static int[] getNexts(String p) {
int m = p.length();
char[] b = p.toCharArray();
int[] next = new int[m];
next[0] = 0;
int k = 0; // 表示前后缀相匹配的最大长度
// 根据已知 next 数组的前 i-1 位推测第 i 位
for (int i = 1; i < m; ++i) {
while (k != 0 && b[k] != b[i]) {
// k 为 b[0, i) 子串最大匹配前后缀长度
// b[0, k) 为 b[0, i) 子串最大匹配前缀子串
// 若1、b[k] != b[i],则求 b[0, i] 子串最大匹配前后缀长度问题
// 转换成了求 b[0, k) 子串最大匹配前后缀长度问题
// 循环直到 b[k] == b[i] (下一步处理) 或 k == 0
k = next[k];
}
// 若2、b[k] == b[i],则 b[0, i] 子串最大匹配前后缀长度为 k + 1
if (b[k] == b[i]) {
++k;
}
next[i] = k;
}
return next;
}
}

View File

@@ -0,0 +1,207 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.search;
/**
* @author ehlxr
* @since 2022-01-01 17:06.
*/
public class BinarySearch {
public static void main(String[] args) {
int[] a = new int[]{1, 3, 5, 6, 7, 8, 9};
System.out.println(search(a, a.length, 3));
System.out.println(searchRec(a, a.length, 3));
a = new int[]{1, 2, 2, 2, 2, 5, 6, 7, 8, 9};
System.out.println(searchFirst(a, a.length, 2));
a = new int[]{1, 3, 4, 5, 6, 8, 8, 8, 9};
System.out.println(searchLast(a, a.length, 8));
a = new int[]{1, 2, 2, 3, 4, 5, 6, 7, 8, 8, 9};
System.out.println(searchFirstGreater(a, a.length, 7));
a = new int[]{1, 2, 3, 4, 5, 6, 8, 9};
System.out.println(searchLastLess(a, a.length, 7));
}
/**
* 非递归二分查找
*
* @param a 要查找的数组
* @param n 数组的长度
* @param v 要查找的值
* @return 要查找值在数组中的索引
*/
public static int search(int[] a, int n, int v) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] == v) {
return mid;
} else if (a[mid] < v) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
/**
* 递归二分查找
*
* @param a 要查找的数组
* @param n 数组的长度
* @param v 要查找的值
* @return 要查找值在数组中的索引
*/
public static int searchRec(int[] a, int n, int v) {
return searchRec(a, 0, n - 1, v);
}
/**
* 递归二分查找
*/
public static int searchRec(int[] a, int low, int high, int v) {
if (low > high) {
return -1;
}
int mid = low + ((high - low) >> 1);
if (a[mid] == v) {
return mid;
} else if (a[mid] < v) {
return searchRec(a, mid + 1, high, v);
} else {
return searchRec(a, low, mid - 1, v);
}
}
/**
* 查找第一个值等于给定值的元素
*
* @param a 要查找的数组
* @param n 数组的长度
* @param v 要查找的值
* @return 要查找值在数组中的索引
*/
public static int searchFirst(int[] a, int n, int v) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] == v) {
if (mid == 0 || a[mid - 1] != v) {
return mid;
} else {
high = mid - 1;
}
} else if (a[mid] < v) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
/**
* 查找最后一个值等于给定值的元素
*
* @param a 要查找的数组
* @param n 数组的长度
* @param v 要查找的值
* @return 要查找值在数组中的索引
*/
public static int searchLast(int[] a, int n, int v) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] == v) {
if (mid == n - 1 || a[mid + 1] != v) {
return mid;
} else {
low = mid + 1;
}
} else if (a[mid] < v) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
/**
* 查找第一个大于等于给定值的元素
*
* @param a 要查找的数组
* @param n 数组的长度
* @param v 要查找的值
* @return 要查找值在数组中的索引
*/
public static int searchFirstGreater(int[] a, int n, int v) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] < v) {
low = mid + 1;
} else {
if (mid == 0 || a[mid - 1] < v) {
return mid;
} else {
high = mid - 1;
}
}
}
return -1;
}
/**
* 查找最后一个小于等于给定值的元素
*
* @param a 要查找的数组
* @param n 数组的长度
* @param v 要查找的值
* @return 要查找值在数组中的索引
*/
public static int searchLastLess(int[] a, int n, int v) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > v) {
high = mid - 1;
} else {
if (mid == n - 1 || a[mid + 1] > v) {
return mid;
} else {
low = mid + 1;
}
}
}
return -1;
}
}

View File

@@ -0,0 +1,111 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.sort;
import java.util.Arrays;
/**
* @author ehlxr
* @since 2021-12-27 19:06.
*/
public class MergeSort {
public static void main(String[] args) {
int[] arrs = new int[]{3, 2, 5, 7, 1, 9};
System.out.println(Arrays.toString(sort(arrs)));
System.out.println(Arrays.toString(sort2(arrs)));
}
public static int[] sort(int[] arrs) {
if (arrs.length <= 1) {
return arrs;
}
int[] a1 = sort(Arrays.copyOfRange(arrs, 0, arrs.length / 2));
int[] a2 = sort(Arrays.copyOfRange(arrs, arrs.length / 2, arrs.length));
return merge(a1, a2);
}
public static int[] merge(int[] a1, int[] a2) {
int i = 0;
int j = 0;
int[] result = new int[a1.length + a2.length];
int k = 0;
while (i < a1.length || j < a2.length) {
int temp;
if (i >= a1.length) {
temp = a2[j++];
} else if (j >= a2.length) {
temp = a1[i++];
} else if (a1[i] <= a2[j]) {// 为了保证算法的稳定性,如果 a1、a2 有相同的元素,保证 a1 的元素在前面
temp = a1[i++];
} else {
temp = a2[j++];
}
result[k] = temp;
k++;
}
return result;
}
public static int[] sort2(int[] a) {
if (a == null || a.length <= 1) {
return a;
}
return merge2(sort2(Arrays.copyOfRange(a, 0, a.length / 2)),
sort2(Arrays.copyOfRange(a, a.length / 2, a.length)));
}
public static int[] merge2(int[] a, int[] b) {
int[] r = new int[a.length + b.length];
int i = 0;
int j = 0;
int m = 0;
while (i < a.length || j < b.length) {
if (i >= a.length) {
r[m++] = b[j++];
continue;
}
if (j >= b.length) {
r[m++] = a[i++];
continue;
}
if (a[i] < b[j]) {
r[m++] = a[i++];
} else {
r[m++] = b[j++];
}
}
return r;
}
}

View File

@@ -0,0 +1,116 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.algorithm.sort;
import java.util.Arrays;
/**
* @author ehlxr
* @since 2021-12-28 19:57.
*/
public class QuickSort {
public static void main(String[] args) {
int[] a = new int[]{3, 9, 5, 7, 1, 2};
sort2(a, 0, a.length - 1);
System.out.println(Arrays.toString(a));
}
public static void sort(int[] a, int p, int r) {
if (p >= r) {
return;
}
int q = partition(a, p, r);
sort(a, p, q - 1);
sort(a, q + 1, r);
}
/**
* 获取分区点
* <p>
* 图示https://cdn.jsdelivr.net/gh/0vo/oss/images/quick_sort.jpg
* <p>
* 通过游标 i 把 a[p...r] 分成两部分。
* a[p...i-1] 的元素都是小于 pivot 的,我们暂且叫它 “已处理区间”a[i...r] 是 “未处理区间”。
* 我们每次都从未处理的区间 a[i...r] 中取一个元素 a[j],与 pivot 对比,
* 如果小于 pivot则将其加入到已处理区间的尾部也就是 a[i] 的位置
* <p>
* 只需要将 a[i] 与 a[j] 交换,就可以在 O(1) 时间复杂度内将 a[j] 放到下标为 i 的位置。
*/
public static int partition(int[] a, int p, int r) {
int i = p;
int pivot = a[r];
for (int j = p; j < r; j++) {
if (a[j] < pivot) {
swap(a, i++, j);
}
}
swap(a, i, r);
System.out.println("i=" + i + " " + Arrays.toString(a));
return i;
}
public static void swap(int[] a, int i, int j) {
if (i == j) {
return;
}
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void sort2(int[] a, int l, int r) {
if (a == null || l >= r) {
return;
}
int i = l, j = r;
int p = l; // 选择最左边的元素为 pivot
while (l < r) {
// 如果选择 p = l 必须先从右边找到小于 a[p] 的第一个元素
while (l < r && a[r] >= a[p]) {
r--;
}
swap(a, r, p);
p = r;
// 从左边找到大于 a[p] 的第一个元素
while (l < r && a[l] <= a[p]) {
l++;
}
swap(a, l, p);
p = l;
System.out.println(Arrays.toString(a));
}
sort2(a, i, p - 1);
sort2(a, p + 1, j);
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +22,7 @@
* THE SOFTWARE.
*/
/**
*
*/
package io.github.ehlxr.annotation;
package io.github.ehlxr.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -33,11 +30,12 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author ehlxr
* 请求日志排除注解
*
* @author ehlxr
* @since 2021-08-18 14:03.
*/
@Target(ElementType.PACKAGE)
@Retention(RetentionPolicy.RUNTIME)
@interface PkgAnnotation {
@Target(ElementType.METHOD)
public @interface NoRequestLog {
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,28 +22,26 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.common;
/**
* @author ehlxr
*/
/**
* @author ehlxr
* 常量
*
* @author ehlxr
* @since 2021-08-29 18:32.
*/
@PkgAnnotation
package io.github.ehlxr.annotation;
public interface Constant {
/**
* traceID
*/
String LOG_TRACE_ID = "logTraceId";
/**
* 包内方法
*/
class MyPackageMethod {
public void myPackageMethod() {
System.out.println("MyPackageMethod...");
}
/**
* 接口请求开始时间戳
*/
String REQUEST_START_TIME = "request_start_time";
int SUCCESS_CODE = 0;
String SUCCESS_MSG = "success";
}
/**
* 包内常量
*/
class MyPackageConst {
static final java.lang.String PACKAGE_STRING = "myPackageConst";
}

View File

@@ -1,28 +1,4 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.common;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -30,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import io.github.ehlxr.enums.CodeEnum;
import java.io.Serializable;
import java.text.SimpleDateFormat;
@@ -67,7 +44,7 @@ public class Result<T> implements Serializable {
}
public static <T> Result<T> success(T data, String message) {
return new Result<>(Code.SUCCESSFUL.getCode(), data, message);
return new Result<>(CodeEnum.SUCCESSFUL.getCode(), data, message);
}
public static <T> Result<T> success(T data) {
@@ -82,35 +59,35 @@ public class Result<T> implements Serializable {
return new Result<>(c, d, m);
}
public static <T> Result<T> of(Code c, T d, String m) {
public static <T> Result<T> of(CodeEnum c, T d, String m) {
return new Result<>(c.getCode(), d, m);
}
public static <T> Result<T> fail(Code code, String message) {
return of(code.getCode(), null, message);
public static <T> Result<T> fail(CodeEnum codeEnum, String message) {
return of(codeEnum.getCode(), null, message);
}
public static <T> Result<T> fail(Code code) {
return fail(code, code.getMessage());
public static <T> Result<T> fail(CodeEnum codeEnum) {
return fail(codeEnum, codeEnum.getMessage());
}
public static <T> Result<T> fail(Throwable e) {
// 格式化异常消息防止输出异常栈信息到结果集
e = Throwables.getRootCause(e);
return of(Code.UNKNOWN_EXCEPTION.getCode(), null, String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()));
return of(CodeEnum.UNKNOWN_EXCEPTION.getCode(), null, String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage()));
}
public String getMessage() {
// return Strings.isNullOrEmpty(m) ? c.getMessage() : m;
if (Strings.isNullOrEmpty(message)) {
Code code;
CodeEnum codeEnum;
try {
code = Code.code(this.code);
codeEnum = CodeEnum.code(this.code);
} catch (Exception e) {
return message;
}
return Objects.isNull(code) ? "" : code.getMessage();
return Objects.isNull(codeEnum) ? "" : codeEnum.getMessage();
}
return message;
}

View File

@@ -0,0 +1,56 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author ehlxr
* @since 2021-08-29 18:32.
*/
@Configuration
public class RedisTemplateConfig {
@Bean(name = "redisTemplate")
public RedisTemplate<String, String> getRedisTemplate(RedisConnectionFactory factory) {
return buildRedisTemplateByString(factory);
}
/**
* 构建 redisTemplate 使用 string序列化
*/
public RedisTemplate<String, String> buildRedisTemplateByString(RedisConnectionFactory factory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,35 +22,51 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
package io.github.ehlxr.datastructure;
/**
* 链表节点数据结构
*
* @author ehlxr
* @since 2019-06-28.
* @since 2021-12-23 14:41.
*/
public class MyInvocationHandler implements InvocationHandler {
private final Bird bird;
public class Node<T> {
private T val;
private Node<T> next;
public MyInvocationHandler(Bird bird) {
this.bird = bird;
public Node(T val, Node<T> next) {
this.val = val;
this.next = next;
}
public T getVal() {
return val;
}
public void setVal(T val) {
this.val = val;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
public void print() {
Node<T> n = this;
while (n != null) {
System.out.printf("%s -> ", n.getVal());
n = n.getNext();
}
System.out.print("null");
System.out.println();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
long start = System.currentTimeMillis();
try {
method.invoke(bird, args);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("Fly time = " + (end - start));
return null;
public String toString() {
return "Node{" + val + '}';
}
}

View File

@@ -0,0 +1,103 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.datastructure.linkedlist;
import io.github.ehlxr.datastructure.Node;
/**
* 反转链表
*
* @author ehlxr
* @since 2021-12-23 14:40.
*/
public class ReverseLinkedList<T> {
public static void main(String[] args) {
ReverseLinkedList<Integer> reverseLinkedList = new ReverseLinkedList<>();
Node<Integer> n5 = new Node<>(5, null);
Node<Integer> n4 = new Node<>(4, n5);
Node<Integer> n3 = new Node<>(3, n4);
Node<Integer> n2 = new Node<>(2, n3);
Node<Integer> n1 = new Node<>(1, n2);
Node<Integer> head = new Node<>(0, n1);
head.print();
System.out.println("-------------");
// head = reverse(head);
head = reverseLinkedList.reverse2(head);
// head = reverse3(head, null);
head.print();
}
// 循环方式
public Node<T> reverse(Node<T> head) {
if (head == null || head.getNext() == null) {
return head;
}
Node<T> pre = null;
Node<T> cur = head;
while (cur != null) {
Node<T> next = cur.getNext();
cur.setNext(pre);
pre = cur;
cur = next;
}
return pre;
}
// 递归一
public Node<T> reverse2(Node<T> head) {
if (head == null || head.getNext() == null) {
return head;
}
Node<T> next = head.getNext();
Node<T> node = reverse2(next);
head.getNext().setNext(head);
head.setNext(null);
return node;
}
// 递归二
public Node<T> reverse3(Node<T> head, Node<T> pre) {
if (head == null) {
return pre;
}
Node<T> next = head.getNext();
Node<T> node = reverse3(next, head);
head.setNext(pre);
return node;
}
}

View File

@@ -0,0 +1,101 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.datastructure.queue;
/**
* 数组实现循环队列
* <p>
* 一般情况下只需要 tail + 1 == head 即可判定队列已满结合特殊情况head == 0tail == n - 1
* 可使用公式 (tail + 1) % size == head 判定队列已满head == tail 判断队列为空,
* 但这种公式判断循环队列会浪费一个数组的存储空间。
* <p>
* 另也可使用一个变量 n 记录当前队列中的数量(入队 +1出队 -1当 head == tail 时,
* 如果 n == size则队列已满如果 n == 0 则队列为空。
*
* @author ehlxr
* @since 2021-12-25 21:01.
*/
public class CircularQueue {
private final Integer[] data;
private int head = 0;
private int tail = 0;
private final int size;
public CircularQueue(int size) {
data = new Integer[size];
this.size = size;
}
public static void main(String[] args) {
CircularQueue queue = new CircularQueue(5);
// 循环队列会浪费一个数组的存储空间。队列容量为 5入队 5 个最后一个失败
for (int i = 0; i < 5; i++) {
System.out.println(queue.enqueue(i));
}
// 出队 2 个,然后还可以入队 2 个
for (int i = 0; i < 2; i++) {
System.out.println(queue.dequeue());
}
System.out.println(queue.enqueue(7));
System.out.println(queue.enqueue(8));
System.out.println(queue.enqueue(9));
// 出队 6 个,最后一个失败
for (int i = 0; i < 6; i++) {
System.out.println(queue.dequeue());
}
}
/**
* 入队(从队尾添加元素)
*/
public boolean enqueue(Integer item) {
// 判断队列是否已满
if ((tail + 1) % size == head) {
return false;
}
data[tail] = item;
tail = (tail + 1) % size;
return true;
}
/**
* 出队(从队首取出元素)
*/
public Integer dequeue() {
// 判断队列是否为空
if (head == tail) {
return null;
}
Integer no = data[head];
head = (head + 1) % size;
return no;
}
}

View File

@@ -0,0 +1,103 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.datastructure.queue;
/**
* 数组实现动态扩容队列
*
* @author ehlxr
* @since 2021-12-25 15:19.
*/
public class DynamicArrayQueue {
private final String[] data;
private final int size;
private int head = 0;
private int tail = 0;
public DynamicArrayQueue(int size) {
data = new String[size];
this.size = size;
}
public static void main(String[] args) {
DynamicArrayQueue queue = new DynamicArrayQueue(5);
// 队列容量为 5入队 6 个最后一个失败
for (int i = 0; i < 6; i++) {
System.out.println(queue.enqueue("" + i));
}
// 出队 2 个,然后还可以入队 2 个
for (int i = 0; i < 2; i++) {
System.out.println(queue.dequeue());
}
System.out.println(queue.enqueue("a"));
System.out.println(queue.enqueue("b"));
System.out.println(queue.enqueue("c"));
// 出队 6 个,最后一个失败
for (int i = 0; i < 6; i++) {
System.out.println(queue.dequeue());
}
}
/**
* 入队(从队尾添加元素)
*/
public boolean enqueue(String item) {
// 判断队列是否已满
if (tail == size) {
if (head == 0) {
return false;
}
// 如果 tail == size而 head != 00 与 head 之间还有空位,向前移动 head 与 tail 之间的数据
// for (int i = head; i < tail; i++) {
// data[i - head] = data[i];
// }
if (tail - head >= 0) {
System.arraycopy(data, head, data, 0, tail - head);
}
tail -= head;
head = 0;
}
data[tail++] = item;
return true;
}
/**
* 出队(从队首取出元素)
*/
public String dequeue() {
// 判断队列是否为空
if (head == tail) {
return null;
}
return data[head++];
}
}

View File

@@ -0,0 +1,92 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.datastructure.queue;
import io.github.ehlxr.datastructure.Node;
/**
* 基于链表实现的队列
* <p>
* 入队时间复杂度 O(n)
*
* @author ehlxr
* @since 2021-12-25 16:02.
*/
public class LinkedListQueue<T> {
private Node<T> head;
public static void main(String[] args) {
LinkedListQueue<Integer> queue = new LinkedListQueue<>();
for (int i = 0; i < 6; i++) {
System.out.println(queue.enqueue(i));
}
for (int i = 0; i < 6; i++) {
queue.getData().print();
System.out.println(queue.dequeue());
}
System.out.println(queue.dequeue());
}
/**
* 入队(从队尾添加元素)
* 时间复杂度 O(n)
*/
public boolean enqueue(T item) {
Node<T> node = new Node<T>(item, null);
if (head == null) {
head = node;
return true;
}
// 找到队尾
Node<T> tail = head;
while (tail.getNext() != null) {
tail = tail.getNext();
}
tail.setNext(node);
return true;
}
/**
* 出队(从队首取出元素)
*/
public T dequeue() {
if (head == null) {
return null;
}
T val = head.getVal();
head = head.getNext();
return val;
}
public Node<T> getData() {
return head;
}
}

View File

@@ -0,0 +1,94 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.datastructure.queue;
import io.github.ehlxr.datastructure.Node;
/**
* 基于链表实现的队列
* <p>
* 多一个变量 tail换取入队时间复杂度为 O(1)
*
* @author ehlxr
* @since 2021-12-25 16:48.
*/
public class LinkedListQueue2<T> {
private Node<T> head = null;
private Node<T> tail = null;
public static void main(String[] args) {
LinkedListQueue2<Integer> queue = new LinkedListQueue2<>();
for (int i = 0; i < 6; i++) {
System.out.println(queue.enqueue(i));
}
for (int i = 0; i < 6; i++) {
queue.getData().print();
System.out.println(queue.dequeue());
}
System.out.println(queue.dequeue());
}
/**
* 入队(从队尾添加元素)
* 时间复杂度 O(1)
*/
public boolean enqueue(T item) {
Node<T> node = new Node<>(item, null);
if (tail == null) {
head = node;
tail = node;
return true;
}
tail.setNext(node);
tail = node;
return true;
}
/**
* 出队(从队首取出元素)
*/
public T dequeue() {
if (head == null) {
return null;
}
T val = head.getVal();
head = head.getNext();
// 如果队列为空了,需要把 tail 置空
if (head == null) {
tail = null;
}
return val;
}
public Node<T> getData() {
return head;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,44 +22,56 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.hashing.consistent;
package io.github.ehlxr.datastructure.stack;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author ehlxr
* @since 2021-12-25 22:10.
*/
public class ArrayStack {
private final Integer[] data;
private final int size;
// 栈顶下标
private int top = 0;
public class Cluster {
private static final int SERVER_SIZE_MAX = 1024;
private final SortedMap<Integer, Server> servers = new TreeMap<>();
private int size = 0;
public void put(Entry e) {
routeServer(e.hashCode()).put(e);
}
public Entry get(Entry e) {
return routeServer(e.hashCode()).get(e);
}
public Server routeServer(int hash) {
if (servers.isEmpty())
return null;
if (!servers.containsKey(hash)) {
SortedMap<Integer, Server> tailMap = servers.tailMap(hash);
hash = tailMap.isEmpty() ? servers.firstKey() : tailMap.firstKey();
// hash = servers.firstKey();
public static void main(String[] args) {
ArrayStack stack = new ArrayStack(5);
for (int i = 0; i < 6; i++) {
System.out.println(stack.push(i));
}
return servers.get(hash);
for (int i = 0; i < 6; i++) {
System.out.println(stack.pop());
}
}
public boolean addServer(Server s) {
if (size >= SERVER_SIZE_MAX)
public ArrayStack(int size) {
data = new Integer[size];
this.size = size;
}
/**
* 入栈
*/
public boolean push(Integer item) {
// 判断栈是否已满
if (top == size) {
return false;
}
data[top++] = item;
servers.put(s.hashCode(), s);
size++;
return true;
}
/**
* 出栈
*/
public Integer pop() {
// 判断栈是否为空
if (top == 0) {
return null;
}
return data[--top];
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,55 +22,63 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.test;
package io.github.ehlxr.datastructure.stack;
import io.github.ehlxr.datastructure.Node;
/**
* Created by ehlxr on 2017/4/14.
* @author ehlxr
* @since 2021-12-25 22:28.
*/
public class TestReference {
public class LinkedListStack<T> {
private Node<T> head;
public Node<T> getData() {
return head;
}
public static void main(String[] args) {
Person person = new Person();
LinkedListStack<Integer> stack = new LinkedListStack<>();
for (int i = 0; i < 6; i++) {
System.out.println(stack.push(i));
}
for (int i = 0; i < 6; i++) {
stack.getData().print();
System.out.println(stack.pop());
}
person.age = 20;
person.name = "test20";
System.out.println(person);
TestReference testReference = new TestReference();
testReference.test(person);
System.out.println(person);
}
public void test(Person person) {
person = new Person();
person.age = 21;
person.name = "test21";
/**
* 入栈
*/
public boolean push(T item) {
Node<T> node = new Node<>(item, null);
if (head == null) {
head = node;
return true;
}
node.setNext(head);
head = node;
return true;
}
static class Person {
String name;
int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
/**
* 出栈
*/
public T pop() {
if (head == null) {
return null;
}
public String getName() {
return name;
}
T val = head.getVal();
head = head.getNext();
return val;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void clear() {
head = null;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.enums;
/**
* 自定义状态码
@@ -30,7 +30,7 @@ package io.github.ehlxr.utils;
* @author ehlxr
* @since 2020/3/18.
*/
public enum Code {
public enum CodeEnum {
/**
* 成功
*/
@@ -55,7 +55,7 @@ public enum Code {
private final int code;
private final String message;
Code(int code, String message) {
CodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
@@ -76,10 +76,10 @@ public enum Code {
'}';
}
private static final Code[] CODES = Code.values();
private static final CodeEnum[] CODE_ENUMS = CodeEnum.values();
public static Code code(int code) {
for (Code c : CODES) {
public static CodeEnum code(int code) {
for (CodeEnum c : CODE_ENUMS) {
if (code == c.getCode()) {
return c;
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.enums;
/**
* FORM 表单提交类型

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.enums;
/**
* @author ehlxr

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,31 +22,30 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.singleton;
import java.util.stream.IntStream;
package io.github.ehlxr.exception;
/**
* 枚举单例模式
*
* @author ehlxr
* @since 2021-02-18 10:28.
* @since 2020-05-06.
*/
public enum SingleEnum {
/**
* 唯一实例
*/
INSTANCE;
public class JsonParseException extends RuntimeException {
private static final long serialVersionUID = -2626765995683345473L;
public static SingleEnum getInstance() {
return INSTANCE;
public JsonParseException(String msg) {
super(msg);
}
public String hello(String str) {
return "hello " + str;
public JsonParseException(String msg, Throwable e) {
super(msg, e);
}
public static void main(String[] args) {
IntStream.range(0, 5).parallel().forEach(i -> System.out.println(Thread.currentThread().getName() + " => " + SingleEnum.getInstance()));
public JsonParseException(Throwable e) {
super(e);
}
@Override
public synchronized Throwable fillInStackTrace() {
// 不拷贝栈信息
return null;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,28 +22,46 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.singleton;
package io.github.ehlxr.exception;
import java.util.stream.IntStream;
import io.github.ehlxr.enums.CodeEnum;
/**
* @author ehlxr
* @since 2021-02-18 11:23.
* @since 2021-08-29 19:18.
*/
public class SingleTonStaticInnerClass {
private SingleTonStaticInnerClass() {
public class ServiceDataException extends RuntimeException {
/**
* 错误码
*/
private int code;
/**
* 异常信息
*/
private String msg;
public int getCode() {
return code;
}
private static class HandlerInstance {
private static SingleTonStaticInnerClass instance = new SingleTonStaticInnerClass();
public String getMsg() {
return msg;
}
public static SingleTonStaticInnerClass getInstance() {
return HandlerInstance.instance;
public ServiceDataException(Throwable throwable) {
super(throwable);
}
public static void main(String[] args) {
IntStream.range(0, 5).parallel().forEach(i -> System.out.println(Thread.currentThread().getName() + " => " + SingleTonStaticInnerClass.getInstance()));
public ServiceDataException(CodeEnum codeEnum) {
this.code = codeEnum.getCode();
this.msg = codeEnum.getMessage();
}
}
public ServiceDataException(int code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,74 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.function;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.function.Consumer;
/**
* @author ehlxr
* @since 2021-09-06 10:48.
*/
public class BlockerActionConsumer<T> extends RecursiveAction {
private static final long serialVersionUID = 4942349095463615123L;
private final MyManagedBlockerImpl<T> blocker;
public BlockerActionConsumer(Consumer<T> consumer, T t) {
this.blocker = new MyManagedBlockerImpl<>(consumer, t);
}
@Override
protected void compute() {
try {
ForkJoinPool.managedBlock(blocker);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
static class MyManagedBlockerImpl<T> implements ForkJoinPool.ManagedBlocker {
private final Consumer<T> consumer;
private final T t;
private boolean done = false;
public MyManagedBlockerImpl(Consumer<T> consumer, T t) {
this.consumer = consumer;
this.t = t;
}
@Override
public boolean block() {
consumer.accept(t);
done = true;
return true;
}
@Override
public boolean isReleasable() {
return done;
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.function;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.function.Function;
/**
* @author ehlxr
* @since 2021-09-06 10:39.
*/
public class BlockerTaskFunction<T, R> extends RecursiveTask<R> {
private static final long serialVersionUID = -4114798302790287199L;
private final MyManagedBlockerImpl<T, R> blocker;
public BlockerTaskFunction(Function<T, R> function, T t) {
this.blocker = new MyManagedBlockerImpl<>(function, t);
}
@Override
protected R compute() {
try {
ForkJoinPool.managedBlock(blocker);
setRawResult(blocker.r);
return getRawResult();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
static class MyManagedBlockerImpl<T, R> implements ForkJoinPool.ManagedBlocker {
private final Function<T, R> function;
private final T t;
private R r;
private boolean done = false;
public MyManagedBlockerImpl(Function<T, R> function, T t) {
this.function = function;
this.t = t;
}
@Override
public boolean block() {
r = function.apply(t);
done = true;
return true;
}
@Override
public boolean isReleasable() {
return done;
}
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,27 +22,26 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.proxy;
package io.github.ehlxr.function;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.function.Function;
/**
* @author ehlxr
* @since 2019-06-28.
* @since 2021-09-06 10:40.
*/
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying...");
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
public class CallableFunction<T, R> implements Callable<R> {
private final T t;
private final Function<T, R> function;
public CallableFunction(Function<T, R> function, T t) {
this.function = function;
this.t = t;
}
// @Override
// public void run() {
// System.out.println("Bird is running...");
// }
}
@Override
public R call() {
return function.apply(t);
}
}

View File

@@ -0,0 +1,48 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.function;
import java.util.concurrent.RecursiveTask;
import java.util.function.Function;
/**
* @author ehlxr
* @since 2021-09-06 10:41.
*/
public class RecursiveTaskFunction<T, R> extends RecursiveTask<R> {
private static final long serialVersionUID = 4451027118600634633L;
private final T t;
private final Function<T, R> function;
public RecursiveTaskFunction(Function<T, R> function, T t) {
this.function = function;
this.t = t;
}
@Override
protected R compute() {
return function.apply(t);
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,21 +22,25 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.hashing.consistent;
package io.github.ehlxr.function;
public class Entry {
private final String key;
import java.util.function.Consumer;
Entry(String key) {
this.key = key;
/**
* @author ehlxr
* @since 2021-09-06 10:40.
*/
public class RunnableConsumer<T> implements Runnable {
private final T t;
private final Consumer<T> consumer;
public RunnableConsumer(Consumer<T> consumer, T t) {
this.consumer = consumer;
this.t = t;
}
@Override
public String toString() {
return key;
public void run() {
consumer.accept(t);
}
public int hashCode() {
return key.hashCode();
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.queue;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author ehlxr
* @since 2022-02-24 20:00.
*/
@Component
public class RedisDelayQueue {
private static final Logger log = LoggerFactory.getLogger(RedisDelayQueue.class);
/**
* 延迟队列名称
*/
private static final String DELAY_QUEUE_NAME = "budd:delayQueue";
private static final ExecutorService POOL = new ThreadPoolExecutor(5, 200,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1024), new ThreadFactoryBuilder()
.setNameFormat("RedisDelayQueue-pool-%d").build(),
new ThreadPoolExecutor.AbortPolicy());
private final RedisTemplate<String, String> redisTemplate;
public RedisDelayQueue(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 添加延迟任务
*
* @param msg 延迟任务消息
* @param delayTime 延迟时间(毫秒)
*/
public void addDelayTasks(String msg, long delayTime) {
Boolean result = redisTemplate.opsForZSet()
.add(DELAY_QUEUE_NAME, msg, System.currentTimeMillis() + delayTime);
log.debug("add task {} result {} ", msg, result);
}
/**
* 监听延迟消息
*/
@PostConstruct
public void listenDelayLoop() {
//noinspection AlibabaAvoidManuallyCreateThread
new Thread(() -> {
while (true) {
// 获取一个到点的消息
Set<String> taskSet = redisTemplate.opsForZSet()
.rangeByScore(DELAY_QUEUE_NAME, 0, System.currentTimeMillis(), 0, 1);
// 如果没有,就等等
if (taskSet == null || taskSet.isEmpty()) {
try {
// log.debug("there is no task will sleep 1s.");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
log.error("listen delay loop error.", e);
}
// 继续执行
continue;
}
for (String task : taskSet) {
// 任务认领成功
Long isRemove = redisTemplate.opsForZSet().remove(DELAY_QUEUE_NAME, task);
if (isRemove != null && isRemove > 0) {
log.info("will deal task {}", task);
// 拿到任务 后续处理
POOL.execute(() -> log.info("task {} deal done.", task));
} else {
log.warn("task {} has been handled by another instance", task);
}
}
}
}).start();
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +22,23 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.proxy;
package io.github.ehlxr.semaphore;
/**
* @author ehlxr
* @since 2019-06-28.
* @since 2022-03-03 11:25.
*/
public interface Flyable {
void fly();
public interface DistributedSemaphore {
/**
* 尝试获取一个信号量
*
* @return true 获取成功false 获取失败
*/
boolean tryAcquire();
// void run();
/**
* 释放自己持有的信号量
*/
void release();
}

View File

@@ -0,0 +1,147 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.semaphore;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.ZSetOperations;
import javax.annotation.Nonnull;
import java.util.concurrent.TimeUnit;
/**
* @author ehlxr
* @since 2022-03-03 11:25.
*/
public class RedisSemaphore implements DistributedSemaphore {
private static final String SEMAPHORE_TIME_KEY = "budd:semaphore:time:";
private static final String SEMAPHORE_OWNER_KEY = "budd:semaphore:owner:";
private static final String SEMAPHORE_COUNTER_KEY = "budd:semaphore:counter:";
private final RedisTemplate<String, String> redisTemplate;
private final String timeKey;
private final String ownerKey;
private final String counterKey;
// 信号量的信息
private final SemaphoreInfo info;
// 信号量实体
private final DistributedSemaphore semaphore;
// 身份证明
private final String identification;
public RedisSemaphore(SemaphoreInfo info, RedisTemplate<String, String> redisTemplate,
String identification) {
this.info = info;
this.redisTemplate = redisTemplate;
this.timeKey = SEMAPHORE_TIME_KEY.concat(info.getSemaphoreName());
this.ownerKey = SEMAPHORE_OWNER_KEY.concat(info.getSemaphoreName());
this.counterKey = SEMAPHORE_COUNTER_KEY.concat(info.getSemaphoreName());
this.semaphore = info.isFair() ? new FairSemaphore() : new NonfairSemaphore();
this.identification = identification;
}
@Override
public boolean tryAcquire() {
return semaphore.tryAcquire();
}
@Override
public void release() {
semaphore.release();
}
private class NonfairSemaphore implements DistributedSemaphore {
@Override
public boolean tryAcquire() {
ZSetOperations<String, String> zsetOps = redisTemplate.opsForZSet();
long timeMillis = System.currentTimeMillis();
// 先清除过期的信号量
zsetOps.removeRangeByScore(timeKey, 0, timeMillis - TimeUnit.SECONDS.toMillis(info.getExpire()));
// 尝试获取信号量并比较自身的排名,如果小于许可证的数量则表示获取成功 (redis rank 指令从 0 开始计数)
zsetOps.add(timeKey, identification, timeMillis);
Long rank = zsetOps.rank(timeKey, identification);
if (rank != null && rank < info.getPermits()) {
return true;
}
// 获取失败,删除掉上边添加的标识
release();
return false;
}
@Override
public void release() {
redisTemplate.opsForZSet().remove(timeKey, identification);
}
}
private class FairSemaphore implements DistributedSemaphore {
@Override
public boolean tryAcquire() {
long timeMillis = System.currentTimeMillis();
// 用于获取信号量的计数
Long counter = redisTemplate.opsForValue().increment(counterKey, 1);
if (counter == null) {
return false;
}
// 用流水线把这一堆命令用一次 IO 全部发过去
redisTemplate.executePipelined(new SessionCallback<>() {
@Override
public Object execute(@Nonnull RedisOperations operations) throws DataAccessException {
ZSetOperations<String, Object> zsetOps = operations.opsForZSet();
// 利用 timeKey 来控制是否过期ownerKey 控制是否超配额,
// 使用 zset 的 intersectAndStore 在获取信号量之前清理过期数据,同时清理排名集合中的数据
// 清除过期的信号量
zsetOps.removeRangeByScore(timeKey, 0, timeMillis - TimeUnit.SECONDS.toMillis(info.getExpire()));
zsetOps.intersectAndStore(timeKey, ownerKey, ownerKey);
// 尝试获取信号量
zsetOps.add(timeKey, identification, timeMillis);
zsetOps.add(ownerKey, identification, counter);
return null;
}
});
// 这里根据 持有者集合 的分数来进行判断
Long ownerRank = redisTemplate.opsForZSet().rank(ownerKey, identification);
if (ownerRank != null && ownerRank < info.getPermits()) {
return true;
}
release();
return false;
}
@Override
public void release() {
redisTemplate.executePipelined(new SessionCallback<>() {
@Override
public Object execute(@Nonnull RedisOperations operations) throws DataAccessException {
ZSetOperations<String, Object> zetOps = operations.opsForZSet();
zetOps.remove(timeKey, identification);
zetOps.remove(ownerKey, identification);
return null;
}
});
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.semaphore;
/**
* @author ehlxr
* @since 2022-03-03 11:24.
*/
public final class SemaphoreInfo {
// 信号量的名称
private final String semaphoreName;
// 许可证的数量
private final int permits;
// 信号量最大持有时间 (过期时间) 单位 s
private final long expire;
// 公平 or 非公平
private final boolean fair;
public SemaphoreInfo(String semaphoreName, int permits, long expire) {
this(semaphoreName, permits, expire, false);
}
public SemaphoreInfo(String semaphoreName, int permits, long expire, boolean fair) {
this.semaphoreName = semaphoreName;
this.permits = permits;
this.expire = expire;
this.fair = fair;
}
public String getSemaphoreName() {
return semaphoreName;
}
public int getPermits() {
return permits;
}
public long getExpire() {
return expire;
}
public boolean isFair() {
return fair;
}
}

View File

@@ -0,0 +1,323 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.util;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.time.*;
import java.time.chrono.ChronoLocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.WeakHashMap;
/**
* 日期操作
*
* @author ehlxr
* @since 2021-08-29 18:32.
*/
public class DateUtil {
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String MM_DD = "MM-dd";
public static final String HH_MM_SS = "HH:mm:ss";
// private static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
// private static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern(YYYY_MM_DD);
// private static final DateTimeFormatter DEFAULT_DATE_NO_YEAR_FORMATTER = DateTimeFormatter.ofPattern(MM_DD);
// private static final DateTimeFormatter DEFAULT_TIME_FORMATTER = DateTimeFormatter.ofPattern(HH_MM_SS);
private static final Map<String, DateTimeFormatter> PATTEN_FORMATTER_MAPPER = Collections.synchronizedMap(new WeakHashMap<>());
// static {
// PATTEN_FORMATTER_MAPPER.put(YYYY_MM_DD_HH_MM_SS, DEFAULT_DATE_TIME_FORMATTER);
// PATTEN_FORMATTER_MAPPER.put(YYYY_MM_DD, DEFAULT_DATE_FORMATTER);
// PATTEN_FORMATTER_MAPPER.put(MM_DD, DEFAULT_DATE_NO_YEAR_FORMATTER);
// PATTEN_FORMATTER_MAPPER.put(HH_MM_SS, DEFAULT_TIME_FORMATTER);
// }
private static DateTimeFormatter cacheFormatterAndGet(String patten) {
DateTimeFormatter dateTimeFormatter = PATTEN_FORMATTER_MAPPER.get(patten);
if (dateTimeFormatter == null) {
dateTimeFormatter = DateTimeFormatter.ofPattern(patten).withZone(ZoneId.of("+8"));
PATTEN_FORMATTER_MAPPER.put(patten, dateTimeFormatter);
}
return dateTimeFormatter;
}
/**
* @param localDateTime date time
* @return yyyy-MM-dd HH:mm:ss
*/
public static String formatLocalDateTime(LocalDateTime localDateTime) {
return localDateTime.format(cacheFormatterAndGet(YYYY_MM_DD_HH_MM_SS));
}
/**
* @param localDateTime time
* @param patten yyyy-MM-dd HH:mm:ss
* @return yyyy-MM-dd HH:mm:ss
*/
public static String formatLocalDateTime(LocalDateTime localDateTime, String patten) {
DateTimeFormatter dateTimeFormatter = cacheFormatterAndGet(patten);
return localDateTime.format(dateTimeFormatter);
}
/**
* @param localDate date
* @param patten only date patten
* @return yyyy-MM-dd
*/
public static String formatLocalDate(LocalDate localDate, String patten) {
DateTimeFormatter dateTimeFormatter = cacheFormatterAndGet(patten);
return localDate.format(dateTimeFormatter);
}
/**
* @param localDate localDate
* @return yyyy-MM-dd
*/
public static String formatLocalDate(LocalDate localDate) {
return localDate.format(cacheFormatterAndGet(YYYY_MM_DD));
}
/**
* @param localTime localTime
* @param patten patten
* @return HH:mm:ss
*/
public static String formatLocalTime(LocalTime localTime, String patten) {
DateTimeFormatter dateTimeFormatter = cacheFormatterAndGet(patten);
return localTime.format(dateTimeFormatter);
}
/**
* @param localTime localTime
* @return HH:mm:ss
*/
public static String formatLocalTime(LocalTime localTime) {
return localTime.format(cacheFormatterAndGet(HH_MM_SS));
}
/**
* @param date date time
* @param patten patten
* @return yyyy-MM-dd HH:mm:ss
*/
public static String format(Date date, String patten) {
Instant instant = date.toInstant();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("+8"));
return localDateTime.format(cacheFormatterAndGet(patten));
}
/**
* @param date date
* @return yyyy-MM-dd HH:mm:ss
*/
public static String format(Date date) {
return format(date, YYYY_MM_DD_HH_MM_SS);
}
/**
* @param date date
* @return yyyy-MM-dd
*/
public static String formatDate(Date date) {
return format(date, YYYY_MM_DD);
}
/**
* @param date date
* @return HH:mm:ss
*/
public static String formatTime(Date date) {
return format(date, HH_MM_SS);
}
/**
* @param mills mills
* @return yyyy-MM-dd HH:mm:ss
*/
public static String formatMills(long mills, String patten) {
Instant instant = Instant.ofEpochMilli(mills);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("+8"));
return formatLocalDateTime(localDateTime, patten);
}
/**
* @param mills mills
* @return yyyy-MM-dd HH:mm:ss
*/
public static String formatMills(long mills) {
return formatMills(mills, YYYY_MM_DD_HH_MM_SS);
}
/**
* @param mills mills
* @return yyyy-MM-dd
*/
public static String formatMillsDate(long mills) {
return formatMills(mills, YYYY_MM_DD);
}
/**
* @param date date
* @return HH:mm:ss
*/
public static String formatMillsTime(long date) {
return formatMills(date, HH_MM_SS);
}
/**
* @param date yyyy-MM-dd HH:mm:ss
* @return Date
*/
public static Date parse(String date) {
LocalDateTime localDateTime = parseToLocalDateTime(date);
Instant instant = localDateTime.toInstant(OffsetDateTime.now().getOffset());
return Date.from(instant);
}
/**
* @param date string date
* @param patten formatter patten
* @return LocalDateTime
*/
public static LocalDateTime parseToLocalDateTime(String date, String patten) {
return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(patten));
}
/**
* @param date yyyy-MM-dd HH:mm:ss
* @return LocalDateTime
*/
public static LocalDateTime parseToLocalDateTime(String date) {
return LocalDateTime.parse(date, cacheFormatterAndGet(YYYY_MM_DD_HH_MM_SS));
}
/**
* @param date yyyy-MM-dd HH:mm:ss
* @return milliseconds
*/
public static Long parseToMillis(String date) {
return parseToMillis(date, YYYY_MM_DD_HH_MM_SS);
}
/**
* @param date string date
* @param patten formatter patten
* @return milliseconds
*/
public static Long parseToMillis(String date, String patten) {
return toInstant(LocalDateTime.parse(date, cacheFormatterAndGet(patten))).toEpochMilli();
}
/**
* @param date yyyy-MM-dd
* @return LocalDate
*/
public static LocalDate parseToLocalDate(String date) {
return LocalDate.parse(date, cacheFormatterAndGet(YYYY_MM_DD));
}
/**
* @param date HH:mm:ss
* @return LocalTime
*/
public static LocalTime parseToLocalTime(String date) {
return LocalTime.parse(date, cacheFormatterAndGet(HH_MM_SS));
}
/**
* @param dayStart date
* @param dayEnd date
*/
public static Period betweenDays(Date dayStart, Date dayEnd) {
LocalDateTime localDateTimeStart = LocalDateTime.ofInstant(dayStart.toInstant(), OffsetDateTime.now().getOffset());
LocalDateTime localDateTimeEnd = LocalDateTime.ofInstant(dayEnd.toInstant(), OffsetDateTime.now().getOffset());
return Period.between(localDateTimeStart.toLocalDate(), localDateTimeEnd.toLocalDate());
}
/**
* @param dayStart date
* @param dayEnd date
*/
public static Duration betweenTimes(Date dayStart, Date dayEnd) {
LocalDateTime localDateTimeStart = LocalDateTime.ofInstant(dayStart.toInstant(), OffsetDateTime.now().getOffset());
LocalDateTime localDateTimeEnd = LocalDateTime.ofInstant(dayEnd.toInstant(), OffsetDateTime.now().getOffset());
return Duration.between(localDateTimeStart, localDateTimeEnd);
}
/**
* @param dayStart date
* @param dayEnd date
*/
public static Period betweenDays(String dayStart, String dayEnd) {
return Period.between(parseToLocalDate(dayStart), parseToLocalDate(dayEnd));
}
/**
* @param dayStart date
* @param dayEnd date
*/
public static Duration betweenTimes(String dayStart, String dayEnd) {
return Duration.between(parseToLocalDateTime(dayStart), parseToLocalDateTime(dayEnd));
}
/**
* 每月开始、结束毫秒时间戳
*/
public static ImmutablePair<Long, Long> firstAndLastMillisOfMonth() {
LocalDate today = LocalDate.now();
Long firstDay = toInstant(LocalDateTime.of(today.with(TemporalAdjusters.firstDayOfMonth()), LocalTime.MIN)).toEpochMilli();
Long lastDay = toInstant(LocalDateTime.of(today.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX)).toEpochMilli();
return ImmutablePair.of(firstDay, lastDay);
}
public static Instant toInstant(ChronoLocalDateTime<?> d) {
return d.toInstant(ZoneOffset.of("+8"));
}
/**
* 当前秒级别时间戳
*
* @return 10 位时间戳
*/
public static Long currentTimeSecond() {
return toInstant(LocalDateTime.now()).getEpochSecond();
}
/**
* 之前的多少天
*
* @param days 之前的天数
* @return yyyy-MM-dd
*/
public static String beforeDay(long days) {
return formatLocalDate(LocalDate.now().minusDays(days));
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,25 +22,62 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.util;
import com.google.common.collect.Maps;
import io.github.ehlxr.enums.FormType;
import io.github.ehlxr.enums.HttpContentType;
import okhttp3.*;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author ehlxr
* @since 2020/4/20.
*/
public class HttpUtil {
private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder()
private static OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.build();
public static void trustAllClient() {
Try.of(() -> {
X509TrustManager x509TrustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
client = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.sslSocketFactory(sslContext.getSocketFactory(), x509TrustManager)
.hostnameVerifier((s, sslSession) -> true)
.build();
}).trap(Throwable::printStackTrace).run();
}
public static String get(String url, Map<String, String> headers) {
String resp;
try {
@@ -48,7 +85,7 @@ public class HttpUtil {
.url(url)
.headers(Headers.of(headers))
.build();
Response response = OK_HTTP_CLIENT.newCall(request).execute();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
resp = response.body() != null ? response.body().string() : "";
} else {
@@ -75,7 +112,7 @@ public class HttpUtil {
.post(RequestBody.create(mediaType, body))
.build();
Response response = OK_HTTP_CLIENT.newCall(request).execute();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
resp = response.body() != null ? response.body().string() : "";
} else {
@@ -117,7 +154,7 @@ public class HttpUtil {
.post(builder.build())
.headers(Headers.of(header))
.build();
Response response = OK_HTTP_CLIENT.newCall(request).execute();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
resp = response.body() != null ? response.body().string() : "";
} else {
@@ -136,5 +173,9 @@ public class HttpUtil {
return sb.substring(0, sb.length() - 1);
}
public static void main(String[] args) {
HttpUtil.trustAllClient();
}
}

View File

@@ -0,0 +1,108 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 自增 id 生成工具类
*
* @author ehlxr
* @since 2021-08-29 18:32.
*/
@Component
public class IdUtil {
private final static String REDIS_ID_KEY = "com.tzld.piaoquan.incentive_";
/**
* 每一毫秒生成的最大数
*/
private static final int MAX_NUN = 99;
private static final AtomicInteger ATOMIC_NUM = new AtomicInteger();
private static RedisTemplate<String, String> redisTemplate;
private static String cur_date;
public static long redisId() {
// 生成 17 位的时间戳(每毫秒使用新的时间戳当key)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
String timeStamp = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
// 获得 redis-key
String newKey = String.format("%s:%s", REDIS_ID_KEY, timeStamp);
// 获取自增值(时间戳 + 自定义 key
Long increment = redisTemplate.opsForValue().increment(newKey, 1);
// 设置时间戳生成的 key 的有效期为 1 秒
redisTemplate.expire(newKey, 1, TimeUnit.SECONDS);
// 获取订单号,时间戳 + 唯一自增 Id(2 位数,不过前方补 0)
return Long.parseLong(String.format("%s%02d", timeStamp, increment));
}
// @Autowired
// public IdUtil(RedisTemplate<String, Object> redisTemplate) {
// IdUtil.redisTemplate = redisTemplate;
// }
/**
* 生成 19 位数 id
* <p>
* 17 位日期 + 2 位自增数<br>
* 一毫秒最多生成 MAX_NUN 个 id同一毫秒 id 有序自增
*/
public static long localId() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
String nowStr = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
// 如果当前时间不是 cur_date 时间 设置 cur_date 为当前时间 重新开始计数
if (!nowStr.equals(cur_date)) {
cur_date = nowStr;
ATOMIC_NUM.set(0);
}
// 如果同一毫秒最大数大于 最大数 MAX_NUN 则等待 1 毫秒 重新计算
if (ATOMIC_NUM.get() >= MAX_NUN) {
try {
Thread.sleep(1);
} catch (InterruptedException ignored) {
}
nowStr = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
ATOMIC_NUM.set(0);
}
// 线程安全的原子操作,所以此方法无需同步 调用 incrementAndGet 函数来进行自增操作
return Long.parseLong(String.format("%s%02d", nowStr, ATOMIC_NUM.incrementAndGet()));
}
@Autowired
public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
IdUtil.redisTemplate = redisTemplate;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -30,6 +30,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import io.github.ehlxr.exception.JsonParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -75,7 +76,7 @@ public class JsonUtils {
try {
return OBJECT_MAPPER.readTree(obj2String(obj));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
throw new JsonParseException(e);
}
}
@@ -93,7 +94,7 @@ public class JsonUtils {
try {
return obj instanceof String ? (String) obj : OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
throw new JsonParseException(e);
}
}
@@ -111,7 +112,7 @@ public class JsonUtils {
try {
return obj instanceof String ? (String) obj : OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
throw new JsonParseException(e);
}
}
@@ -130,7 +131,7 @@ public class JsonUtils {
try {
return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
throw new JsonParseException(e);
}
}
@@ -149,7 +150,7 @@ public class JsonUtils {
try {
return typeReference.getType().equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, typeReference);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
throw new JsonParseException(e);
}
}
@@ -167,7 +168,7 @@ public class JsonUtils {
try {
return OBJECT_MAPPER.readValue(str, javaType);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
throw new JsonParseException(e);
}
}
@@ -246,4 +247,3 @@ public class JsonUtils {
}
}

View File

@@ -0,0 +1,127 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.util;
import java.util.BitSet;
/**
* @author ehlxr
* @since 2021-12-16 09:36.
*/
public class MyBloomFilter {
/**
* 一个长度为10 亿的比特位
*/
private static final int DEFAULT_SIZE = 256 << 22;
/**
* 为了降低错误率使用加法hash算法所以定义一个8个元素的质数数组
*/
private static final int[] SEEDS = {3, 5, 7, 11, 13, 31, 37, 61};
/**
* 相当于构建 8 个不同的hash算法
*/
private static final HashFunction[] HASH_FUNCS = new HashFunction[SEEDS.length];
/**
* 初始化布隆过滤器的 bitmap
*/
private static final BitSet BIT_SET = new BitSet(DEFAULT_SIZE);
/**
* 添加数据
*
* @param value 需要加入的值
*/
public static void add(String value) {
if (value != null) {
for (HashFunction f : HASH_FUNCS) {
//计算 hash 值并修改 bitmap 中相应位置为 true
BIT_SET.set(f.hash(value), true);
}
}
}
/**
* 判断相应元素是否存在
*
* @param value 需要判断的元素
* @return 结果
*/
public static boolean contains(String value) {
if (value == null) {
return false;
}
boolean ret = true;
for (HashFunction f : HASH_FUNCS) {
ret = BIT_SET.get(f.hash(value));
//一个 hash 函数返回 false 则跳出循环
if (!ret) {
break;
}
}
return ret;
}
/**
* 模拟用户是不是会员,或用户在不在线。。。
*/
public static void main(String[] args) {
for (int i = 0; i < SEEDS.length; i++) {
HASH_FUNCS[i] = new HashFunction(DEFAULT_SIZE, SEEDS[i]);
}
// 添加1亿数据
for (int i = 0; i < 1_0000_0000; i++) {
add(String.valueOf(i));
}
String id = "123456789";
add(id);
System.out.println(contains(id)); // true
System.out.println("" + contains("234567890")); //false
}
}
class HashFunction {
private final int size;
private final int seed;
public HashFunction(int size, int seed) {
this.size = size;
this.seed = seed;
}
public int hash(String value) {
int result = 0;
int len = value.length();
for (int i = 0; i < len; i++) {
result = seed * result + value.charAt(i);
}
int r = (size - 1) & result;
return (size - 1) & result;
}
}

View File

@@ -0,0 +1,312 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.scripting.support.StaticScriptSource;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* redis 操作
*
* @author ehlxr
* @since 2021-08-29 18:32.
*/
@Component
public class RedisUtil {
private static final Logger log = LoggerFactory.getLogger(RedisUtil.class);
/**
* 解锁 lua 脚本
*/
private static final String UNLOCK = "if (redis.call('hexists', KEYS[1], ARGV[1]) == 0) then " +
"return nil; " +
"end; " +
"local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1); " +
"if (counter > 0) then " +
"return 0; " +
"else " +
"redis.call('del', KEYS[1]); " +
"return 1; " +
"end; " +
"return nil;";
/**
* 锁前缀
*/
private static final String LOCK_PREFIX = "LOCK_";
/**
* 默认重试次数
*/
private static final Integer DEFAULT_RETRIES = 1;
/**
* 默认 10毫秒
*/
private static final Long DEFAULT_INTERVAL = 10L;
/**
* 加锁 lua 脚本
*/
private static final String LOCK = "if (redis.call('exists', KEYS[1]) == 0) then " +
"redis.call('hset', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return 1; " +
"end; " +
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return 1; " +
"end; " +
"return 0;";
private static RedisTemplate<String, String> redisTemplate;
/**
* 释放分布式锁时使用的 lua 脚本,保证原子性
* <p>
* if (redis.call('get', KEYS[1]) == ARGV[1])
* then
* return redis.call('del', KEYS[1])
* else
* return 0
* end
*/
private static final String RELEASE_LOCK_LUA = "if (redis.call('get', KEYS[1]) == ARGV[1]) then return redis.call('del', KEYS[1]) else return 0 end";
/**
* 滑动窗口限流使用的 lua 脚本,保证原子性
* <p>
* local key = KEYS[1];
* local index = tonumber(ARGV[1]);
* local time_window = tonumber(ARGV[2]);
* local now_time = tonumber(ARGV[3]);
* local far_time = redis.call('lindex', key, index);
* if (not far_time)
* then
* redis.call('lpush', key, now_time);
* redis.call('pexpire', key, time_window+1000);
* return 1;
* end
* if (now_time - far_time > time_window)
* then
* redis.call('rpop', key);
* redis.call('lpush', key, now_time);
* redis.call('pexpire', key, time_window+1000);
* return 1;
* else
* return 0;
* end
*/
private static final String SLIDE_WINDOW_LUA = "local key = KEYS[1];\n" + "local index = tonumber(ARGV[1]);\n" + "local time_window = tonumber(ARGV[2]);\n" + "local now_time = tonumber(ARGV[3]);\n" + "local far_time = redis.call('lindex', key, index);\n" + "if (not far_time)\n" + "then\n" + " redis.call('lpush', key, now_time);\n" + " redis.call('pexpire', key, time_window+1000);\n" + " return 1;\n" + "end\n" + "\n" + "if (now_time - far_time > time_window)\n" + "then\n" + " redis.call('rpop', key);\n" + " redis.call('lpush', key, now_time);\n" + " redis.call('pexpire', key, time_window+1000);\n" + " return 1;\n" + "else\n" + " return 0;\n" + "end";
/**
* 获取分布式锁
*
* @param key key
* @param value value需要保证全局唯一用来删除分布式锁时判断身份使用
* @param expireTime 锁过期时间,毫秒,防止业务崩溃未删除锁,导致死锁
* @return 是否获取成功锁
*/
public static boolean getDistributedLock(String key, String value, long expireTime) {
boolean result = false;
try {
Boolean set = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
result = set == null || set;
log.info("getLock redis key: {}, value: {}, expireTime: {}, result: {}", key, value, expireTime, result);
} catch (Exception e) {
log.error("getLock redis key: {}, value: {}, expireTime: {}", key, value, expireTime, e);
}
return result;
}
/**
* 释放分布式锁
*
* @param key key
* @param value value需要和获取锁时传入的一致
* @return 是否释放成功锁
*/
public static boolean releaseDistributedLock(String key, String value) {
Long execute = null;
try {
RedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA, Long.class);
execute = redisTemplate.execute(redisScript, Collections.singletonList(key), value);
log.debug("releaseLock redis key: {}, value: {}, result: {}", key, value, execute);
} catch (Exception e) {
log.error("releaseLock redis key: {}, value: {}", key, value, e);
}
return Long.valueOf(1L).equals(execute);
}
/**
* 分布式限流队列,在时间窗口内(包含该时间点),判断是否达到限流的阀值
* 本接口实现的方法通过加锁避免并发问题,性能不高。只是为了说明限流逻辑如何实现
*
* @param key key
* @param count 限流阀值
* @param timeWindow 限流时间窗口
* @return 是否允许通过(通过即不进行限流)
*/
public static synchronized boolean slideWindow(String key, int count, long timeWindow) {
try {
long nowTime = System.currentTimeMillis();
ListOperations<String, String> list = redisTemplate.opsForList();
String farTime = list.index(key, count - 1);
if (farTime == null) {
list.leftPush(key, String.valueOf(nowTime));
redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
return true;
}
if (nowTime - Long.parseLong(farTime) > timeWindow) {
list.rightPop(key);
list.leftPush(key, String.valueOf(nowTime));
redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
return true;
}
return false;
} catch (Exception e) {
log.error("", e);
return false;
}
}
/**
* 分布式限流队列,在时间窗口内(包含该时间点),判断是否达到限流的阀值
* 本接口实现的方法通过 Lua 脚本避免并发问题,性能较高。
*
* @param key key
* @param count 限流阀值
* @param timeWindow 限流时间窗口
* @return 是否允许通过(通过即不进行限流)
*/
public static boolean slideWindowLua(String key, int count, long timeWindow) {
if (count <= 0 || timeWindow <= 0) {
return false;
}
Long execute = null;
try {
RedisScript<Long> redisScript = new DefaultRedisScript<>(SLIDE_WINDOW_LUA, Long.class);
execute = redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(count - 1), String.valueOf(timeWindow), String.valueOf(System.currentTimeMillis()));
log.debug("slideWindowLua redis key: {}, count: {}, timeWindow: {}, result: {}", key, count, timeWindow, execute);
} catch (Exception e) {
log.error("slideWindowLua redis key: {}, count: {}, timeWindow: {}", key, count, timeWindow, e);
}
return Long.valueOf(1L).equals(execute);
}
/**
* 加锁 不可重入
*
* @param timeout 毫秒
*/
public static Boolean lock(String key, long timeout) {
return redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + key, "1", timeout, TimeUnit.MILLISECONDS);
}
/**
* 解锁 不可重入
*/
public static Boolean unlock(String key) {
return redisTemplate.delete(LOCK_PREFIX + key);
}
/**
* 加锁
*
* @param reentrantId 重入Id
* 超时时间 毫秒ms
*/
public static Boolean lock(String key, String reentrantId, long timeout) {
return lock(key, reentrantId, timeout, DEFAULT_RETRIES);
}
/**
* 加锁
*
* @param reentrantId 重入Id
* 超时时间 毫秒ms
* @param retries 重试次数
*/
public static Boolean lock(String key, String reentrantId, long timeout, int retries) {
return lock(key, reentrantId, timeout, retries, DEFAULT_INTERVAL);
}
/**
* 加锁
*
* @param reentrantId 重入Id
* 超时时间 毫秒ms
* @param retries 重试次数
* @param interval 每次重试间隔时间 毫秒
*/
public static Boolean lock(String key, String reentrantId, long timeout, int retries, long interval) {
String lockKey = LOCK_PREFIX + key;
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
script.setResultType(Long.class);
script.setScriptSource(new StaticScriptSource(LOCK));
for (int i = 0; i < retries; i++) {
Object result = redisTemplate.execute(script, Collections.singletonList(lockKey), String.valueOf(timeout), reentrantId);
if (Objects.nonNull(result) && Objects.equals(1L, Long.valueOf(result.toString()))) {
return true;
}
try {
TimeUnit.MILLISECONDS.sleep(interval);
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
return false;
}
/**
* 解锁
*
* @param reentrantId 重入ID
*/
public static Boolean unlock(String key, String reentrantId) {
String lockKey = LOCK_PREFIX + key;
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
script.setResultType(Long.class);
script.setScriptSource(new StaticScriptSource(UNLOCK));
Object result = redisTemplate.execute(script, Collections.singletonList(lockKey), reentrantId);
if (Objects.isNull(result)) {
return null;
}
return Objects.equals(1L, Long.valueOf(result.toString()));
}
@Autowired
public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
RedisUtil.redisTemplate = redisTemplate;
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +22,11 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.util;
import com.google.common.collect.ImmutableMap;
import io.github.ehlxr.common.Constant;
import org.slf4j.MDC;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@@ -48,11 +50,11 @@ public class SendAlarmUtil {
/**
* 异步发送预警信息
*
* @param msg 预警信息
* @param action {@link BiConsumer} 完成后回调函数式接口
* @param message 预警信息
* @param action {@link BiConsumer} 完成后回调函数式接口
*/
public static void send(String msg, BiConsumer<? super String, ? super Throwable> action) {
// String msg = String.format("%s\ntraceid: %s", msg, MDC.get(Constants.LOG_TRACE_ID));
public static void send(String message, BiConsumer<? super String, ? super Throwable> action) {
String msg = String.format("%s\ntraceid: %s", message, MDC.get(Constant.LOG_TRACE_ID));
CompletableFuture.supplyAsync(() -> {
Objects.requireNonNull(dingtalkUrl, "SendAlarmUtil not init.");
@@ -79,10 +81,10 @@ public class SendAlarmUtil {
.trap(System.out::println)
.run();
send("dsfsdf",
send("hello",
(t, u) -> System.out.println("send exception message to dingtalk result " + t + ". " + u));
System.out.println("000000");
System.out.println("do other something....");
Thread.sleep(2000);
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
package io.github.ehlxr.util;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.ImmutableMap;
@@ -84,6 +84,163 @@ public interface Try {
return new TryRunnable(runnable);
}
@SuppressWarnings({"ConstantConditions", "Convert2MethodRef"})
static void main(String[] args) {
System.out.println("------------有返回值,无入参----------------");
// 有返回值无入参
String param = "hello";
Long result = Try.of(() -> Long.valueOf(param)).get(0L);
System.out.println("Long.valueOf 1: " + result);
result = Try.of(() -> Long.valueOf(param)).get();
System.out.println("Long.valueOf 2: " + result);
System.out.println("------------有返回值,有入参----------------");
// 有返回值有入参
result = Try.<Map<String, String>, Long>of(s -> Long.valueOf(s.get("k1")))
.apply(ImmutableMap.of("k1", param))
.trap(e -> System.out.println("Long.valueOf exception: " + e.getMessage()))
.andFinally(() -> System.out.println("This message will ignore."))
.andFinally(s -> {
Map<String, Object> returnMap = JsonUtils.string2Obj(JsonUtils.obj2String(s), new TypeReference<Map<String, Object>>() {
});
System.out.println("Long.valueOf finally run code." + s);
// 演示抛异常
String k2 = returnMap.get("k2").toString();
System.out.println(k2);
})
.finallyTrap(e -> System.out.println("Long.valueOf finally exception: " + e.getMessage()))
.get();
System.out.println("Long.valueOf 3: " + result);
ArrayList<String> list = null;
System.out.println("-----------无返回值,无入参-----------------");
// 无返回值无入参
Try.of(() -> Thread.sleep(-1L))
.andFinally(() -> list.clear())
// .andFinally(list::clear) //https://stackoverflow.com/questions/37413106/java-lang-nullpointerexception-is-thrown-using-a-method-reference-but-not-a-lamb
.run();
System.out.println("--------------无返回值,有入参--------------");
// 无返回值有入参
Try.<String>of(v -> list.add(0, v))
.andFinally(s -> System.out.println(s))
.accept("hello");
}
class TryRunnable extends Tryable<TryRunnable> {
private final ThrowableRunnable runnable;
protected TryRunnable(ThrowableRunnable runnable) {
Objects.requireNonNull(runnable, "No runnable present");
this.runnable = runnable;
super.c = this;
}
/**
* 计算结果
*/
public void run() {
try {
runnable.run();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
} finally {
doFinally();
}
}
}
class TrySupplier<R> extends Tryable<TrySupplier<R>> {
private final ThrowableSupplier<? extends R> supplier;
protected TrySupplier(ThrowableSupplier<? extends R> supplier) {
Objects.requireNonNull(supplier, "No supplier present");
this.supplier = supplier;
super.c = this;
}
/**
* 如果有异常返回默认值否则返回计算结果
*
* @param r 指定默认值
* @return 实际值或默认值
*/
public R get(R r) {
try {
return supplier.get();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return r;
} finally {
doFinally();
}
}
/**
* 如果有异常返回 null否则返回计算结果
*
* @return 实际值或 null
*/
public R get() {
try {
return supplier.get();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return null;
} finally {
doFinally();
}
}
}
@FunctionalInterface
interface ThrowableConsumer<P> {
/**
* Performs this operation on the given argument.
*
* @param p the input argument
* @throws Throwable throwable
*/
void accept(P p) throws Throwable;
}
@FunctionalInterface
interface ThrowableSupplier<R> {
/**
* Gets a result.
*
* @return a result
* @throws Throwable throwable
*/
R get() throws Throwable;
}
@FunctionalInterface
interface ThrowableRunnable {
/**
* Performs this operation
*
* @throws Throwable throwable
*/
void run() throws Throwable;
}
@FunctionalInterface
interface ThrowableFunction<P, R> {
/**
* Applies this function to the given argument.
*
* @param p the function argument
* @return the function result
* @throws Throwable throwable
*/
R apply(P p) throws Throwable;
}
abstract class Tryable<C> {
Consumer<? super Throwable> throwConsumer;
ThrowableRunnable finallyRunnable;
@@ -175,74 +332,6 @@ public interface Try {
}
}
class TryRunnable extends Tryable<TryRunnable> {
private final ThrowableRunnable runnable;
protected TryRunnable(ThrowableRunnable runnable) {
Objects.requireNonNull(runnable, "No runnable present");
this.runnable = runnable;
super.c = this;
}
/**
* 计算结果
*/
public void run() {
try {
runnable.run();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
} finally {
doFinally();
}
}
}
class TrySupplier<R> extends Tryable<TrySupplier<R>> {
private final ThrowableSupplier<? extends R> supplier;
protected TrySupplier(ThrowableSupplier<? extends R> supplier) {
Objects.requireNonNull(supplier, "No supplier present");
this.supplier = supplier;
super.c = this;
}
/**
* 如果有异常返回默认值否则返回计算结果
*
* @param r 指定默认值
* @return 实际值或默认值
*/
public R get(R r) {
try {
return supplier.get();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return r;
} finally {
doFinally();
}
}
/**
* 如果有异常返回 null否则返回计算结果
*
* @return 实际值或 null
*/
public R get() {
try {
return supplier.get();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return null;
} finally {
doFinally();
}
}
}
class TryConsumer<P> extends Tryable<TryConsumer<P>> {
private final ThrowableConsumer<? super P> consumer;
@@ -335,93 +424,4 @@ public interface Try {
}
}
}
@FunctionalInterface
interface ThrowableConsumer<P> {
/**
* Performs this operation on the given argument.
*
* @param p the input argument
* @throws Throwable throwable
*/
void accept(P p) throws Throwable;
}
@FunctionalInterface
interface ThrowableSupplier<R> {
/**
* Gets a result.
*
* @return a result
* @throws Throwable throwable
*/
R get() throws Throwable;
}
@FunctionalInterface
interface ThrowableRunnable {
/**
* Performs this operation
*
* @throws Throwable throwable
*/
void run() throws Throwable;
}
@FunctionalInterface
interface ThrowableFunction<P, R> {
/**
* Applies this function to the given argument.
*
* @param p the function argument
* @return the function result
* @throws Throwable throwable
*/
R apply(P p) throws Throwable;
}
@SuppressWarnings({"ConstantConditions", "Convert2MethodRef"})
static void main(String[] args) {
System.out.println("------------有返回值,无入参----------------");
// 有返回值无入参
String param = "hello";
Long result = Try.of(() -> Long.valueOf(param)).get(0L);
System.out.println("Long.valueOf 1: " + result);
result = Try.of(() -> Long.valueOf(param)).get();
System.out.println("Long.valueOf 2: " + result);
System.out.println("------------有返回值,有入参----------------");
// 有返回值有入参
result = Try.<Map<String, String>, Long>of(s -> Long.valueOf(s.get("k1")))
.apply(ImmutableMap.of("k1", param))
.trap(e -> System.out.println("Long.valueOf exception: " + e.getMessage()))
.andFinally(() -> System.out.println("This message will ignore."))
.andFinally(s -> {
Map<String, Object> returnMap = JsonUtils.string2Obj(JsonUtils.obj2String(s), new TypeReference<Map<String, Object>>() {
});
System.out.println("Long.valueOf finally run code." + s);
// 演示抛异常
String k2 = returnMap.get("k2").toString();
System.out.println(k2);
})
.finallyTrap(e -> System.out.println("Long.valueOf finally exception: " + e.getMessage()))
.get();
System.out.println("Long.valueOf 3: " + result);
ArrayList<String> list = null;
System.out.println("-----------无返回值,无入参-----------------");
// 无返回值无入参
Try.of(() -> Thread.sleep(-1L))
.andFinally(() -> list.clear())
// .andFinally(list::clear) //https://stackoverflow.com/questions/37413106/java-lang-nullpointerexception-is-thrown-using-a-method-reference-but-not-a-lamb
.run();
System.out.println("--------------无返回值,有入参--------------");
// 无返回值有入参
Try.<String>of(v -> list.add(0, v))
.andFinally(s -> System.out.println(s))
.accept("hello");
}
}

18
budd-demo/pom.xml Normal file
View File

@@ -0,0 +1,18 @@
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>budd-demo</artifactId>
<name>budd-demo</name>
<dependencies>
<dependency>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,123 @@
/*
* The MIT License (MIT)
*
* Copyright © 2023 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import com.fasterxml.jackson.core.type.TypeReference;
import io.github.ehlxr.util.JsonUtils;
import java.util.Map;
/**
* @author ehlxr
* @since 2023-03-15 16:08.
*/
public class File {
public static void main(String[] args) {
String str0 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
String str2 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\"}";
String str3 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\"}";
String str4 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
String str5 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
String str6 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
String str7 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\"}";
String str10 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"shortShareFriendPath\": \"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"addMaskGuide\":true,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":-1,\"addBubbleDuration\":5,\"barrageUiShow\": true,\"barrageSwitchOpen\": true}";
String str17 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\"}";
String str18 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\"}";
String str19 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
String str21 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
String str22 = "{\"mode\":2,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
// String str0 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":0,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
// String str2 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":0,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\"}";
// String str3 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":0,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\"}";
// String str4 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
// String str5 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
// String str6 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":0,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
// String str7 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":0,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\"}";
// String str10 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"shortShareFriendPath\": \"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"addMaskGuide\":true,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":-1,\"addBubbleDuration\":5,\"barrageUiShow\": true,\"barrageSwitchOpen\": true}";
// String str17 = "{\"mode\":0,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\"}";
// String str18 = "{\"mode\":0,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\"}";
// String str19 = "{\"mode\":0,\"isIOSAutoPlay\":true,\"isAndroidAutoPlay\":true,\"isShowDefaultPic\":true,\"isShowWeChatCircleShareButton\":true,\"isForceUpdate\":true,\"isGzhFullScreen\":true,\"isGzhAutoPlay\":true,\"isSharePageFullScreen\":true,\"isSharePageAutoPlay\":true,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":true,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":1,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":1,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoagreement.html\",\"serviceAgreementUrl\":\"https://rescdn.piaoquantv.com/agreement/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
// String str21 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":0,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
// String str22 = "{\"mode\":0,\"isIOSAutoPlay\":false,\"isAndroidAutoPlay\":false,\"isShowDefaultPic\":false,\"isShowWeChatCircleShareButton\":false,\"isForceUpdate\":true,\"isGzhFullScreen\":false,\"isGzhAutoPlay\":false,\"isSharePageFullScreen\":false,\"isSharePageAutoPlay\":false,\"distDir\":\"dist_1_3_4\",\"distNewDir\":\"dist_1_3_4\",\"videoShareFriendPath\":\"pages/user-videos\",\"videoShareMomentPath\":\"pages/user-videos\",\"userShareFriendPath\":\"pages/mine/mine-info\",\"userShareMomentPath\":\"pages/mine/mine-info\",\"addMaskGuide\":false,\"addMaskDayInterval\":2,\"addMaskMaxCount\":3,\"addMaskDuration\":10,\"addBubbleGuide\":true,\"addBubbleDayInterval\":2,\"addBubbleMaxCount\":3,\"addBubbleDuration\":10,\"shortShareFriendPath\":\"pages/shortvideo/shortvideo\",\"shortShareMomentPath\":\"pages/shortvideo/shortvideo\",\"barrageUiShow\":true,\"barrageSwitchOpen\":true,\"sortType\":2,\"barrageInputStates\":0,\"videoBarrageSwitch\":true,\"isOpenUnUploadReason\":false,\"isOpenUploadReason\":false,\"homeTabUserInfoPanel\":false,\"isShowDialogOnUpdate\":false,\"fundebug\":false,\"barrageSection\":30,\"isUploadPageLoadData\":0,\"showPayTipsMaxCount\":2,\"openFollowRemind\":true,\"dayFollowRemind\":1,\"totalFollowRemind\":3,\"sharePageRoute\":0,\"shouldFixWxRenderBug\":1,\"defaultSearchText\":\"搜索你想看的\",\"isShowDetailPageGuide\":false,\"gzhOtherVideoCount\":4,\"otherVideoCount\":10,\"shareVideoDialogCount\":2,\"videoShare2PageNotFoundPercent\":0,\"categoryRouterPercent\":100,\"fixed707Upload\":1,\"albumAvailable\":1,\"csVideoShareH5Title\":\"\",\"activityMoney\":2.88,\"privacyAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoagreement.html\",\"serviceAgreementUrl\":\"https://weapppiccdn.yishihui.com/resources/agreements/videoservice.html\",\"h5Domain\":\"https://vlogh5.piaoquantv.com/\",\"sendVideoIgnoreAuthorizeMobile\":1,\"sendVideoPostAuthorizeMobile\":1,\"noGrantLoginEnable\":1}";
Map<String, String> j0 = JsonUtils.string2Obj(str0, new TypeReference<>() {
});
Map<String, String> j2 = JsonUtils.string2Obj(str2, new TypeReference<>() {
});
Map<String, String> j3 = JsonUtils.string2Obj(str3, new TypeReference<>() {
});
Map<String, String> j4 = JsonUtils.string2Obj(str4, new TypeReference<>() {
});
Map<String, String> j5 = JsonUtils.string2Obj(str5, new TypeReference<>() {
});
Map<String, String> j6 = JsonUtils.string2Obj(str6, new TypeReference<>() {
});
Map<String, String> j7 = JsonUtils.string2Obj(str7, new TypeReference<>() {
});
Map<String, String> j10 = JsonUtils.string2Obj(str10, new TypeReference<>() {
});
Map<String, String> j17 = JsonUtils.string2Obj(str17, new TypeReference<>() {
});
Map<String, String> j18 = JsonUtils.string2Obj(str18, new TypeReference<>() {
});
Map<String, String> j19 = JsonUtils.string2Obj(str19, new TypeReference<>() {
});
Map<String, String> j21 = JsonUtils.string2Obj(str21, new TypeReference<>() {
});
Map<String, String> j22 = JsonUtils.string2Obj(str22, new TypeReference<>() {
});
for (String key : j0.keySet()) {
System.out.println(key + "|" + j0.get(key) + "|" + j2.remove(key)
+ "|" + j3.remove(key)
+ "|" + j4.remove(key)
+ "|" + j5.remove(key)
+ "|" + j6.remove(key)
+ "|" + j7.remove(key)
+ "|" + j10.remove(key)
+ "|" + j17.remove(key)
+ "|" + j18.remove(key)
+ "|" + j19.remove(key)
+ "|" + j21.remove(key)
+ "|" + j22.remove(key));
}
System.out.println("j2: " + j2);
System.out.println("j3: " + j3);
System.out.println("j4: " + j4);
System.out.println("j5: " + j5);
System.out.println("j6: " + j6);
System.out.println("j7: " + j7);
System.out.println("j10: " + j10);
System.out.println("j17: " + j17);
System.out.println("j18: " + j18);
System.out.println("j19: " + j19);
System.out.println("j21: " + j21);
System.out.println("j22: " + j22);
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,16 +22,29 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.test;
package io.github.ehlxr;
import io.github.ehlxr.redis.JedisUtil;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Created by ehlxr on 2016/6/14.
* @author ehlxr
* @since 2022-01-17 06:31.
*/
public class Main {
public static void main(String[] args) {
JedisUtil.set("test_20160614", "20160614");
System.out.println(JedisUtil.getStr("test_20160614"));
int[][] ns = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
System.out.println(ns.length); // 3
System.out.println(ns[0].length); // 4
System.out.println(ns[2][2]); // 11
List<String> collect = Stream.of("111", "wwwdddd", "dddddd", "12").filter(x -> x.length() > 3).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,260 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import com.google.common.base.Stopwatch;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author ehlxr
* @since 2021-09-02 15:52.
*/
public class ManagedBlockerTest {
static String threadDateTimeInfo() {
return DateTimeFormatter.ISO_TIME.format(LocalTime.now()) + Thread.currentThread().getName();
}
static void test1() {
List<RecursiveTask<String>> tasks = Stream.generate(() -> new RecursiveTask<String>() {
private static final long serialVersionUID = 1303648247573881735L;
@Override
protected String compute() {
System.out.println(threadDateTimeInfo() + ":simulate io task blocking for 2 seconds···");
try {
//线程休眠2秒模拟IO调用阻塞
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new Error(e);
}
return threadDateTimeInfo() + ": io blocking task returns successfully";
}
}).limit(28).collect(Collectors.toList());
tasks.forEach(ForkJoinTask::fork);
tasks.forEach(e -> {
try {
System.out.println(e.get());
} catch (Exception ex) {
ex.printStackTrace();
}
});
}
public static void main(String[] args) {
Stopwatch started = Stopwatch.createStarted();
test4();
System.out.println(started);
}
static void test2() {
List<IoBlockerTask<String>> tasks = Stream.generate(() -> new IoBlockerTask<>(() -> {
System.out.println(threadDateTimeInfo() + ":simulate io task blocking for 2 seconds···");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new Error(e);
}
return threadDateTimeInfo() + ": io blocking task returns successfully";
})).limit(28).collect(Collectors.toList());
tasks.forEach(ForkJoinTask::fork);
tasks.forEach(e -> {
try {
System.out.println(e.get());
} catch (Exception ex) {
ex.printStackTrace();
}
});
}
static void test3() {
List<IoBlockerAction> actions = Stream.generate(() -> new IoBlockerAction(() -> {
System.out.println(threadDateTimeInfo() + ":simulate io action blocking for 2 seconds···");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new Error(e);
}
System.out.println(threadDateTimeInfo() + ": io blocking action successfully");
})).limit(56).collect(Collectors.toList());
//如果不使用 ManagedBlocker 耗时估算: 56/78 cpu - 1 = 8 * 2 =16s实际 约等于 2s
actions.forEach(ForkJoinTask::fork);
actions.forEach(ForkJoinTask::join);
}
static void test4() {
List<IoBlockerAction2<Integer>> actions = Stream.generate(() -> new IoBlockerAction2<>((x) -> {
System.out.println(threadDateTimeInfo() + ":simulate io action blocking for 2 seconds···" + x);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new Error(e);
}
System.out.println(threadDateTimeInfo() + ": io blocking action successfully " + x);
}, 1)).limit(56).collect(Collectors.toList());
//如果不使用 ManagedBlocker 耗时估算: 56/78 cpu - 1 = 8 * 2 =16s实际 约等于 2s
actions.forEach(x -> {
x.fork();
System.out.println("fork {}"+ x);
});
actions.forEach(x -> {
x.join();
System.out.println("join {}"+ x);
});
}
}
class IoBlockerAction2<T> extends RecursiveAction {
private static final long serialVersionUID = -4114798302790287199L;
private final MyManagedBlockerImpl<T> blocker;
public IoBlockerAction2(Consumer<T> consumer, T t) {
this.blocker = new MyManagedBlockerImpl<>(consumer, t);
}
static class MyManagedBlockerImpl<T> implements ForkJoinPool.ManagedBlocker {
private final Consumer<T> consumer;
private final T t;
public MyManagedBlockerImpl(Consumer<T> consumer, T t) {
this.consumer = consumer;
this.t = t;
}
@Override
public boolean block() {
consumer.accept(t);
return true;
}
@Override
public boolean isReleasable() {
return false;
}
}
@Override
protected void compute() {
try {
ForkJoinPool.managedBlock(blocker);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
class IoBlockerAction extends RecursiveAction {
private static final long serialVersionUID = -4114798302790287199L;
private final MyManagedBlockerImpl blocker;
public IoBlockerAction(Runnable runnable) {
this.blocker = new MyManagedBlockerImpl(runnable);
}
static class MyManagedBlockerImpl implements ForkJoinPool.ManagedBlocker {
private final Runnable runnable;
public MyManagedBlockerImpl(Runnable runnable) {
this.runnable = runnable;
}
@Override
public boolean block() {
runnable.run();
return true;
}
@Override
public boolean isReleasable() {
return false;
}
}
@Override
protected void compute() {
try {
ForkJoinPool.managedBlock(blocker);
// setRawResult(blocker.result);
// return getRawResult();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
class IoBlockerTask<T> extends RecursiveTask<T> {
private static final long serialVersionUID = -4114798302790287199L;
private final MyManagedBlockerImpl<T> blocker;
public IoBlockerTask(Supplier<T> supplier) {
this.blocker = new MyManagedBlockerImpl<>(supplier);
}
static class MyManagedBlockerImpl<T> implements ForkJoinPool.ManagedBlocker {
private final Supplier<T> supplier;
private T result;
public MyManagedBlockerImpl(Supplier<T> supplier) {
this.supplier = supplier;
}
@Override
public boolean block() {
result = supplier.get();
return true;
}
@Override
public boolean isReleasable() {
return false;
}
}
@Override
protected T compute() {
try {
ForkJoinPool.managedBlock(blocker);
setRawResult(blocker.result);
return getRawResult();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

64
budd-server/pom.xml Normal file
View File

@@ -0,0 +1,64 @@
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>budd-server</artifactId>
<name>budd-server</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd-demo</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,26 +22,20 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.lock;
package io.github.ehlxr;
import java.util.concurrent.locks.ReentrantLock;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
* @author ehlxr
* @since 2021-02-15 18:11.
* @since 2021-08-29 18:32.
*/
public class Locker {
@SpringBootApplication
@ServletComponentScan("io.github.ehlxr.filter")
public class BuddServerApplication {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock();
}
SpringApplication.run(BuddServerApplication.class, args);
}
}

View File

@@ -0,0 +1,141 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.aop;
import com.google.common.base.Strings;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.util.JsonUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 请求日志记录
*
* @author ehlxr
* @since 2021-08-17 22:03.
*/
@Aspect
@Component
public class LogRequestAop {
private static final Logger log = LoggerFactory.getLogger(LogRequestAop.class);
// private final AliyunLogManager aliyunLogManager;
// /**
// * aliyun log 配置
// */
// @Value("${aliyun.log.project:}")
// private String projcet;
// @Value("${aliyun.log.logstore.request:}")
// private String logStore;
// @Value("${aliyun.log.topic:}")
// private String topic;
// @Autowired
// public LogRequestAop(AliyunLogManager aliyunLogManager) {
// this.aliyunLogManager = aliyunLogManager;
// }
/**
* 切入点
*/
@Pointcut("execution(public * io.github.ehlxr.*Controller.*(..)) && !@annotation(io.github.ehlxr.annotations.NoRequestLog)")
// @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && !@annotation(com.tzld.piaoquan.incentive.annotations.NoRequestLog)")
public void requestLog() {
}
/**
* 前置操作
*/
@Before("requestLog()")
public void beforeLog() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
request.setAttribute(Constant.REQUEST_START_TIME, System.currentTimeMillis());
}
/**
* 后置操作
*/
@AfterReturning(pointcut = "requestLog()", returning = "returnValue")
public void afterReturning(JoinPoint point, Object returnValue) {
logRecord(point, JsonUtils.obj2String(returnValue));
}
@AfterThrowing(pointcut = "requestLog()", throwing = "ex")
public void afterThrowing(JoinPoint point, Exception ex) {
logRecord(point, ex.getMessage());
}
private void logRecord(JoinPoint point, String message) {
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
Long startTime = (Long) request.getAttribute(Constant.REQUEST_START_TIME);
if (Objects.isNull(startTime)) {
return;
}
String query = request.getQueryString();
String uri = request.getRequestURI();
Map<String, Object> logMap = new HashMap<>(8);
logMap.put("url", Strings.isNullOrEmpty(query) ? uri : uri + "?" + query);
logMap.put("method", request.getMethod());
logMap.put("header", getHeaders(request));
logMap.put("elapsedTime", String.valueOf(System.currentTimeMillis() - startTime));
logMap.put("clientIp", request.getRemoteAddr());
logMap.put("requestBody", JsonUtils.obj2String(point.getArgs()));
logMap.put(Constant.LOG_TRACE_ID, Strings.nullToEmpty(MDC.get(Constant.LOG_TRACE_ID)));
logMap.put("responseBody", message);
// aliyunLogManager.sendLog(projcet, logStore, topic, logMap);
} catch (Exception e) {
log.error("log report request error", e);
}
}
private String getHeaders(HttpServletRequest request) {
return Collections.list(request.getHeaderNames())
.stream()
.collect(Collectors.toMap(
name -> name,
request::getHeader)).toString();
}
}

View File

@@ -0,0 +1,72 @@
package io.github.ehlxr.config;
import io.github.ehlxr.util.SendAlarmUtil;
import io.github.ehlxr.util.Try;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 项目初始化
*
* @author ehlxr
* @since 2020/4/22.
*/
@Component
public class Initialization implements ApplicationRunner {
private static final Logger log = LoggerFactory.getLogger(Initialization.class);
@Value("${aliyun.oss.endpoint:}")
private String endpoint;
@Value("${aliyun.oss.accesskey.id:}")
private String accessKeyId;
@Value("${aliyun.oss.accesskey.secret:}")
private String accessKeySecret;
@Value("${aliyun.oss.bucket:}")
private String bucket;
@Value("${aliyun.oss.key-path:}")
private String keyPath;
@Value("${aliyun.oss.url-lifetime:0}")
private Long urlLifetime;
@Value("${lk.jmeter.cmd:}")
private String jmeterCmd;
@Value("${location:}")
private String location;
@Value("${lk.dingtalk-url:}")
private String dingtalkUrl;
@Override
public void run(ApplicationArguments args) {
// 初始化阿里云 OSS 配置信息
// AliyunOssConfig config = AliyunOssConfig.newBuilder()
// .endpoint(endpoint)
// .accessKeyId(accessKeyId)
// .accessKeySecret(accessKeySecret)
// .bucketName(bucket)
// .keyPath(keyPath)
// .urlLifetime(urlLifetime)
// .build();
// log.info("aliyun oss config {}", config);
// FileUploadUtil.init(config);
//
// if (!"develop".equals(location) && !"PRO2".equals(location)) {
// try {
// ExecShell.execShellCommand(jmeterCmd);
// } catch (Exception e) {
// log.error("exec jmeter cmd error {}", e.getMessage());
// }
// }
// 预警信息发送初始化
Try.of(() -> SendAlarmUtil.init(dingtalkUrl))
.trap(e -> log.warn("int SendAlarmUtil error: {}", e.getMessage()))
.run();
}
}

View File

@@ -0,0 +1,65 @@
/*
* The MIT License (MIT)
*
* Copyright © 2022 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.config;
// import com.ctrip.framework.apollo.model.ConfigChangeEvent;
// import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.logging.LoggingSystem;
// import org.springframework.stereotype.Component;
/**
* 结合 apollo 配置中心动态刷新logging.level.)日志级别
*
* @author ehlxr
* @since 2022-01-06 17:43.
*/
// @Component
public class LoggerLevelRefresher {
private static final Logger logger = LoggerFactory.getLogger(LoggerLevelRefresher.class);
private static final String LOGGER_TAG = "logging.level.";
private final LoggingSystem loggingSystem;
@Autowired
public LoggerLevelRefresher(LoggingSystem loggingSystem) {
this.loggingSystem = loggingSystem;
}
// @ApolloConfigChangeListener(interestedKeyPrefixes = LOGGER_TAG)
// private void onChange(ConfigChangeEvent changeEvent) {
// for (String key : changeEvent.changedKeys()) {
// String strLevel = changeEvent.getChange(key).getNewValue();
// loggingSystem.setLogLevel(key.replaceAll(LOGGER_TAG, ""),
// LogLevel.valueOf(strLevel.toUpperCase()));
//
// logger.info("logging changed: {}, oldValue: {}, newValue: {}",
// key, changeEvent.getChange(key).getOldValue(), strLevel);
// }
// }
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,25 +22,34 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.extension;
package io.github.ehlxr.controller;
import java.lang.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 把一个接口标识成扩展点
* <p>
* 没有此注释的接口 {@link ExtensionLoader} 会拒绝接管
*
* @author ehlxr
* @see ExtensionLoader
* @since 2021-08-29 18:45.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SPI {
@RestController
@Api(tags = "测试辅助接口")
public class IndexController {
private static final Logger log = LoggerFactory.getLogger(IndexController.class);
/**
* the default extension name.
* 健康检测
*/
String value() default "";
@ApiOperation(value = "健康检测", notes = "健康检测")
@GetMapping("/healthcheck")
public String healthcheck() {
log.debug("env {}", System.getProperty("env"));
return "ok";
}
}

View File

@@ -0,0 +1,77 @@
/*
* The MIT License (MIT)
*
* Copyright © 2021 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.controller.redis;
import io.github.ehlxr.util.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author ehlxr
* @since 2021-08-30 10:08.
*/
@RestController
@Api(tags = "Redis 测试接口")
@RequestMapping("/redis")
public class RedisController {
private static final Logger log = LoggerFactory.getLogger(RedisController.class);
/**
* Redis 锁测试
*/
@ApiOperation(value = "Redis 锁", notes = "Redis 锁测试")
@GetMapping("/lock/test")
public void lockTest() {
Runnable runnable = () -> {
String uuid = UUID.randomUUID().toString();
log.info("{} retry lock...", Thread.currentThread().getName());
boolean lock = RedisUtil.getDistributedLock("lock", uuid, 30_000);
if (lock) {
log.info("{} get lock!", Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
// ...
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Boolean locak = RedisUtil.releaseDistributedLock("lock", uuid);
log.info("{} release lock {}", Thread.currentThread().getName(), locak);
}
}
};
new Thread(runnable, "t1").start();
new Thread(runnable, "t2").start();
}
}

View File

@@ -0,0 +1,42 @@
package io.github.ehlxr.filter;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.util.IdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* auth filter
*
* @author supeng
* @date 2020/08/31
*/
@Order(value = 1)
@WebFilter(filterName = "customFilter", urlPatterns = {"/api/*"})
public class CustomFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);
@Override
public void init(FilterConfig filterConfig) {
log.info("customFilter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
filterChain.doFilter(servletRequest, servletResponse);
MDC.remove(Constant.LOG_TRACE_ID);
}
@Override
public void destroy() {
log.info("customFilter destroy");
}
}

View File

@@ -0,0 +1,66 @@
package io.github.ehlxr.handler;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.common.Result;
import io.github.ehlxr.enums.CodeEnum;
import io.github.ehlxr.exception.ServiceDataException;
import org.assertj.core.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @author ehlxr
* @since 2020/4/20.
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(Exception.class)
@ResponseBody
public Result<?> defaultExceptionHandler(HttpServletRequest request, Exception e) {
log.error("request: {}, exception: ", request.getRequestURI(), e);
// SendAlarmUtil.send(String.format("未知异常 request: %s, exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
// (t, u) -> log.info("send exception message to dingtalk result {} ", t, u));
String msg = CodeEnum.UNKNOWN_EXCEPTION.getMessage();
String traceId = MDC.get(Constant.LOG_TRACE_ID);
if (!Strings.isNullOrEmpty(traceId)) {
msg = String.format("%s%s", msg, traceId);
}
return Result.of(CodeEnum.UNKNOWN_EXCEPTION.getCode(), null, msg);
}
@ExceptionHandler(ServiceDataException.class)
@ResponseBody
public Result<?> serviceDataExceptionHandler(HttpServletRequest request, ServiceDataException e) {
log.error("request: {} service exception: ", request.getRequestURI(), e);
// SendAlarmUtil.send(String.format("业务异常 request: %s, service exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
// (t, u) -> log.info("send service exception message to dingtalk result {} ", t, u));
String msg = e.getMessage();
String traceId = MDC.get(Constant.LOG_TRACE_ID);
if (!Strings.isNullOrEmpty(traceId)) {
msg = String.format("%s%s", msg, traceId);
}
return Result.of(e.getCode(), null, msg);
}
@ExceptionHandler(MultipartException.class)
public String handleError(MultipartException e, RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
return "redirect:/uploadStatus";
}
}

View File

@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,34 +22,31 @@
* THE SOFTWARE.
*/
package io.github.ehlxr;
package io.github.ehlxr.interceptor;
import io.github.ehlxr.common.Constant;
import io.github.ehlxr.util.IdUtil;
import org.slf4j.MDC;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 日志 traceid Interceptor
*
* @author ehlxr
* @date 2018/8/21
* @since 2020-12-23 11:23.
*/
public class ReferenceCountingGC {
public Object instance = null;
private static final int _1MB = 1024 * 1024;
/**
* 这个成员属性的唯一意义就是占点内存以便在能在 GC 日志中看清楚是否有回收过
*/
private final byte[] bigSize = new byte[2 * _1MB];
public static void testGC() {
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
// 假设在这行发生 GCobjA objB 是否能被回收
System.gc();
public class TraceInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
return true;
}
public static void main(String[] args) {
testGC();
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
MDC.remove(Constant.LOG_TRACE_ID);
}
}

View File

@@ -0,0 +1,17 @@
server:
port: 8081
springfox:
documentation:
enabled: true
swagger:
base-package: io.github.ehlxr
base-path: /**
contact:
email: xrv@live.com
name: rtg
url: https://ehlxr.me
description: swagger of budd server
exclude-path: /error, /ops/**
title: budd swagger
version: 0.0.1-SNAPSHOT

View File

@@ -0,0 +1,18 @@
spring:
profiles:
active: dev
application:
name: budd
server:
tomcat:
uri-encoding: UTF-8
accept-count: 1000
connection-timeout: 30000
servlet:
context-path: /budd
session:
timeout: 60
logging:
file:
path: /Users/ehlxr/logs/${spring.application.name}

View File

@@ -0,0 +1,264 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL如果设置为WARN则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
<contextName>logback</contextName>
<!-- name的值是变量的名称value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后可以使“${}”来使用变量。 -->
<!-- <property name="LOG_PATH" value="${logging.file.path}" />-->
<springProperty name="LOG_PATH" source="logging.file.path"/>
<!--<springProperty name="ALIYUN_LOG_ENDPOINT" source="aliyun.log.endpoint"/>-->
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYID" source="aliyun.log.accessKeyId"/>-->
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYSECRET" source="aliyun.log.accessKeySecret"/>-->
<!--<springProperty name="ALIYUN_LOG_PROJECT" source="aliyun.log.project"/>-->
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_INFO" source="aliyun.log.logstore.info"/>-->
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_ERROR" source="aliyun.log.logstore.error"/>-->
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%X{logTraceId}]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--<property name="CONSOLE_LOG_PATTERN"-->
<!-- value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%X{√logTraceId}]){magenta} %clr(-&#45;&#45;){faint} %clr([%15.15t]){faint} %clr(at %class.%method){cyan} \\(%file:%line\\) %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>-->
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用只配置最底级别控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<appender name="ALIYUN_LOG_INFO" class="com.aliyun.openservices.log.logback.LoghubAppender">
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
<project>${ALIYUN_LOG_PROJECT}</project>
<logStore>${ALIYUN_LOG_LOGSTORE_INFO}</logStore>
<totalSizeInBytes>104857600</totalSizeInBytes>
<maxBlockMs>0</maxBlockMs>
<ioThreadCount>8</ioThreadCount>
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
<batchCountThreshold>4096</batchCountThreshold>
<lingerMs>2000</lingerMs>
<retries>10</retries>
<baseRetryBackoffMs>100</baseRetryBackoffMs>
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
<timeZone>Asia/Shanghai</timeZone>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
</filter>
<mdcFields>logTraceId</mdcFields>
</appender>
<appender name="ALIYUN_LOG_ERROR" class="com.aliyun.openservices.log.logback.LoghubAppender">
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
<project>${ALIYUN_LOG_PROJECT}</project>
<logStore>${ALIYUN_LOG_LOGSTORE_ERROR}</logStore>
<totalSizeInBytes>104857600</totalSizeInBytes>
<maxBlockMs>0</maxBlockMs>
<ioThreadCount>8</ioThreadCount>
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
<batchCountThreshold>4096</batchCountThreshold>
<lingerMs>2000</lingerMs>
<retries>10</retries>
<baseRetryBackoffMs>100</baseRetryBackoffMs>
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
<timeZone>Asia/Shanghai</timeZone>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<mdcFields>logTraceId</mdcFields>
</appender>
-->
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别大小写无关TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
还有一个特俗值INHERITED或者同义词NULL代表强制执行上级的级别。
如果未设置此属性那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--<logger name="org.springframework.web" level="info"/>-->
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
<!--
使用mybatis的时候sql语句是debug下才会打印而这里我们只配置了info所以想要查看sql语句的话有以下两种操作
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式代码如下这样配置sql语句会打印其他还是正常info级别
-->
<!--
root节点是必选节点用来指定最基础的日志输出级别只有一个level属性
level:用来设置打印级别大小写无关TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素标识这个appender将会添加到这个logger。
-->
<springProfile name="dev">
<logger name="io.github.ehlxr" level="debug"/>
</springProfile>
<!--<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="warn"/>-->
<!-- 可用来获取 StatusManager 中的状态 -->
<!--<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>-->
<!-- 解决 aliyun loghub debug模式下循环发送的问题 -->
<logger name="org.apache.http.impl.conn.Wire" level="WARN"/>
<!--aliyun loghub 为了防止进程退出时,内存中的数据丢失,请加上此选项-->
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<root level="info">
<appender-ref ref="CONSOLE"/>
<!--<appender-ref ref="DEBUG_FILE"/>-->
<!--<appender-ref ref="INFO_FILE"/>-->
<!--<appender-ref ref="WARN_FILE"/>-->
<!--<appender-ref ref="ERROR_FILE"/>-->
<!--<appender-ref ref="ALIYUN_LOG_INFO"/>-->
<!--<appender-ref ref="ALIYUN_LOG_ERROR"/>-->
</root>
</configuration>

View File

@@ -0,0 +1,65 @@
package com.tzld.activity;
import io.github.ehlxr.semaphore.RedisSemaphore;
import io.github.ehlxr.semaphore.SemaphoreInfo;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.concurrent.*;
@RunWith(SpringRunner.class)
@SpringBootTest()
class ServerApplicationTests {
ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 0, TimeUnit.MINUTES,
new LinkedBlockingQueue<>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Test
public void testNonFair() throws InterruptedException {
SemaphoreInfo semaphoreInfo = new SemaphoreInfo("NonFair", 5, 10);
for (int i = 0; i < 10; i++) {
String id = String.valueOf(i);
RedisSemaphore semaphore = new RedisSemaphore(semaphoreInfo, redisTemplate, id);
CompletableFuture.supplyAsync(semaphore::tryAcquire, pool).thenAcceptAsync((r) -> {
if (r) System.out.println(id + "成功获取到信号量 (NonFair)~ ⭐⭐⭐");
else System.out.println(id + "没有获取到信号量 (NonFair)");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release();
}, pool);
}
Thread.sleep(Long.MAX_VALUE);
}
@Test
public void testFair() throws ExecutionException, InterruptedException {
SemaphoreInfo semaphoreInfo = new SemaphoreInfo("Fair", 5, 10, true);
for (int i = 0; i < 10; i++) {
String id = String.valueOf(i);
RedisSemaphore semaphore = new RedisSemaphore(semaphoreInfo, redisTemplate, id);
CompletableFuture.supplyAsync(semaphore::tryAcquire, pool).thenAcceptAsync((r) -> {
if (r) System.out.println(id + "成功获取到信号量 (Fair)~~ ⭐⭐⭐");
else System.out.println(id + "没有获取到信号量 (Fair)");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release();
}, pool);
}
Thread.sleep(Long.MAX_VALUE);
}
}

38
budd-utils/pom.xml Normal file
View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>budd-utils</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,424 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrv@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.utils;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
/**
* 异常处理,简化 try catch
*
* @author ehlxr
* @since 2020-12-03 10:37.
*/
public interface Try {
/**
* 构建消费型有入参无返回Tryable 对象
*
* @param consumer {@link ThrowableConsumer} 类型函数式接口
* @param <P> 入参类型
* @return {@link TryConsumer}
*/
static <P> TryConsumer<P> of(ThrowableConsumer<? super P> consumer) {
return new TryConsumer<>(consumer);
}
/**
* 构建供给型无入参有返回Tryable 对象
*
* @param supplier {@link ThrowableSupplier} 类型函数式接口
* @param <R> 返回值类型
* @return {@link TrySupplier}
*/
static <R> TrySupplier<R> of(ThrowableSupplier<? extends R> supplier) {
return new TrySupplier<>(supplier);
}
/**
* 构建功能型有入参有返回Tryable 对象
*
* @param function {@link ThrowableFunction} 类型函数式接口
* @param <P> 入参类型
* @param <R> 返回值类型
* @return {@link TryFunction}
*/
static <P, R> TryFunction<P, R> of(ThrowableFunction<? super P, ? extends R> function) {
return new TryFunction<>(function);
}
/**
* 构建运行型无入参无返回Tryable 对象
*
* @param runnable {@link ThrowableRunnable} 类型函数式接口
* @return {@link TryRunnable}
*/
static TryRunnable of(ThrowableRunnable runnable) {
return new TryRunnable(runnable);
}
@SuppressWarnings({"ConstantConditions", "Convert2MethodRef"})
static void main(String[] args) {
System.out.println("------------有返回值,无入参----------------");
// 有返回值,无入参
String param = "hello";
Long result = Try.of(() -> Long.valueOf(param)).get(0L);
System.out.println("Long.valueOf 1: " + result);
result = Try.of(() -> Long.valueOf(param)).get();
System.out.println("Long.valueOf 2: " + result);
System.out.println("------------有返回值,有入参----------------");
// 有返回值,有入参
result = Try.<Map<String, String>, Long>of(s -> Long.valueOf(s.get("k1")))
// .apply(ImmutableMap.of("k1", param))
.trap(e -> System.out.println("Long.valueOf exception: " + e.getMessage()))
.andFinally(() -> System.out.println("This message will ignore."))
.andFinally(s -> {
// Map<String, Object> returnMap = JsonUtils.string2Obj(JsonUtils.obj2String(s), new TypeReference<Map<String, Object>>() {
// });
// System.out.println("Long.valueOf finally run code." + s);
// // 演示抛异常
// String k2 = returnMap.get("k2").toString();
// System.out.println(k2);
})
.finallyTrap(e -> System.out.println("Long.valueOf finally exception: " + e.getMessage()))
.get();
System.out.println("Long.valueOf 3: " + result);
ArrayList<String> list = null;
System.out.println("-----------无返回值,无入参-----------------");
// 无返回值,无入参
Try.of(() -> Thread.sleep(-1L))
.andFinally(() -> list.clear())
// .andFinally(list::clear) //https://stackoverflow.com/questions/37413106/java-lang-nullpointerexception-is-thrown-using-a-method-reference-but-not-a-lamb
.run();
System.out.println("--------------无返回值,有入参--------------");
// 无返回值,有入参
Try.<String>of(v -> list.add(0, v))
.andFinally(s -> System.out.println(s))
.accept("hello");
}
class TryRunnable extends Tryable<TryRunnable> {
private final ThrowableRunnable runnable;
protected TryRunnable(ThrowableRunnable runnable) {
Objects.requireNonNull(runnable, "No runnable present");
this.runnable = runnable;
super.c = this;
}
/**
* 计算结果
*/
public void run() {
try {
runnable.run();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
} finally {
doFinally();
}
}
}
class TrySupplier<R> extends Tryable<TrySupplier<R>> {
private final ThrowableSupplier<? extends R> supplier;
protected TrySupplier(ThrowableSupplier<? extends R> supplier) {
Objects.requireNonNull(supplier, "No supplier present");
this.supplier = supplier;
super.c = this;
}
/**
* 如果有异常返回默认值,否则返回计算结果
*
* @param r 指定默认值
* @return 实际值或默认值
*/
public R get(R r) {
try {
return supplier.get();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return r;
} finally {
doFinally();
}
}
/**
* 如果有异常返回 null否则返回计算结果
*
* @return 实际值或 null
*/
public R get() {
try {
return supplier.get();
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return null;
} finally {
doFinally();
}
}
}
@FunctionalInterface
interface ThrowableConsumer<P> {
/**
* Performs this operation on the given argument.
*
* @param p the input argument
* @throws Throwable throwable
*/
void accept(P p) throws Throwable;
}
@FunctionalInterface
interface ThrowableSupplier<R> {
/**
* Gets a result.
*
* @return a result
* @throws Throwable throwable
*/
R get() throws Throwable;
}
@FunctionalInterface
interface ThrowableRunnable {
/**
* Performs this operation
*
* @throws Throwable throwable
*/
void run() throws Throwable;
}
@FunctionalInterface
interface ThrowableFunction<P, R> {
/**
* Applies this function to the given argument.
*
* @param p the function argument
* @return the function result
* @throws Throwable throwable
*/
R apply(P p) throws Throwable;
}
abstract class Tryable<C> {
Consumer<? super Throwable> throwConsumer;
ThrowableRunnable finallyRunnable;
ThrowableConsumer<? super Object> finallyConsumer;
Consumer<? super Throwable> finallyThrowConsumer;
C c;
/**
* 处理 finally
*/
protected void doFinally() {
Optional.ofNullable(finallyRunnable).ifPresent(r -> {
try {
r.run();
} catch (final Throwable e) {
Optional.ofNullable(finallyThrowConsumer).ifPresent(tc -> tc.accept(e));
}
});
}
/**
* 处理带参数类型 finally
*
* @param p 入参
* @param <P> 入参类型
*/
protected <P> void doFinally(P p) {
if (Objects.nonNull(finallyConsumer)) {
try {
finallyConsumer.accept(p);
} catch (final Throwable e) {
Optional.ofNullable(finallyThrowConsumer).ifPresent(tc -> tc.accept(e));
}
} else {
doFinally();
}
}
/**
* 如果有异常,调用自定义异常处理表达式
*
* @param throwableConsumer 自定义异常处理 lambda 表达式
* @return {@link C}
*/
public C trap(Consumer<? super Throwable> throwableConsumer) {
Objects.requireNonNull(throwableConsumer, "No throwableConsumer present");
this.throwConsumer = throwableConsumer;
return c;
}
/**
* 自定义 finally 处理表达式
* <p>
* 注意:如果类型为 {@link TryConsumer}、{@link TryFunction} 并且已经调用 {@link #andFinally(ThrowableConsumer)} 则忽略
*
* @param finallyRunnable finally 处理 lambda 表达式
* @return {@link C}
*/
public C andFinally(ThrowableRunnable finallyRunnable) {
Objects.requireNonNull(finallyRunnable, "No finallyRunnable present");
this.finallyRunnable = finallyRunnable;
return c;
}
/**
* 自定义 finally 处理表达式
* <p>
* 注意:只会对 {@link TryConsumer}、{@link TryFunction} 类型对象起作用
*
* @param finallyConsumer finally 处理 lambda 表达式
* @return {@link C}
*/
public C andFinally(ThrowableConsumer<? super Object> finallyConsumer) {
Objects.requireNonNull(finallyConsumer, "No finallyConsumer present");
this.finallyConsumer = finallyConsumer;
return c;
}
/**
* 如果 finally 有异常,调用自定义异常处理表达式
*
* @param finallyThrowableConsumer 自定义异常处理 lambda 表达式
* @return {@link C}
*/
public C finallyTrap(Consumer<? super Throwable> finallyThrowableConsumer) {
Objects.requireNonNull(finallyThrowableConsumer, "No finallyThrowableConsumer present");
this.finallyThrowConsumer = finallyThrowableConsumer;
return c;
}
}
class TryConsumer<P> extends Tryable<TryConsumer<P>> {
private final ThrowableConsumer<? super P> consumer;
protected TryConsumer(ThrowableConsumer<? super P> consumer) {
Objects.requireNonNull(consumer, "No consumer present");
this.consumer = consumer;
super.c = this;
}
/**
* 计算结果
*
* @param p 要计算的入参
*/
public void accept(P p) {
try {
Objects.requireNonNull(p, "No accept param present");
consumer.accept(p);
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
} finally {
// doFinally();
doFinally(p);
}
}
}
class TryFunction<P, R> extends Tryable<TryFunction<P, R>> {
private final ThrowableFunction<? super P, ? extends R> function;
private P p;
protected TryFunction(ThrowableFunction<? super P, ? extends R> function) {
Objects.requireNonNull(function, "No function present");
this.function = function;
super.c = this;
}
/**
* 传入要计算的入参
*
* @param p 要计算的入参
* @return {@link TryFunction}
*/
public TryFunction<P, R> apply(P p) {
Objects.requireNonNull(p, "Apply param should not null");
this.p = p;
return this;
}
/**
* 如果有异常返回默认值,否则返回计算结果
*
* @param r 指定默认值
* @return 实际值或默认值
*/
public R get(R r) {
try {
Objects.requireNonNull(function, "No apply param present");
return function.apply(p);
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return r;
} finally {
// doFinally();
doFinally(p);
}
}
/**
* 如果有异常返回 null否则返回计算结果
*
* @return 实际值或 null
*/
public R get() {
try {
Objects.requireNonNull(p, "No apply param present");
return function.apply(p);
} catch (final Throwable e) {
Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e));
return null;
} finally {
// doFinally();
doFinally(p);
}
}
}
}

66
jetbrains.svg Normal file
View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="120.1px" height="130.2px" viewBox="0 0 120.1 130.2" style="enable-background:new 0 0 120.1 130.2;" xml:space="preserve"
>
<g>
<linearGradient id="XMLID_2_" gradientUnits="userSpaceOnUse" x1="31.8412" y1="120.5578" x2="110.2402" y2="73.24">
<stop offset="0" style="stop-color:#FCEE39"/>
<stop offset="1" style="stop-color:#F37B3D"/>
</linearGradient>
<path id="XMLID_3041_" style="fill:url(#XMLID_2_);" d="M118.6,71.8c0.9-0.8,1.4-1.9,1.5-3.2c0.1-2.6-1.8-4.7-4.4-4.9
c-1.2-0.1-2.4,0.4-3.3,1.1l0,0l-83.8,45.9c-1.9,0.8-3.6,2.2-4.7,4.1c-2.9,4.8-1.3,11,3.6,13.9c3.4,2,7.5,1.8,10.7-0.2l0,0l0,0
c0.2-0.2,0.5-0.3,0.7-0.5l78-54.8C117.3,72.9,118.4,72.1,118.6,71.8L118.6,71.8L118.6,71.8z"/>
<linearGradient id="XMLID_3_" gradientUnits="userSpaceOnUse" x1="48.3607" y1="6.9083" x2="119.9179" y2="69.5546">
<stop offset="0" style="stop-color:#EF5A6B"/>
<stop offset="0.57" style="stop-color:#F26F4E"/>
<stop offset="1" style="stop-color:#F37B3D"/>
</linearGradient>
<path id="XMLID_3049_" style="fill:url(#XMLID_3_);" d="M118.8,65.1L118.8,65.1L55,2.5C53.6,1,51.6,0,49.3,0
c-4.3,0-7.7,3.5-7.7,7.7v0c0,2.1,0.8,3.9,2.1,5.3l0,0l0,0c0.4,0.4,0.8,0.7,1.2,1l67.4,57.7l0,0c0.8,0.7,1.8,1.2,3,1.3
c2.6,0.1,4.7-1.8,4.9-4.4C120.2,67.3,119.7,66,118.8,65.1z"/>
<linearGradient id="XMLID_4_" gradientUnits="userSpaceOnUse" x1="52.9467" y1="63.6407" x2="10.5379" y2="37.1562">
<stop offset="0" style="stop-color:#7C59A4"/>
<stop offset="0.3852" style="stop-color:#AF4C92"/>
<stop offset="0.7654" style="stop-color:#DC4183"/>
<stop offset="0.957" style="stop-color:#ED3D7D"/>
</linearGradient>
<path id="XMLID_3042_" style="fill:url(#XMLID_4_);" d="M57.1,59.5C57,59.5,17.7,28.5,16.9,28l0,0l0,0c-0.6-0.3-1.2-0.6-1.8-0.9
c-5.8-2.2-12.2,0.8-14.4,6.6c-1.9,5.1,0.2,10.7,4.6,13.4l0,0l0,0C6,47.5,6.6,47.8,7.3,48c0.4,0.2,45.4,18.8,45.4,18.8l0,0
c1.8,0.8,3.9,0.3,5.1-1.2C59.3,63.7,59,61,57.1,59.5z"/>
<linearGradient id="XMLID_5_" gradientUnits="userSpaceOnUse" x1="52.1736" y1="3.7019" x2="10.7706" y2="37.8971">
<stop offset="0" style="stop-color:#EF5A6B"/>
<stop offset="0.364" style="stop-color:#EE4E72"/>
<stop offset="1" style="stop-color:#ED3D7D"/>
</linearGradient>
<path id="XMLID_3057_" style="fill:url(#XMLID_5_);" d="M49.3,0c-1.7,0-3.3,0.6-4.6,1.5L4.9,28.3c-0.1,0.1-0.2,0.1-0.2,0.2l-0.1,0
l0,0c-1.7,1.2-3.1,3-3.9,5.1C-1.5,39.4,1.5,45.9,7.3,48c3.6,1.4,7.5,0.7,10.4-1.4l0,0l0,0c0.7-0.5,1.3-1,1.8-1.6l34.6-31.2l0,0
c1.8-1.4,3-3.6,3-6.1v0C57.1,3.5,53.6,0,49.3,0z"/>
<g id="XMLID_3008_">
<rect id="XMLID_3033_" x="34.6" y="37.4" style="fill:#000000;" width="51" height="51"/>
<rect id="XMLID_3032_" x="39" y="78.8" style="fill:#FFFFFF;" width="19.1" height="3.2"/>
<g id="XMLID_3009_">
<path id="XMLID_3030_" style="fill:#FFFFFF;" d="M38.8,50.8l1.5-1.4c0.4,0.5,0.8,0.8,1.3,0.8c0.6,0,0.9-0.4,0.9-1.2l0-5.3l2.3,0
l0,5.3c0,1-0.3,1.8-0.8,2.3c-0.5,0.5-1.3,0.8-2.3,0.8C40.2,52.2,39.4,51.6,38.8,50.8z"/>
<path id="XMLID_3028_" style="fill:#FFFFFF;" d="M45.3,43.8l6.7,0v1.9l-4.4,0V47l4,0l0,1.8l-4,0l0,1.3l4.5,0l0,2l-6.7,0
L45.3,43.8z"/>
<path id="XMLID_3026_" style="fill:#FFFFFF;" d="M55,45.8l-2.5,0l0-2l7.3,0l0,2l-2.5,0l0,6.3l-2.3,0L55,45.8z"/>
<path id="XMLID_3022_" style="fill:#FFFFFF;" d="M39,54l4.3,0c1,0,1.8,0.3,2.3,0.7c0.3,0.3,0.5,0.8,0.5,1.4v0
c0,1-0.5,1.5-1.3,1.9c1,0.3,1.6,0.9,1.6,2v0c0,1.4-1.2,2.3-3.1,2.3l-4.3,0L39,54z M43.8,56.6c0-0.5-0.4-0.7-1-0.7l-1.5,0l0,1.5
l1.4,0C43.4,57.3,43.8,57.1,43.8,56.6L43.8,56.6z M43,59l-1.8,0l0,1.5H43c0.7,0,1.1-0.3,1.1-0.8v0C44.1,59.2,43.7,59,43,59z"/>
<path id="XMLID_3019_" style="fill:#FFFFFF;" d="M46.8,54l3.9,0c1.3,0,2.1,0.3,2.7,0.9c0.5,0.5,0.7,1.1,0.7,1.9v0
c0,1.3-0.7,2.1-1.7,2.6l2,2.9l-2.6,0l-1.7-2.5h-1l0,2.5l-2.3,0L46.8,54z M50.6,58c0.8,0,1.2-0.4,1.2-1v0c0-0.7-0.5-1-1.2-1
l-1.5,0v2H50.6z"/>
<path id="XMLID_3016_" style="fill:#FFFFFF;" d="M56.8,54l2.2,0l3.5,8.4l-2.5,0l-0.6-1.5l-3.2,0l-0.6,1.5l-2.4,0L56.8,54z
M58.8,59l-0.9-2.3L57,59L58.8,59z"/>
<path id="XMLID_3014_" style="fill:#FFFFFF;" d="M62.8,54l2.3,0l0,8.3l-2.3,0L62.8,54z"/>
<path id="XMLID_3012_" style="fill:#FFFFFF;" d="M65.7,54l2.1,0l3.4,4.4l0-4.4l2.3,0l0,8.3l-2,0L68,57.8l0,4.6l-2.3,0L65.7,54z"
/>
<path id="XMLID_3010_" style="fill:#FFFFFF;" d="M73.7,61.1l1.3-1.5c0.8,0.7,1.7,1,2.7,1c0.6,0,1-0.2,1-0.6v0
c0-0.4-0.3-0.5-1.4-0.8c-1.8-0.4-3.1-0.9-3.1-2.6v0c0-1.5,1.2-2.7,3.2-2.7c1.4,0,2.5,0.4,3.4,1.1l-1.2,1.6
c-0.8-0.5-1.6-0.8-2.3-0.8c-0.6,0-0.8,0.2-0.8,0.5v0c0,0.4,0.3,0.5,1.4,0.8c1.9,0.4,3.1,1,3.1,2.6v0c0,1.7-1.3,2.7-3.4,2.7
C76.1,62.5,74.7,62,73.7,61.1z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

391
pom.xml
View File

@@ -1,13 +1,18 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>budd-common</module>
<module>budd-demo</module>
<module>budd-server</module>
<module>budd-utils</module>
</modules>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>budd</name>
<url>http://maven.apache.org</url>
<name>budd-parent</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -16,347 +21,53 @@
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring.version>5.2.6.RELEASE</spring.version>
<servlet.version>2.5</servlet.version>
<mybatis.version>3.2.7</mybatis.version>
<mybatis.spring.version>1.1.1</mybatis.spring.version>
<mybatis.generator.core.version>1.4.0</mybatis.generator.core.version>
<file_encoding>utf-8</file_encoding>
<jdk.verion>1.8</jdk.verion>
<powermock.version>1.7.1</powermock.version>
<kotlin.version>1.3.61</kotlin.version>
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
<guava.version>30.0-jre</guava.version>
<spring4all.swagger.version>2.0.0.RELEASE</spring4all.swagger.version>
</properties>
<dependencies>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.53</version>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<!-- Google Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<!-- <scope>test</scope> -->
</dependency>
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>${spring4all.swagger.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>io.github.ehlxr</groupId>
<artifactId>budd-demo</artifactId>
<version>${project.version}</version>
</dependency>
<!-- spring begin-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.25</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring end-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<!-- mybatis start -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis.generator.core.version}</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- mybatis end -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.13.3</version>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>4.5</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
<version>2.1.8</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-jre</version>
</dependency>
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-props</artifactId>
<version>3.6.1</version>
</dependency>
<!--<dependency>-->
<!-- <groupId>cn.ceres.did</groupId>-->
<!-- <artifactId>did-sdk</artifactId>-->
<!-- <version>1.0-SNAPSHOT</version>-->
<!--</dependency>-->
<!--<dependency>-->
<!-- <groupId>cn.enncloud.ceres</groupId>-->
<!-- <artifactId>ceres</artifactId>-->
<!-- <version>1.1.0-SNAPSHOT</version>-->
<!--</dependency>-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>4.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.7</version>
</dependency>
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.10.3</version>
</dependency>
<dependency>
<groupId>pl.touk</groupId>
<artifactId>throwing-function</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<artifactId>did-sdk</artifactId>
<groupId>io.github.ehlxr</groupId>
<version>1.0.2-SNAPSHOT</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>github</id>
<url>https://git.ehlxr.me/ehlxr/maven-repository/raw/branch/main</url>
<!--<url>https://raw.githubusercontent.com/ehlxr/maven-repository/main</url>-->
</repository>
</repositories>
<!--<repositories>-->
<!-- <repository>-->
<!-- &lt;!&ndash;-->
<!-- 需要在 setting.xml 中配置认证信息-->
<!-- <servers>-->
<!-- <server>-->
<!-- <id>github</id>-->
<!-- <username>ehlxr</username>-->
<!-- <password>${env.GITHUB_MVN_TOKEN}</password>-->
<!-- </server>-->
<!-- </servers>-->
<!-- &ndash;&gt;-->
<!-- <id>github</id>-->
<!-- <url>https://maven.pkg.github.com/ehlxr/mvn-repository</url>-->
<!-- <releases>-->
<!-- <enabled>true</enabled>-->
<!-- </releases>-->
<!-- <snapshots>-->
<!-- <enabled>true</enabled>-->
<!-- </snapshots>-->
<!-- </repository>-->
<!--</repositories>-->
</project>

View File

@@ -1,104 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
/**
* Created by ehlxr on 2017/8/3.
*/
public class CharToHex {
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static void main(String[] args) throws Exception {
String hex = bytesToHex("".getBytes());
System.out.println(hex);
System.out.println(toUnicode(""));
// 十六进制 -> 十进制
int i = Integer.parseInt(hex, 16);
System.out.println(i);
// 十进制 -> 二进制
String bin = Integer.toBinaryString(i);
System.out.println(bin);
// 十进制 -> 十六进制
String hex1 = Integer.toHexString(i);
System.out.println(hex1);
// 十进制 -> 八进制
String oct = Integer.toOctalString(i);
System.out.println(oct);
System.out.println("---------------");
System.out.println(Integer.toBinaryString(-22));
//测试 int 转 byte
int int0 = 234;
byte byte0 = intToByte(int0);
System.out.println("byte0= " + byte0);//byte0=-22
//测试 byte 转 int
int int1 = byteToInt(byte0);
System.out.println("int1= " + int1);//int1=234
}
//byte 与 int 的相互转换
public static byte intToByte(int x) {
return (byte) x;
}
public static int byteToInt(byte b) {
//Java 总是把 byte 当做有符处理;我们可以通过将其和 0xFF 进行二进制与得到它的无符值
return b & 0xFF;
}
/**
* 字符对应编码的哈希值
*
* @param bytes
* @return
*/
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static String toUnicode(String s) {
String[] as = new String[s.length()];
StringBuilder s1 = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
as[i] = Integer.toHexString(s.charAt(i) & 0xffff);
s1.append("\\u").append(as[i]);
}
return s1.toString();
}
}

View File

@@ -1,114 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import java.io.*;
/**
* Created by ehlxr on 2017/11/17.
* <p>
* 递归扫描 Java 文件,添加 CopyRight 信息,已有跳过
*/
public class ContentReplace {
private static int total = 0;
private static int unDeal = 0;
public static void main(String[] args) throws IOException {
File dir = new File("/Users/ehlxr/WorkSpaces/Budd");
deal(dir);
System.out.println("总文件数:" + total);
System.out.println("未处理文件数:" + unDeal);
}
private static void deal(File file) throws IOException {
if (file.isDirectory()) {
File[] fs = file.listFiles(((dir, name) -> {
File f = new File(dir.getPath() + File.separator + name);
return (f.getPath().contains("src") && name.endsWith(".java")) || f.isDirectory();
}));
for (File f : fs != null ? fs : new File[0]) {
deal(f);
}
} else {
++total;
// System.out.println(file.getPath());
File tmp = File.createTempFile("tmp", null);
try (
FileOutputStream tmpOut = new FileOutputStream(tmp);
FileInputStream tmpIn = new FileInputStream(tmp);
RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
byte[] buf = new byte[64];
int hasRead;
while ((hasRead = raf.read(buf)) > 0) {
if (new String(buf).contains("Copyright")) {
++unDeal;
System.out.println("未处理文件:" + file.getPath());
return;
}
// 把原有内容读入临时文件
tmpOut.write(buf, 0, hasRead);
}
raf.seek(0L);
String tmpl = "/*\n" +
" * The MIT License (MIT)\n" +
" *\n" +
" * Copyright © 2020 xrv <xrg@live.com>\n" +
" *\n" +
" * Permission is hereby granted, free of charge, to any person obtaining a copy\n" +
" * of this software and associated documentation files (the \"Software\"), to deal\n" +
" * in the Software without restriction, including without limitation the rights\n" +
" * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" +
" * copies of the Software, and to permit persons to whom the Software is\n" +
" * furnished to do so, subject to the following conditions:\n" +
" *\n" +
" * The above copyright notice and this permission notice shall be included in\n" +
" * all copies or substantial portions of the Software.\n" +
" *\n" +
" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" +
" * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" +
" * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" +
" * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" +
" * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" +
" * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n" +
" * THE SOFTWARE.\n" +
" */\n\n";
raf.write(tmpl.getBytes());
// raf.write("/*\n".getBytes());
// raf.write(Files.readAllBytes(Paths.get(System.getProperty("user.dir") + File.separator + "LICENSE")));
// raf.write("\n*/\n\n".getBytes());
// 追加临时文件内容
while ((hasRead = tmpIn.read(buf)) > 0) {
raf.write(buf, 0, hasRead);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -1,72 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import java.io.*;
@SuppressWarnings("ALL")
public class ContentReplace2 {
public static void main(String[] args) {
File file = new File("/Users/ehlxr/ehlxr/blog/hugoBlog/content/post");
File[] files = file.listFiles();
for (File f : files) {
operationFile(f);
}
}
private static void operationFile(File file) {
File tmpfile = new File(file.getParentFile().getAbsolutePath() + "\\" + file.getName() + ".tmp");
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
BufferedWriter writer = new BufferedWriter(new FileWriter(tmpfile))) {
boolean flag = false;
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("title")) {
System.out.println(line);
// StringBuilder sb = new StringBuilder();
// line = sb.append("title: \"").append(line.substring(line.indexOf("title") + 7)).append("\"").toString();
line = line.replaceAll("'", "");
System.out.println(line);
flag = true;
}
writer.write(line + "\n");
}
if (flag) {
file.delete();
tmpfile.renameTo(new File(file.getAbsolutePath()));
} else {
tmpfile.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,122 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import org.apache.commons.codec.binary.Base64;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* Created by ehlxr on 2017/8/1.
*/
public class DemoECDSA {
//摘要
private static final String strMsg = "hold on";
public static void main(String[] args) throws Exception {
jdkECDSA();
}
/**
* ECDSA 微软的椭圆曲线算法 jdk1.7以后引入的算法
*
* @throws Exception
*/
public static void jdkECDSA() throws Exception {
//1.初始化密钥
KeyPair keyPair = initKey();
//2.执行签名(用私钥签名)
ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();
byte[] sign = privateKeySign(strMsg, ecPrivateKey);
String signStr = Base64.encodeBase64String(sign);
System.out.println("sign String :" + signStr);//数字签名格式转换,以便报文传输用
ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
String publicKeyStr = Base64.encodeBase64String(ecPublicKey.getEncoded());
System.out.println("publicKeyStr String :" + publicKeyStr);//提供给对端,以便于对端使用公钥验证签名
//3.验证签名(公钥验证签名)
boolean result = publicKeyVerify(Base64.decodeBase64(signStr), Base64.decodeBase64(publicKeyStr));
System.out.println("JDK DSA verify:" + result);
}
/**
* 1.初始化密钥采用ECDSA
*
* @return
* @throws Exception
*/
public static KeyPair initKey() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
keyPairGenerator.initialize(256); //key长度设置
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
/**
* 2.执行签名(用私钥签名)
*
* @return
* @throws Exception
*/
public static byte[] privateKeySign(String data, ECPrivateKey ecPrivateKey) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA1withECDSA");
signature.initSign(privateKey);
signature.update(strMsg.getBytes());
byte[] sign = signature.sign();
return sign;
}
/**
* 3.公钥验证签名(摘要+签名串+公钥)
*
* @throws Exception
*/
public static boolean publicKeyVerify(byte[] sign, byte[] dsaPublicKey) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance("SHA1withECDSA");
signature.initVerify(publicKey);
signature.update(strMsg.getBytes());
boolean result = signature.verify(sign);
return result;
}
}

View File

@@ -1,92 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import java.io.*;
import java.lang.management.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Code which writes a stack dump for all threads to a file.
*/
public class DumpStack {
// directory where the stack files are written
private static final String STACK_DUMP_DIR = "/var/tmp";
// here for testing
public static void main(String[] args) throws Exception {
dumpStacks();
}
private static void dumpStacks() throws IOException {
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
ThreadInfo[] threadInfos = mxBean.getThreadInfo(mxBean.getAllThreadIds(), 0);
Map<Long, ThreadInfo> threadInfoMap = new HashMap<>();
for (ThreadInfo threadInfo : threadInfos) {
threadInfoMap.put(threadInfo.getThreadId(), threadInfo);
}
// choose our dump-file
File dumpFile = new File(STACK_DUMP_DIR, "stacks." + System.currentTimeMillis());
try (Writer writer = new BufferedWriter(new FileWriter(dumpFile))) {
dumpTraces(mxBean, threadInfoMap, writer);
}
}
private static void dumpTraces(ThreadMXBean mxBean, Map<Long, ThreadInfo> threadInfoMap, Writer writer)
throws IOException {
Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces();
writer.write("Dump of " + stacks.size() + " thread at "
+ new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z").format(new Date(System.currentTimeMillis())) + "\n\n");
for (Map.Entry<Thread, StackTraceElement[]> entry : stacks.entrySet()) {
Thread thread = entry.getKey();
writer.write("\"" + thread.getName() + "\" prio=" + thread.getPriority() + " tid=" + thread.getId() + " "
+ thread.getState() + " " + (thread.isDaemon() ? "deamon" : "worker") + "\n");
ThreadInfo threadInfo = threadInfoMap.get(thread.getId());
if (threadInfo != null) {
writer.write(" native=" + threadInfo.isInNative() + ", suspended=" + threadInfo.isSuspended()
+ ", block=" + threadInfo.getBlockedCount() + ", wait=" + threadInfo.getWaitedCount() + "\n");
writer.write(" lock=" + threadInfo.getLockName() + " owned by " + threadInfo.getLockOwnerName()
+ " (" + threadInfo.getLockOwnerId() + "), cpu="
+ (mxBean.getThreadCpuTime(threadInfo.getThreadId()) / 1000000L) + ", user="
+ (mxBean.getThreadUserTime(threadInfo.getThreadId()) / 1000000L) + "\n");
}
for (StackTraceElement element : entry.getValue()) {
writer.write(" ");
writer.write(element.toString());
writer.write("\n");
}
writer.write("\n");
}
}
}

View File

@@ -1,68 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import java.io.*;
/**
* @author ehlxr
*/
public class FindRequestMapping {
private static final int total = 0;
private static final int unDeal = 0;
public static void main(String[] args) throws IOException {
File dir = new File("/Users/ehlxr/WorkSpaces/enncloud/ceres-epns/ceres-epns-web/src/main/java/com/ceres/epns/web");
deal(dir);
}
private static void deal(File file) throws IOException {
if (file.isDirectory()) {
File[] fs = file.listFiles(((dir, name) -> {
File f = new File(dir.getPath() + File.separator + name);
return (f.getPath().contains("src") && name.endsWith(".java")) || f.isDirectory();
}));
for (File f : fs != null ? fs : new File[0]) {
deal(f);
}
} else {
InputStreamReader read = new InputStreamReader(new FileInputStream(file));
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt;
while ((lineTxt = bufferedReader.readLine()) != null) {
if (lineTxt.contains("@RequestMapping")) {
System.out.println(lineTxt);
}
}
bufferedReader.close();
read.close();
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
/**
* Created by ehlxr on 2016/11/8.
*/
public class MD2Json {
public static void main(String[] args) throws IOException {
resume();
}
private static void resume() throws IOException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("show", 1);
String content = FileUtils.readFileToString(new File("E:\\ehlxr\\Git\\md-files\\resume.md"), "UTF-8");
jsonObject.put("content", content);
System.out.println(jsonObject.toString());
}
}

View File

@@ -1,127 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import java.io.*;
/*
* 替换文件如果该文件含有子目录则包括子目录所有文件中某个字符串并写入新内容Java代码实现.
*
*原理:逐行读取源文件的内容,一边读取一边同时写一个*.tmp的文件。
*当读取的行中发现有需要被替换和改写的目标内容‘行’时候,用新的内容‘行’替换之。
*最终,删掉源文件,把*.tmp的文件重命名为源文件名字。
*
*注意!代码功能是逐行读取一个字符串,然后检测该字符串‘行’中是否含有替换的内容,有则用新的字符串‘行’替换源文件中该处整个字符串‘行’。没有则继续读。
*注意!替换是基于‘行’,逐行逐行的替换!
*
* */
public class Modify {
private final String target;
private final String newContent;
private final String path;
public Modify(String path, String target, String newContent) {
// 操作目录。从该目录开始。该文件目录下及其所有子目录的文件都将被替换。
this.path = path;
// target:需要被替换、改写的内容。
this.target = target;
// newContent:需要新写入的内容。
this.newContent = newContent;
operation();
}
public static void main(String[] args) {
//代码测试假设有一个test文件夹test文件夹下含有若干文件或者若干子目录子目录下可能也含有若干文件或者若干子目录意味着可以递归操作
//把test目录下以及所有子目录下如果有中文件含有"hi"的字符串行替换成新的"hello,world!"字符串行。
new Modify("/Users/ehlxr/WorkSpaces/budd/src/main/java/me/ehlxr/test.txt", "hi", "hello,world!");
}
private void operation() {
File file = new File(path);
opeationDirectory(file);
}
private void opeationDirectory(File file) {
if (file.isFile()) {
operationFile(file);
}
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
opeationDirectory(f);
}
}
}
}
private void operationFile(File file) {
try {
InputStream is = new FileInputStream(file);
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
String filename = file.getName();
// tmpfile为缓存文件代码运行完毕后此文件将重命名为源文件名字。
File tmpfile = new File(file.getParentFile().getAbsolutePath() + "\\" + filename + ".tmp");
BufferedWriter writer = new BufferedWriter(new FileWriter(tmpfile));
boolean flag = false;
String str;
while (true) {
str = reader.readLine();
if (str == null)
break;
if (str.contains(target)) {
writer.write(newContent + "\n");
flag = true;
} else
writer.write(str + "\n");
}
is.close();
writer.flush();
writer.close();
if (flag) {
file.delete();
tmpfile.renameTo(new File(file.getAbsolutePath()));
} else {
tmpfile.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,97 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
/**
* Created by ehlxr on 2018/2/13.
*/
public class PrintMatrixClockWisely {
/**
* 题目:输入一个矩阵,按照从外向里以顺时针的顺序打印出每一个数字。
* 思路:
* 循环打印:
* 1先打印一行第 1 行肯定会打印)
* 2再打印当前矩阵的最后一列
* 3再倒序打印当前矩阵的最后一行
* 4再倒序打印当前矩阵的第一列
* 起始坐标的规律:
* (0,0),(1,1),(2,2)...(startX,startY), 起始坐标的两个坐标值相等。
* 并且 startX<= (rows-1)/2,startY<=(columns-1)/2
* 当前矩阵,第 1 行 坐标 (start,columns-1-start) => (start,endX)
* 当前矩阵,最后 1 列 坐标 (start+1,rows-1-start) => (start+1,endY)
* 当前矩阵,最后 1 行 坐标 (start,columns-1-start+1) => (start,endX-1)
* 当前矩阵,第 1 行 坐标 (start+1,columns-1+1) => (start+1,endY-1)
*
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// 初始化矩阵 arr[][]
int[][] arr = new int[5][5];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = i * arr[i].length + j;
System.out.print(arr[i][j] + " " + '\t');
}
System.out.println();
}
System.out.println("顺时针打印矩阵:");
// 顺时针打印矩阵 arr[][]
printMatrixWisely(arr);
}
// 循环打印
private static void printMatrixWisely(int[][] arr) {
if (arr == null || arr.length < 1 || arr[0].length < 1)
return;
int start = 0;
int rows = arr.length;
int columns = arr[0].length;
while (2 * start < columns && 2 * start < rows) {
printMatrix(arr, rows, columns, start);
start++;
}
}
// 打印一圈
private static void printMatrix(int[][] arr, int rows, int columns, int start) {
int endX = columns - 1 - start; // 最后一列的列号
int endY = rows - 1 - start; // 最后一行的行号
// 打印该圈第一行
for (int i = start; i <= endX; i++)
System.out.print(arr[start][i] + " ");
// 打印该圈最后一列 (至少是两行)
if (start < endY)
for (int i = start + 1; i <= endY; i++)
System.out.print(arr[i][endX] + " ");
// 打印该圈最后一行 (至少是两行两列)
if ((start < endX) && (start < endY))
for (int i = endX - 1; i >= start; i--)
System.out.print(arr[endY][i] + " ");
// 打印该圈的第一列 (至少是三行两列)
if ((start < endX) && (start < endY - 1))
for (int i = endY - 1; i >= start + 1; i--)
System.out.print(arr[i][start] + " ");
}
}

View File

@@ -1,71 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import java.io.*;
/**
* @author ehlxr
* @date 2017/3/27
*/
public class Rename {
public static void main(String[] args) {
File dir = new File("/Users/ehlxr/ehlxr/blog/posts");
File[] files = dir.listFiles();
if (null == files || files.length <= 0) {
System.out.println("sources is null!");
return;
}
int count = 0;
for (File file : files) {
try {
String oName = file.getName();
String date = oName.substring(oName.lastIndexOf("-201") + 1, oName.indexOf(".md"));
String title = oName.substring(0, oName.lastIndexOf("-201"));
String nName = date + "-" + title + ".md";
copyFileUsingFileStreams(file, new File("/Users/ehlxr/Desktop/post/" + nName));
count++;
} catch (Exception e) {
System.out.println("exce file [ " + file.getName() + " ] error, reason: " + e.getMessage());
}
}
System.out.println("complete: " + count);
}
private static void copyFileUsingFileStreams(File source, File dest)
throws IOException {
try (InputStream input = new FileInputStream(source); OutputStream output = new FileOutputStream(dest)) {
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buf)) > 0) {
output.write(buf, 0, bytesRead);
}
}
}
}

View File

@@ -1,78 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.activemq;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* 消息的消费者(接受者)
* Created by ehlxr on 2016-07-11
*/
public class JMSConsumer {
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;//默认连接用户名
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;//默认连接密码
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;//默认连接地址
public static void main(String[] args) {
ConnectionFactory connectionFactory;//连接工厂
Connection connection = null;//连接
Session session;//会话 接受或者发送消息的线程
Destination destination;//消息的目的地
MessageConsumer messageConsumer;//消息的消费者
//实例化连接工厂
connectionFactory = new ActiveMQConnectionFactory(JMSConsumer.USERNAME, JMSConsumer.PASSWORD, JMSConsumer.BROKEURL);
try {
//通过连接工厂获取连接
connection = connectionFactory.createConnection();
//启动连接
connection.start();
//创建session
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个连接HelloWorld的消息队列
destination = session.createQueue("HelloWorld");
//创建消息消费者
messageConsumer = session.createConsumer(destination);
while (true) {
TextMessage textMessage = (TextMessage) messageConsumer.receive(100000);
if (textMessage != null) {
System.out.println("收到的消息:" + textMessage.getText());
} else {
break;
}
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}

View File

@@ -1,108 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.activemq;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* 消息的生产者(发送者)
* Created by ehlxr on 2016-07-11.
*/
public class JMSProducer {
//默认连接用户名
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
//默认连接密码
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
//默认连接地址
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;
//发送的消息数量
private static final int SENDNUM = 10;
public static void main(String[] args) {
//连接工厂
ConnectionFactory connectionFactory;
//连接
Connection connection = null;
//会话 接受或者发送消息的线程
Session session;
//消息的目的地
Destination destination;
//消息生产者
MessageProducer messageProducer;
//实例化连接工厂
connectionFactory = new ActiveMQConnectionFactory(JMSProducer.USERNAME, JMSProducer.PASSWORD, JMSProducer.BROKEURL);
try {
//通过连接工厂获取连接
connection = connectionFactory.createConnection();
//启动连接
connection.start();
//创建session
session = connection.createSession(true, javax.jms.Session.AUTO_ACKNOWLEDGE);
//创建一个名称为HelloWorld的消息队列
destination = session.createQueue("HelloWorld");
//创建消息生产者
messageProducer = session.createProducer(destination);
//发送消息
sendMessage(session, messageProducer);
session.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
/**
* 发送消息
*
* @param session
* @param messageProducer 消息生产者
* @throws Exception
*/
public static void sendMessage(Session session, MessageProducer messageProducer) throws Exception {
for (int i = 0; i < JMSProducer.SENDNUM; i++) {
//创建一条文本消息
TextMessage message = session.createTextMessage("ActiveMQ 发送消息" + i);
System.out.println("发送消息Activemq 发送消息" + i);
//通过消息生产者发出消息
messageProducer.send(message);
}
}
}

View File

@@ -1,42 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.annotation;
import java.lang.annotation.Annotation;
public class TestPkgAnnotation {
public static void main(String[] args) {
Package pkg = Package.getPackage("osc.git.eh3.annotation");
Annotation[] annotations = pkg.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// ===========================友好类和包内访问常量==============
new MyPackageMethod().myPackageMethod();
System.out.println(MyPackageConst.PACKAGE_STRING);
}
}

View File

@@ -1,75 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.cache;
public class Cache {
private String key;// 缓存ID
private Object value;// 缓存数据
private long timeOut;// 更新时间
private boolean expired; // 是否终止
public Cache() {
super();
}
public Cache(String key, Object value, long timeOut, boolean expired) {
this.key = key;
this.value = value;
this.timeOut = timeOut;
this.expired = expired;
}
public String getKey() {
return key;
}
public long getTimeOut() {
return timeOut;
}
public Object getValue() {
return value;
}
public void setKey(String string) {
key = string;
}
public void setTimeOut(long l) {
timeOut = l;
}
public void setValue(Object object) {
value = object;
}
public boolean isExpired() {
return expired;
}
public void setExpired(boolean b) {
expired = b;
}
}

View File

@@ -1,187 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.cache;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class CacheManager {
private static final HashMap<String, Object> cacheMap = new HashMap<String, Object>();
// 单实例构造方法
private CacheManager() {
super();
}
// 得到缓存。同步静态方法
private synchronized static Cache getCache(String key) {
return (Cache) cacheMap.get(key);
}
// 判断是否存在一个缓存
private synchronized static boolean hasCache(String key) {
return cacheMap.containsKey(key);
}
// 清除所有缓存
public synchronized static void clearAll() {
cacheMap.clear();
}
// 清除某一类特定缓存,通过遍历HASHMAP下的所有对象来判断它的KEY与传入的TYPE是否匹配
public synchronized static void clearAll(String type) {
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
String key;
ArrayList<String> arr = new ArrayList<String>();
try {
while (i.hasNext()) {
Entry<String, Object> entry = i.next();
key = entry.getKey();
if (key.startsWith(type)) { // 如果匹配则删除掉
arr.add(key);
}
}
for (int k = 0; k < arr.size(); k++) {
clearOnly(arr.get(k));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 清除指定的缓存
public synchronized static void clearOnly(String key) {
cacheMap.remove(key);
}
// 载入缓存
public synchronized static void putCache(String key, Cache obj) {
cacheMap.put(key, obj);
}
// 获取缓存信息
public static Cache getCacheInfo(String key) {
if (hasCache(key)) {
Cache cache = getCache(key);
if (cacheExpired(cache)) { // 调用判断是否终止方法
cache.setExpired(true);
}
return cache;
} else {
return null;
}
}
// 载入缓存信息
public static void putCacheInfo(String key, Cache obj, long dt, boolean expired) {
Cache cache = new Cache();
cache.setKey(key);
cache.setTimeOut(dt + System.currentTimeMillis()); // 设置多久后更新缓存
cache.setValue(obj);
cache.setExpired(expired); // 缓存默认载入时终止状态为FALSE
cacheMap.put(key, cache);
}
// 重写载入缓存信息方法
public static void putCacheInfo(String key, Cache obj, long dt) {
Cache cache = new Cache();
cache.setKey(key);
cache.setTimeOut(dt + System.currentTimeMillis());
cache.setValue(obj);
cache.setExpired(false);
cacheMap.put(key, cache);
}
// 判断缓存是否终止
public static boolean cacheExpired(Cache cache) {
if (null == cache) { // 传入的缓存不存在
return false;
}
long nowDt = System.currentTimeMillis(); // 系统当前的毫秒数
long cacheDt = cache.getTimeOut(); // 缓存内的过期毫秒数
// 过期时间小于等于零时,或者过期时间大于当前时间时则为FALSE
// 大于过期时间 即过期
return cacheDt > 0 && cacheDt <= nowDt;
}
// 获取缓存中的大小
public static int getCacheSize() {
return cacheMap.size();
}
// 获取指定的类型的大小
public static int getCacheSize(String type) {
int k = 0;
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
String key;
try {
while (i.hasNext()) {
Entry<String, Object> entry = i.next();
key = entry.getKey();
if (key.indexOf(type) != -1) { // 如果匹配则删除掉
k++;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return k;
}
// 获取缓存对象中的所有键值名称
public static ArrayList<String> getCacheAllkey() {
ArrayList<String> a = new ArrayList<String>();
try {
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
while (i.hasNext()) {
Entry<String, Object> entry = i.next();
a.add(entry.getKey());
}
} catch (Exception ex) {
}
return a;
}
// 获取缓存对象中指定类型 的键值名称
public static ArrayList<String> getCacheListkey(String type) {
ArrayList<String> a = new ArrayList<String>();
String key;
try {
Iterator<Entry<String, Object>> i = cacheMap.entrySet().iterator();
while (i.hasNext()) {
Entry<String, Object> entry = i.next();
key = entry.getKey();
if (key.indexOf(type) != -1) {
a.add(key);
}
}
} catch (Exception ex) {
}
return a;
}
}

View File

@@ -1,74 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.cache;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public final class SimpleCache<K, V> {
private final Lock lock = new ReentrantLock();
private final int maxCapacity;
private final Map<K, V> eden;
private final Map<K, V> perm;
public SimpleCache(int maxCapacity) {
this.maxCapacity = maxCapacity;
this.eden = new ConcurrentHashMap<K, V>(maxCapacity);
this.perm = new WeakHashMap<K, V>(maxCapacity);
}
public V get(K k) {
V v = this.eden.get(k);
if (v == null) {
lock.lock();
try {
v = this.perm.get(k);
} finally {
lock.unlock();
}
if (v != null) {
this.eden.put(k, v);
}
}
return v;
}
public void put(K k, V v) {
if (this.eden.size() >= maxCapacity) {
lock.lock();
try {
this.perm.putAll(this.eden);
} finally {
lock.unlock();
}
this.eden.clear();
}
this.eden.put(k, v);
}
}

View File

@@ -1,102 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.cache;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class SimpleCacheUtil<T> {
private final Map<String, T> m_objects;
private final Map<String, Long> m_expiredObjects;
private final long m_lExpireTime;
private final ExecutorService m_executor;
public SimpleCacheUtil() {
this(500);
}
public SimpleCacheUtil(final int nExpireTime) {
m_objects = Collections.synchronizedMap(new HashMap<String, T>());
m_expiredObjects = Collections.synchronizedMap(new HashMap<String, Long>());
m_lExpireTime = nExpireTime;
m_executor = Executors.newFixedThreadPool(256);
Executors.newScheduledThreadPool(5).scheduleWithFixedDelay(RemoveExpiredObjects(), m_lExpireTime / 2, m_lExpireTime,
TimeUnit.SECONDS);
}
private final Runnable RemoveExpiredObjects() {
return new Runnable() {
public void run() {
for (final String name : m_expiredObjects.keySet()) {
if (System.currentTimeMillis() > m_expiredObjects.get(name)) {
m_executor.execute(CreateRemoveRunnable(name));
}
}
}
};
}
private final Runnable CreateRemoveRunnable(final String name) {
return new Runnable() {
public void run() {
m_objects.remove(name);
m_expiredObjects.remove(name);
}
};
}
public long getExpireTime() {
return m_lExpireTime;
}
public void put(final String name, final T obj) {
put(name, obj, m_lExpireTime);
}
public void put(final String name, final T obj, final long expireTime) {
m_objects.put(name, obj);
m_expiredObjects.put(name, System.currentTimeMillis() + expireTime * 1000);
}
public T get(final String name) {
final Long expireTime = m_expiredObjects.get(name);
if (expireTime == null)
return null;
if (System.currentTimeMillis() > expireTime) {
m_executor.execute(CreateRemoveRunnable(name));
return null;
}
return m_objects.get(name);
}
@SuppressWarnings("unchecked")
public <R extends T> R get(final String name, final Class<R> type) {
return (R) get(name);
}
}

View File

@@ -1,35 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.cache;
public class Test {
public static void main(String[] args) {
SimpleCacheUtil<Object> cache2 = new SimpleCacheUtil<>(5);
cache2.put("123", "fdfd");
System.out.println(cache2.get("123"));
}
}

View File

@@ -1,55 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.cache;
import java.util.ArrayList;
public class TestCache {
public static void main(String[] args) {
CacheManager.putCache("abc", new Cache("key", "value", 10, false));
CacheManager.putCache("def", new Cache());
CacheManager.putCache("ccc", new Cache());
CacheManager.clearOnly("");
Cache c = new Cache();
for (int i = 0; i < 10; i++) {
CacheManager.putCache("" + i, c);
}
CacheManager.putCache("aaaaaaaa", c);
CacheManager.putCache("abchcy;alskd", c);
CacheManager.putCache("cccccccc", c);
CacheManager.putCache("abcoqiwhcy", c);
System.out.println("删除前的大小:" + CacheManager.getCacheSize());
ArrayList<String> cacheAllkey = CacheManager.getCacheAllkey();
for (String key : cacheAllkey) {
System.out.println(key + ":" + CacheManager.getCacheInfo(key).getValue());
}
CacheManager.clearAll("aaaa");
System.out.println("删除后的大小:" + CacheManager.getCacheSize());
cacheAllkey = CacheManager.getCacheAllkey();
for (String key : cacheAllkey) {
System.out.println(key);
}
}
}

View File

@@ -1,120 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.cache;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
* Created by ehlxr on 2017/4/11.
*/
public class TestFutureCahe<K, V> {
private final ConcurrentHashMap<K, Future<V>> cacheMap = new ConcurrentHashMap<>();
public static void main(String[] args) {
final TestFutureCahe<String, String> TestGuaVA = new TestFutureCahe<String, String>();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("T1======start========");
Object value = TestGuaVA.getCache("key", "T1");
System.out.println("T1 value==============" + value);
System.out.println("T1======end========");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("T2======start========");
Object value = TestGuaVA.getCache("key", "T2");
System.out.println("T2 value==============" + value);
System.out.println("T2======end========");
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("T3======start========");
Object value = TestGuaVA.getCache("key", "T3");
System.out.println("T3 value==============" + value);
System.out.println("T3======end========");
}
});
t1.start();
t2.start();
t3.start();
}
public Object getCache(K keyValue, String ThreadName) {
Future<V> value = null;
try {
System.out.println("ThreadName getCache==============" + ThreadName);
//从缓存获取数据
value = cacheMap.get(keyValue);
//如果没有的话,把数据放到缓存
if (value == null) {
value = putCache(keyValue, ThreadName);
return value.get();
}
return value.get();
} catch (Exception e) {
}
return null;
}
public Future<V> putCache(K keyValue, final String ThreadName) {
// //把数据放到缓存
Future<V> value = null;
Callable<V> callable = new Callable<V>() {
@SuppressWarnings("unchecked")
@Override
public V call() throws Exception {
//可以根据业务从数据库获取等取得数据,这边就模拟已经获取数据了
System.out.println("ThreadName 执行业务数据并返回处理结果的数据(访问数据库等)==============" + ThreadName);
return (V) "dataValue";
}
};
FutureTask<V> futureTask = new FutureTask<V>(callable);
value = cacheMap.putIfAbsent(keyValue, futureTask);
if (value == null) {
value = futureTask;
futureTask.run();
}
return value;
}
}

View File

@@ -1,93 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr.date;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
* @author ehlxr
* @since 2021-01-28 16:03.
*/
public class Main {
public static void main(String[] args) {
// 旧 API 转新 API
// Date -> Instant:
Instant ins1 = new Date().toInstant();
System.out.println(ins1);
ZonedDateTime zonedDateTime = ins1.atZone(ZoneId.systemDefault());
System.out.println(zonedDateTime);
LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
System.out.println(localDateTime);
// Calendar -> Instant -> ZonedDateTime:
Calendar calendar = Calendar.getInstance();
Instant ins2 = calendar.toInstant();
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
System.out.println(zdt);
// 新 API 转旧 API
// ZonedDateTime -> long:
ZonedDateTime zdt1 = ZonedDateTime.now();
long ts = zdt1.toEpochSecond() * 1000;
// long -> Date:
Date date = new Date(ts);
// long -> Calendar:
Calendar calendar1 = Calendar.getInstance();
calendar1.clear();
calendar1.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
calendar1.setTimeInMillis(zdt.toEpochSecond() * 1000);
// 在数据库中存储时间戳时,尽量使用 long 型时间戳,它具有省空间,效率高,不依赖数据库的优点
ts = 1574208900000L;
System.out.println(timestampToString(ts, Locale.CHINA, "Asia/Shanghai"));
System.out.println(timestampToString(ts, Locale.US, "America/New_York"));
}
/**
* 不同用户以不同的偏好来显示不同的本地时间
*/
static String timestampToString(long epochMilli, Locale lo, String zoneId) {
Instant ins = Instant.ofEpochMilli(epochMilli);
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT)
// 按照 Locale 默认习惯格式化
.withLocale(lo);
return f.withLocale(lo).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
}
}

View File

@@ -1,88 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright © 2020 xrv <xrg@live.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.github.ehlxr;
import com.google.common.collect.Maps;
/**
* Created by ehlxr on 2016/12/23.
*/
public class dfd {
public static void main(String[] args) {
var map = Maps.newHashMap();
map.put("d", 1);
System.out.println(map);
}
public void printCircle(int[][] matrix, int startX, int startY, int endX, int endY) {
// only one column left
if (startY == endY) {
for (int i = startX; i <= endX; i++) {
System.out.println(matrix[i][endY]);
}
return;
}
// only one row left
if (startX == endX) {
for (int i = startY; i <= endY; i++) {
System.out.println(matrix[startX][i]);
}
return;
}
for (int i = startY; i < endY; i++) {
System.out.println(matrix[startX][i]);
}
for (int i = startX; i < endX; i++) {
System.out.println(matrix[i][endY]);
}
for (int i = endY; i > startY; i--) {
System.out.println(matrix[endX][i]);
}
for (int i = endX; i > startX; i--) {
System.out.println(matrix[i][startY]);
}
}
public void printMatrix(int[][] matrix) {
if (matrix == null) {
return;
}
int startX = 0;
int startY = 0;
int endY = matrix[0].length - 1;
int endX = matrix.length - 1;
while ((startX <= endX) && (startY <= endY)) {
printCircle(matrix, startX, startY, endX, endY);
startX++;
startY++;
endX--;
endY--;
}
}
}

Some files were not shown because too many files have changed in this diff Show More