list = List.of(1, 2, 3, 4, 5, 6, 7, 8);
+ int count = 0;
+ for (Integer _ : list) {
+ count++;
+ }
+ System.out.println(count);
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/Jep444VirtualThread.java b/core-java-modules/core-java-21/src/main/java/Jep444VirtualThread.java
new file mode 100644
index 0000000..52c565c
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/Jep444VirtualThread.java
@@ -0,0 +1,48 @@
+import java.time.Duration;
+import java.util.concurrent.Executors;
+import java.util.stream.IntStream;
+
+/**
+ * 虚拟线程
+ *
+ * @author https://www.wdbyte.com
+ * @date 2023/10/10
+ */
+public class Jep444VirtualThread {
+ public static void main(String[] args) throws InterruptedException {
+ // 创建并提交执行虚拟线程
+ long start = System.currentTimeMillis();
+ try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
+ IntStream.range(0, 10_000).forEach(i -> {
+ executor.submit(() -> {
+ Thread.sleep(Duration.ofSeconds(1));
+ return i;
+ });
+ });
+ }
+ System.out.println("time:" + (System.currentTimeMillis() - start) + "ms");
+
+
+ // 创建一个虚拟线程指定虚拟线程名称
+ Thread thread1 = Thread.ofVirtual().name("v-thread").unstarted(() -> {
+ String threadName = Thread.currentThread().getName();
+ System.out.println(String.format("[%s] Hello Virtual Thread", threadName));
+ });
+ thread1.start();
+ System.out.println(thread1.isVirtual());
+
+ //创建一个线程,启动为虚拟线程
+ Thread thread2 = new Thread(() -> {
+ String threadName = Thread.currentThread().getName();
+ System.out.println(String.format("[%s] Hello Virtual Thread 2", threadName));
+ });
+
+ Thread.startVirtualThread(thread2);
+
+ // 判断一个线程是否是虚拟线程
+ System.out.println(thread1.isVirtual());
+ System.out.println(thread2.isVirtual());
+
+ Thread.sleep(1000);
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/Jep445HelloJava.java b/core-java-modules/core-java-21/src/main/java/Jep445HelloJava.java
new file mode 100644
index 0000000..9f5ba6b
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/Jep445HelloJava.java
@@ -0,0 +1,5 @@
+
+void main(){
+ System.out.println("Hello, Java 21!");
+}
+
diff --git a/core-java-modules/core-java-22/pom.xml b/core-java-modules/core-java-22/pom.xml
new file mode 100644
index 0000000..4fc6401
--- /dev/null
+++ b/core-java-modules/core-java-22/pom.xml
@@ -0,0 +1,14 @@
+
+
+ 4.0.0
+ com.wdbyte.core-java-modules
+ core-java-22
+ 1.0.0-SNAPSHOT
+
+ 22
+ 22
+ UTF-8
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-22/src/main/java/com/wdbyte/Main.java b/core-java-modules/core-java-22/src/main/java/com/wdbyte/Main.java
new file mode 100644
index 0000000..cbe7f6f
--- /dev/null
+++ b/core-java-modules/core-java-22/src/main/java/com/wdbyte/Main.java
@@ -0,0 +1,21 @@
+package com.wdbyte;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2025/04/28
+ */
+//TIP To Run code, press or
+// click the icon in the gutter.
+public class Main {
+ public static void main(String[] args) {
+ //TIP Press with your caret at the highlighted text
+ // to see how IntelliJ IDEA suggests fixing it.
+ System.out.printf("Hello and welcome!");
+
+ for (int i = 1; i <= 5; i++) {
+ //TIP Press to start debugging your code. We have set one breakpoint
+ // for you, but you can always add more by pressing .
+ System.out.println("i = " + i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8/pom.xml b/core-java-modules/core-java-8/pom.xml
index 2ae8b99..132cc2e 100644
--- a/core-java-modules/core-java-8/pom.xml
+++ b/core-java-modules/core-java-8/pom.xml
@@ -35,11 +35,6 @@
org.junit.jupiter
junit-jupiter
-
- org.projectlombok
- lombok
- 1.18.22
-
\ No newline at end of file
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Base64.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Base64.java
index f3034f9..c50f47c 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Base64.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Base64.java
@@ -7,7 +7,7 @@
*
* JDK8 对 base64 编码的支持
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/6/12 9:47
*/
public class Jdk8Base64 {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Function.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Function.java
index 78d045b..9d14a98 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Function.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Function.java
@@ -14,7 +14,7 @@
* - Consumer: 数据消费器, 接收一个 T类型的对象,无返回值,通常用于设置T对象的值; 单参数无返回值的行为接口;提供了 accept, andThen 方法
* - Predicate: 条件测试器,接收一个 T 类型的对象,返回布尔值,通常用于传递条件函数; 单参数布尔值的条件性接口。提供了 test (条件测试) , and-or- negate(与或非) 方法。
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/2/18 22:08
*/
public class Jdk8Function {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Interface.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Interface.java
index 4037c71..790262a 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Interface.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Interface.java
@@ -5,7 +5,7 @@
* 接口的静态方法和默认方法
*
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/2/18 22:52
*/
public class Jdk8Interface {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Lambda.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Lambda.java
index b2663cb..cbd5029 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Lambda.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Lambda.java
@@ -1,9 +1,5 @@
package com.wdbyte;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.ToString;
import org.junit.jupiter.api.Test;
import java.util.*;
@@ -23,7 +19,7 @@
* 4. 花括号可选,一个语句可以不用花括号,多个参数则花括号必须。
* 5. 返回值可选,如果只有一个表达式,可以自动返回不需要 return 语句,花括号中需要 return 语法。
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/2/17 14:48
*/
public class Jdk8Lambda {
@@ -70,13 +66,33 @@ public void functionLambdaTest() {
}
- @Getter
- @Setter
- @ToString
- @AllArgsConstructor
static class User {
private String name;
private Integer age;
+
+ public User() {
+ }
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
}
public static List userList = new ArrayList();
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8LocalDateTime.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8LocalDateTime.java
index 360e967..9af6004 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8LocalDateTime.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8LocalDateTime.java
@@ -19,7 +19,7 @@
* - 实现了大部分常用操作方法
*
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/2/19 17:48
*/
public class Jdk8LocalDateTime {
@@ -161,15 +161,29 @@ public void calcTest() {
public void timeFunctionTest() {
LocalDateTime now = LocalDateTime.now();
System.out.println("当前时间:" + now);
- // 第一天
+
+ // LocalDateTime 本月第一天
+ // 方法1
LocalDateTime firstDay = now.withDayOfMonth(1);
System.out.println("本月第一天:" + firstDay);
- // 当天最后一秒
- LocalDateTime lastSecondOfDay = now.withHour(23).withMinute(59).withSecond(59);
- System.out.println("当天最后一秒:" + lastSecondOfDay);
- // 最后一天
+ // 方法2
+ firstDay = now.with(TemporalAdjusters.firstDayOfMonth());
+ System.out.println("本月第一天:" + firstDay);
+
+ // LocalDateTime 本月最后一天
LocalDateTime lastDay = now.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("本月最后一天:" + lastDay);
+
+
+ // LocalDateTime 当天最后一秒
+ // 方法1
+ LocalDateTime lastSecondOfDay1 = now.withHour(23).withMinute(59).withSecond(59);
+ System.out.println("当天最后一秒:" + lastSecondOfDay1);
+ // 方法2
+ LocalDateTime lastSecondOfDay2 = LocalDateTime.now().with(LocalTime.MAX);
+ System.out.println("当天最后一秒:" + lastSecondOfDay2);
+
+
// 是否闰年
System.out.println("今年是否闰年:" + Year.isLeap(now.getYear()));
}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8NashornJs.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8NashornJs.java
index 6a1a2e7..ac34fd1 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8NashornJs.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8NashornJs.java
@@ -15,7 +15,7 @@
*
* 这类Script引擎遵循相同的规则,允许Java和JavaScript交互使用,例子代码如下:
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/6/12 9:41
*/
public class Jdk8NashornJs {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Optional.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Optional.java
index 4288b27..fc080a8 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Optional.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Optional.java
@@ -2,15 +2,13 @@
import java.util.Optional;
-
-import lombok.Data;
import org.junit.jupiter.api.Test;
/**
*
* JDK8 为解决空指针增加的 Optional 方法
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/2/19 11:40
*/
public class Jdk8Optional {
@@ -182,23 +180,44 @@ public void optionalTest() {
/**
* 计算机
*/
-@Data
class Computer {
private Optional soundCard;
+
+ public Optional getSoundCard() {
+ return soundCard;
+ }
+
+ public void setSoundCard(Optional soundCard) {
+ this.soundCard = soundCard;
+ }
}
/**
* 声卡
*/
-@Data
class SoundCard {
private Optional usb;
+
+ public Optional getUsb() {
+ return usb;
+ }
+
+ public void setUsb(Optional usb) {
+ this.usb = usb;
+ }
}
/**
* USB
*/
-@Data
class Usb {
private String version;
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Stream.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Stream.java
index aa1a6b5..d78cdb2 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Stream.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Stream.java
@@ -13,7 +13,7 @@
*
* JDK 8 steam 流操作
*
- * @Author niujinpeng
+* @Author https://www.wdbyte.com
* @Date 2019/8/12 18:03
*/
public class Jdk8Stream {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator.java
index 78f7109..b4c5773 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator.java
@@ -6,7 +6,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/02
*/
public class Java8Comparator {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator2.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator2.java
index bef75cc..b53e60e 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator2.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator2.java
@@ -6,7 +6,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/02
*/
public class Java8Comparator2 {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator3.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator3.java
index 70d3a24..4031315 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator3.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator3.java
@@ -5,7 +5,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/02
*/
public class Java8Comparator3 {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator4.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator4.java
index 250e30a..c02c30d 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator4.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator4.java
@@ -5,7 +5,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/02
*/
public class Java8Comparator4 {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator5.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator5.java
index d65054b..ca3ae94 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator5.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator5.java
@@ -6,7 +6,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/02
*/
public class Java8Comparator5 {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator6.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator6.java
index bec0fb7..20ab437 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator6.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator6.java
@@ -6,7 +6,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/02
*/
public class Java8Comparator6 {
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator7.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator7.java
index c7c9d25..2918e31 100644
--- a/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator7.java
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/comparator/Java8Comparator7.java
@@ -5,7 +5,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/02
*/
public class Java8Comparator7 {
diff --git a/core-java-modules/core-java-base/README.md b/core-java-modules/core-java-base/README.md
new file mode 100644
index 0000000..5b2d151
--- /dev/null
+++ b/core-java-modules/core-java-base/README.md
@@ -0,0 +1,26 @@
+## core-java-base
+当前模块包含 Java 核心代码
+
+### 相关文章
+
+- [JDK、JRE、JVM 的区别](/java/jdk-jre-jvm/)
+- [Java 数据类型](/java/data-type/)
+- [Java 流程控制](/java/flow-control/)
+- [Java String 字符串](/java/java-string/)
+- [Java Array 数组](/java/java-array/)
+- [Java 多维数组](/java/java-array-mul/)
+- [Java StringBuilder](/java/java-stringbuilder/)
+- [Java Scanner](/java/scanner/)
+- [Java 继承](/java/extends/)
+- [Java 接口](/java/interface/)
+- [Java 抽象类](/java/abstract/)
+- [抽象类和接口的区别](https://www.wdbyte.com/java/abs-interface/)
+- [Java 多态](/java/polymorphism/)
+- [Java Scanner](/java/scanner/)
+- [Java 日期时间Date](/java/date/)
+- [Java 异常处理](/java/exception/)
+- [Java 枚举](https://www.wdbyte.com/java/enum/)
+- [Java 注释](*https://www.wdbyte.com/java/comment/*)
+- [Java 集合框架](https://www.wdbyte.com/java/collection/)
+- [Java 中使用 List ](https://www.wdbyte.com/java/list/)
+- [Java 断言 Assert 使用教程与最佳实践](https://www.wdbyte.com/java/assert/)
\ No newline at end of file
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaDataType.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaDataType.java
index 24aa637..192314b 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaDataType.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaDataType.java
@@ -1,7 +1,7 @@
package com.wdbyte;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/23
*/
public class JavaDataType {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray.java
index daac4ec..521b1c2 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray.java
@@ -5,7 +5,7 @@
import java.util.List;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/23
*/
public class JavaArray {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray2.java
index b5a5b66..ba92287 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray2.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray2.java
@@ -1,7 +1,7 @@
package com.wdbyte.array;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/25
*/
public class JavaArray2 {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray3.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray3.java
index d48cd29..3816c54 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray3.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray3.java
@@ -1,7 +1,7 @@
package com.wdbyte.array;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/25
*/
public class JavaArray3 {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray4.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray4.java
index b1b998c..4665cc6 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray4.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/array/JavaArray4.java
@@ -2,7 +2,7 @@
/**
* 锯齿数组
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/25
*/
public class JavaArray4 {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo1.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo1.java
new file mode 100644
index 0000000..50490a5
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo1.java
@@ -0,0 +1,29 @@
+package com.wdbyte.assert1;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2024/04/22
+ */
+public class AssertDemo1 {
+ public static void main(String[] args) {
+
+ List list = Arrays.asList("1", "2");
+ boolean result = list.remove("x");
+ //assert result;
+ assert result : "移除失败";
+ System.out.println(calc(100, 10));
+
+ // 手动开启断言
+ //ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
+ //System.out.println(calc(100, 0));
+ }
+
+ public static int calc(int a, int b) {
+ assert b != 0 : "除数不能为0";
+ return a / b;
+
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo2.java
new file mode 100644
index 0000000..735c2bb
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo2.java
@@ -0,0 +1,24 @@
+package com.wdbyte.assert1;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.google.common.base.Verify.*;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2024/04/22
+ */
+public class AssertDemo2 {
+ public static void main(String[] args) {
+ int x = 100;
+ verifyNotNull(x != 0);
+ System.out.println(calc(100, 10));
+ System.out.println(calc(100, 0));
+ }
+
+ public static int calc(int a, int b) {
+ verify(b != 0, "除数不能为0");
+ return a / b;
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo3.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo3.java
new file mode 100644
index 0000000..09e2272
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo3.java
@@ -0,0 +1,20 @@
+package com.wdbyte.assert1;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2024/04/22
+ */
+public class AssertDemo3 {
+ static final boolean asserts = false; // 设置为 false 来消除断言
+
+ public static void main(String[] args) {
+ List list = Arrays.asList("1", "2");
+ boolean result = list.remove("x");
+ if (asserts) {
+ assert result : "移除失败";
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo4.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo4.java
new file mode 100644
index 0000000..565de43
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo4.java
@@ -0,0 +1,25 @@
+package com.wdbyte.assert1;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2024/04/22
+ */
+public class AssertDemo4 {
+
+ static {
+ boolean assertsEnabled = false;
+ assert assertsEnabled = true; // 故意产生副作用!!!
+ if (!assertsEnabled) {
+ throw new RuntimeException("必须启用断言!!!");
+ }
+ }
+
+ public static void main(String[] args) {
+ List list = Arrays.asList("1", "2");
+ boolean result = list.remove("x");
+ assert result : "移除失败";
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo5.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo5.java
new file mode 100644
index 0000000..4c37dde
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/AssertDemo5.java
@@ -0,0 +1,25 @@
+package com.wdbyte.assert1;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Verify;
+import org.apache.commons.lang3.Validate;
+import org.junit.jupiter.api.Assertions;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2024/04/22
+ */
+public class AssertDemo5 {
+
+ public static void main(String[] args) {
+ List list = Arrays.asList("1", "2");
+ boolean result = list.remove("x");
+ Assertions.assertTrue(result);
+ Preconditions.checkNotNull("","msg");
+ Validate.isTrue(list.isEmpty(),"msg");
+ Verify.verify(list.isEmpty(),"msg");
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/InitializationDemo.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/InitializationDemo.java
new file mode 100644
index 0000000..cfebe99
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/assert1/InitializationDemo.java
@@ -0,0 +1,28 @@
+package com.wdbyte.assert1;
+
+public class InitializationDemo {
+
+ static {
+ init();
+ }
+
+ static void init() {
+ System.out.println("Static initialization block called");
+ // 假设这里有一个重要的初始化逻辑
+ // 这个方法错误地在静态初始化之前被调用了
+ assert isProperlyInitialized() : "System not properly initialized";
+ }
+
+ static boolean isProperlyInitialized() {
+ // 这里返回 false 模拟系统未被正确初始化
+ return false;
+ }
+
+ public InitializationDemo() {
+ System.out.println("Constructor called");
+ }
+
+ public static void main(String[] args) {
+ new InitializationDemo();
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest.java
new file mode 100644
index 0000000..582a6f3
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest.java
@@ -0,0 +1,63 @@
+package com.wdbyte.collection;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/10/19
+ */
+public class ArrayListTest {
+
+ public static void main(String[] args) {
+ //String[] arr = new String[]{"w","d","b","y","t","e"};
+ ////arr[7] = "f";
+ //
+ //List list = new ArrayList();
+ //list.add("a");
+ //list.add("b");
+ //list.add("c");
+ //list.add("d");
+ //
+ //System.out.println(list.get(2));
+ //list.remove(2);
+ //System.out.println(list.get(2));
+
+ //List list2 = List.of("www", "wdbyte", "com");
+ //list2.add("a");
+ //System.out.println(list2);
+
+ List list = new ArrayList();
+ list.add("b");
+ list.add("c");
+ list.add("a");
+ list.add("d");
+
+ System.out.println(list);
+
+ list = list.stream().sorted().collect(Collectors.toList());
+ System.out.println(list);
+
+ // 排序时指定降序还是升序:Comparator.reverseOrder() 降序
+ list = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
+ System.out.println(list);
+
+ System.out.println("----------");
+
+ Collections.sort(list);
+ System.out.println(list);
+ // 降序
+ Collections.sort(list,Comparator.reverseOrder());
+ System.out.println(list);
+
+ list.sort(Comparator.comparing(Function.identity()));
+ System.out.println(list);
+
+
+
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest2.java
new file mode 100644
index 0000000..f18c9b1
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest2.java
@@ -0,0 +1,49 @@
+package com.wdbyte.collection;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/10/19
+ */
+public class ArrayListTest2 {
+
+ public static void main(String[] args) {
+ List list = new ArrayList();
+ list.add("a");
+ list.add("b");
+ System.out.println("当前集合:" + list);
+ System.out.println("获取第一个元素:" + list.get(0));
+ list.set(0, "x");
+ System.out.println("修改第一个元素为 x:" + list);
+ list.remove(1);
+ System.out.println("移除第2个元素后剩余:" + list);
+ System.out.println("判断元素 x 是否存在:" + list.contains("x"));
+ System.out.println("判断元素 a 是否存在:" + list.contains("a"));
+ System.out.println("当前 list 大小:" + list.size());
+
+ list.add("y");
+ list.add("z");
+ System.out.println("添加两个元素:" + list);
+
+ System.out.println("遍历元素:");
+ for (String string : list) {
+ System.out.print(string);
+ }
+ for (int i = 0; i < list.size(); i++) {
+ System.out.print(list.get(i));
+ }
+ list.forEach(s -> {
+ System.out.println(s);
+ });
+
+ Iterator iterator = list.iterator();
+ while (iterator.hasNext()){
+ System.out.println(iterator.next());
+ }
+
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest3.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest3.java
new file mode 100644
index 0000000..a88fd7a
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest3.java
@@ -0,0 +1,54 @@
+package com.wdbyte.collection;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.Lists;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/10/19
+ */
+public class ArrayListTest3 {
+
+ public static void main(String[] args) {
+ List list = new ArrayList();
+ list.add("a");
+ list.add("b");
+
+ String[] array = list.toArray(new String[0]);
+ System.out.println(Arrays.toString(array));
+
+ String[] array2 = list.stream().toArray(String[]::new);
+ System.out.println(Arrays.toString(array2));
+
+ // 数组 -> List
+ // 方式1
+ List list0 = Lists.newArrayList(array);
+ list0.add("e");
+ System.out.println(list0);
+
+ // 方式2
+ List list1 = Arrays.stream(array).toList();
+ // list1.add("e"); 报错,不能修改
+ System.out.println(list1);
+
+ // 方式3
+ List list2 = Arrays.asList(array);
+ //list2.add("e"); 报错,不能修改
+ System.out.println(list2);
+
+ // 方式4
+ List list3 = new ArrayList<>(Arrays.asList(array));
+ list3.add("e");
+ System.out.println(list3);
+
+ // 方式5
+ List list4 = Arrays.stream(array).collect(Collectors.toList());
+ list4.add("e");
+ System.out.println(list4);
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest4.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest4.java
new file mode 100644
index 0000000..93d09e4
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/ArrayListTest4.java
@@ -0,0 +1,83 @@
+package com.wdbyte.collection;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.Lists;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/10/19
+ */
+public class ArrayListTest4 {
+
+ public static void main(String[] args) {
+ List list = new ArrayList();
+ list.add(new Dog("大黄", 1));
+ list.add(new Dog("小黑", 2));
+
+ Map dogMap = list.stream()
+ .collect(Collectors.toMap(Dog::getName, Function.identity(), (o, n) -> o));
+ System.out.println(dogMap.get("大黄"));
+
+ Map dogMap2 = new HashMap<>();
+ for (Dog dog : list) {
+ dogMap2.put(dog.getName(), dog);
+ }
+ System.out.println(dogMap.get("大黄"));
+
+ List arrayList = new ArrayList();
+ arrayList.add("a");
+ arrayList.add("b");
+
+ Iterator iterator = arrayList.iterator();
+ while (iterator.hasNext()) {
+ String next = iterator.next();
+ if ("a".equals(next)) {
+ iterator.remove();
+ }
+ }
+ System.out.println(arrayList);
+ }
+
+}
+
+class Dog {
+ String name;
+ Integer age;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public Dog(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ @Override
+ public String toString() {
+ return "Dog{" +
+ "name='" + name + '\'' +
+ ", age=" + age +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest.java
new file mode 100644
index 0000000..fc953ed
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest.java
@@ -0,0 +1,20 @@
+package com.wdbyte.collection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class CollectionTest {
+ public static void main(String[] args) {
+ List arrayList = new ArrayList<>();
+ // 向 List 中添加元素
+ arrayList.add("www");
+ arrayList.add("wdbyte");
+ arrayList.add("com");
+ arrayList.add("com");
+ // 输出
+ System.out.println(arrayList);
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest2.java
new file mode 100644
index 0000000..3c67874
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest2.java
@@ -0,0 +1,35 @@
+package com.wdbyte.collection;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeSet;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class CollectionTest2 {
+ public static void main(String[] args) {
+ List arrayList = new ArrayList<>();
+ List linkedList = new LinkedList<>();
+ Set hashSet = new HashSet<>();
+ Set treeSet = new TreeSet<>();
+ Stack stack = new Stack<>();
+ // 添加元素
+ arrayList.add("wdbyte.com");
+ linkedList.add("wdbyte.com");
+ hashSet.add("wdbyte.com");
+ treeSet.add("wdbyte.com");
+ stack.add("wdbyte.com");
+ // 输出
+ System.out.println(arrayList);
+ System.out.println(linkedList);
+ System.out.println(hashSet);
+ System.out.println(treeSet);
+ System.out.println(stack);
+ }
+
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest3.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest3.java
new file mode 100644
index 0000000..2989ef5
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest3.java
@@ -0,0 +1,35 @@
+package com.wdbyte.collection;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class CollectionTest3 {
+ public static void main(String[] args) {
+ List arrayList = new ArrayList<>();
+ // 向 List 中添加元素
+ arrayList.add("www");
+ arrayList.add("wdbyte");
+ arrayList.add("com");
+ // 普通遍历
+ for (int i = 0; i < arrayList.size(); i++) {
+ System.out.println(arrayList.get(0));
+ }
+ System.out.println("--------");
+ // iterator 迭代器遍历
+ Iterator iterator = arrayList.iterator();
+ while (iterator.hasNext()) {
+ System.out.println(iterator.next());
+ }
+ }
+
+ public void printCollection(Collection collection) {
+ for (Object o : collection) {
+ System.out.println(o);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest4.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest4.java
new file mode 100644
index 0000000..349619b
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest4.java
@@ -0,0 +1,37 @@
+package com.wdbyte.collection;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class CollectionTest4 {
+ public static void main(String[] args) {
+ List arrayList = new ArrayList<>();
+ // 向 List 中添加元素
+ arrayList.add("www");
+ arrayList.add("wdbyte");
+ arrayList.add("com");
+
+ HashSet hashSet = new HashSet<>();
+ hashSet.addAll(arrayList);
+
+ printCollection(arrayList.iterator());
+ System.out.println("--------------");
+ printCollection(hashSet.iterator());
+ }
+
+ public static void printCollection(Iterator iterator) {
+ // 当前日期
+ LocalDate now = LocalDate.now();
+ while (iterator.hasNext()) {
+ String obj = iterator.next();
+ System.out.println(now + ":" + obj.toString());
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest5.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest5.java
new file mode 100644
index 0000000..6d480e8
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/CollectionTest5.java
@@ -0,0 +1,34 @@
+package com.wdbyte.collection;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class CollectionTest5 {
+ public static void main(String[] args) {
+ List arrayList = new ArrayList<>();
+ // 向 List 中添加元素
+ arrayList.add("www");
+ arrayList.add("wdbyte");
+ arrayList.add("com");
+ HashSet hashSet = new HashSet<>();
+ hashSet.addAll(arrayList);
+
+ printCollection(arrayList);
+ printCollection(hashSet);
+ }
+ public static void printCollection(Iterable iterable) {
+ // 当前日期
+ LocalDate now = LocalDate.now();
+ Iterator iterator = iterable.iterator();
+ while (iterator.hasNext()) {
+ String obj = iterator.next();
+ System.out.println(now + ":" + obj.toString());
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/MapTest.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/MapTest.java
new file mode 100644
index 0000000..cd346f9
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/MapTest.java
@@ -0,0 +1,21 @@
+package com.wdbyte.collection;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class MapTest {
+ public static void main(String[] args) {
+ Map hashMap = new HashMap<>();
+ // 添加元素
+ hashMap.put("site","www.wdbyte.com");
+ hashMap.put("author","程序猿阿朗");
+ hashMap.put("github","github.com/niumoo");
+ // 获取元素
+ System.out.println(hashMap.get("github"));
+ // 输出全部元素
+ System.out.println(hashMap);
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/MapTest2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/MapTest2.java
new file mode 100644
index 0000000..235c79a
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/collection/MapTest2.java
@@ -0,0 +1,26 @@
+package com.wdbyte.collection;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class MapTest2 {
+ public static void main(String[] args) {
+ Map hashMap = new HashMap<>();
+ Map linkedHashMap = new LinkedHashMap<>();
+ // 添加元素
+ hashMap.put("site", "www.wdbyte.com");
+ hashMap.put("author", "程序猿阿朗");
+ hashMap.put("github", "github.com/niumoo");
+ linkedHashMap.put("site", "www.wdbyte.com");
+ linkedHashMap.put("author", "程序猿阿朗");
+ linkedHashMap.put("github", "github.com/niumoo");
+
+ // 输出全部元素
+ System.out.println(hashMap);
+ System.out.println(linkedHashMap);
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/JavaDocDemo.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/JavaDocDemo.java
new file mode 100644
index 0000000..0625952
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/JavaDocDemo.java
@@ -0,0 +1,41 @@
+package com.wdbyte.comment;
+
+/**
+ * 输出一个名称和地域的问候信息。
+ * 如:Hello 朋友,welcome to 杭州
+ * 主要实现方法是 {@link JavaDocDemo#getMessage(String, String)}
+ *
+ * @author wdbyte
+ * @version 1.0
+ * @see com.wdbyte.comment.JavaDocDemo#getMessage(String, String)
+ * @since 1.0
+ */
+public class JavaDocDemo {
+
+ /**
+ * 启动应用程序
+ *
+ * @param args - 应用启动参数
+ */
+ public static void main(String[] args) {
+ System.out.println(getMessage("朋友", "杭州"));
+ }
+
+ /**
+ * 返回一个欢迎信息。
+ * @see Java Dcoumentation
+ * @param name - 访问者名称
+ * @param region - 地域信息
+ * @return - 欢迎信息语句
+ */
+ public static String getMessage(String name, String region) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Hello ");
+ builder.append(name);
+ builder.append(", Welcome to ");
+ builder.append(region);
+ builder.append(" !!");
+ return builder.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/WelcomeMain.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/WelcomeMain.java
new file mode 100644
index 0000000..153bed9
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/WelcomeMain.java
@@ -0,0 +1,51 @@
+package com.wdbyte.comment;
+
+/**
+ * 输出一个名称和地域的问候信息。
+ * 如:Hello 朋友,welcome to 杭州
+ *
+ * @author https://www.wdbyte.com
+ */
+public class WelcomeMain {
+
+ /**
+ * 启动应用程序
+ *
+ * @param args - 应用启动参数
+ */
+ public static void main(String[] args) {
+ System.out.println(getMessage("朋友", "杭州"));
+ }
+
+ /**
+ * 返回一个欢迎信息。
+ *
+ * @param name - 访问者名称
+ * @param region - 地域信息
+ * @return - 欢迎信息
+ */
+ public static String getMessage(String name, String region) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Hello ");
+ builder.append(name);
+ builder.append(", Welcome to ");
+ builder.append(region);
+ builder.append(" !!");
+ return builder.toString();
+ }
+
+
+ /**
+ * 计算两数之和
+ * @param x 数字1
+ * @param y 数字2
+ * @return
+ */
+ public int add(int x, int y) {
+ /*
+ * 计算两数之和
+ */
+ int s = x + y;
+ return s;
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/allclasses-frame.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/allclasses-frame.html
new file mode 100644
index 0000000..d1e5c11
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/allclasses-frame.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+所有类
+
+
+
+
+
+所有类
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/allclasses-noframe.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/allclasses-noframe.html
new file mode 100644
index 0000000..4e6a6c4
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/allclasses-noframe.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+所有类
+
+
+
+
+
+所有类
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/JavaDocDemo.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/JavaDocDemo.html
new file mode 100644
index 0000000..12f6a1c
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/JavaDocDemo.html
@@ -0,0 +1,310 @@
+
+
+
+
+
+JavaDocDemo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+- 概要:
+- 嵌套 |
+- 字段 |
+- 构造器 |
+- 方法
+
+
+- 详细资料:
+- 字段 |
+- 构造器 |
+- 方法
+
+
+
+
+
+
+
+
+
+
+- java.lang.Object
+-
+
+- com.wdbyte.comment.JavaDocDemo
+
+
+
+
+
+
+-
+
+
+
+
+-
+
+
+
方法概要
+
+所有方法 静态方法 具体方法
+
+| 限定符和类型 |
+方法和说明 |
+
+
+static java.lang.String |
+getMessage(java.lang.String name,
+ java.lang.String region)
+返回一个欢迎信息。
+ |
+
+
+static void |
+main(java.lang.String[] args)
+启动应用程序
+ |
+
+
+
+-
+
+
+
从类继承的方法 java.lang.Object
+clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
+
+
+
+
+
+
+
+
+-
+
+
+-
+
+
+
构造器详细资料
+
+
+
+
+-
+
JavaDocDemo
+public JavaDocDemo()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+- 概要:
+- 嵌套 |
+- 字段 |
+- 构造器 |
+- 方法
+
+
+- 详细资料:
+- 字段 |
+- 构造器 |
+- 方法
+
+
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-frame.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-frame.html
new file mode 100644
index 0000000..cafb6ef
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-frame.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+com.wdbyte.comment
+
+
+
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-summary.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-summary.html
new file mode 100644
index 0000000..14848c8
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-summary.html
@@ -0,0 +1,140 @@
+
+
+
+
+
+com.wdbyte.comment
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-
+
+类概要
+
+| 类 |
+说明 |
+
+
+
+| JavaDocDemo |
+
+ 输出一个名称和地域的问候信息。
+ |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-tree.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-tree.html
new file mode 100644
index 0000000..dad782d
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/com/wdbyte/comment/package-tree.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+com.wdbyte.comment 类分层结构
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/constant-values.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/constant-values.html
new file mode 100644
index 0000000..be8d957
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/constant-values.html
@@ -0,0 +1,120 @@
+
+
+
+
+
+常量字段值
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/deprecated-list.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/deprecated-list.html
new file mode 100644
index 0000000..a03d078
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/deprecated-list.html
@@ -0,0 +1,120 @@
+
+
+
+
+
+已过时的列表
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/help-doc.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/help-doc.html
new file mode 100644
index 0000000..b96669f
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/help-doc.html
@@ -0,0 +1,217 @@
+
+
+
+
+
+API 帮助
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-
+
程序包
+每个程序包都有一个页面, 其中包含它的类和接口的列表及其概要。此页面可以包含六个类别:
+
+- 接口 (斜体)
+- 类
+- 枚举
+- 异常错误
+- 错误
+- 注释类型
+
+
+-
+
类/接口
+每个类, 接口, 嵌套类和嵌套接口都有各自的页面。其中每个页面都由三部分 (类/接口说明, 概要表, 以及详细的成员说明) 组成:
+
+- 类继承图
+- 直接子类
+- 所有已知子接口
+- 所有已知实现类
+- 类/接口声明
+- 类/接口说明
+
+
+- 嵌套类概要
+- 字段概要
+- 构造器概要
+- 方法概要
+
+
+- 字段详细资料
+- 构造器详细资料
+- 方法详细资料
+
+每个概要条目都包含该项目的详细说明的第一句。概要条目按字母顺序排列, 而详细说明则按其在源代码中出现的顺序排列。这样保持了程序员所建立的逻辑分组。
+
+-
+
注释类型
+每个注释类型都有各自的页面, 其中包含以下部分:
+
+- 注释类型声明
+- 注释类型说明
+- 必需元素概要
+- 可选元素概要
+- 元素详细资料
+
+
+-
+
枚举
+每个枚举都有各自的页面, 其中包含以下部分:
+
+- 枚举声明
+- 枚举说明
+- 枚举常量概要
+- 枚举常量详细资料
+
+
+-
+
树 (类分层结构)
+对于所有程序包, 有一个类分层结构页面, 以及每个程序包的分层结构。每个分层结构页面都包含类的列表和接口的列表。从java.lang.Object开始, 按继承结构对类进行排列。接口不从java.lang.Object继承。
+
+- 查看“概览”页面时, 单击 "树" 将显示所有程序包的分层结构。
+- 查看特定程序包, 类或接口页面时, 单击 "树" 将仅显示该程序包的分层结构。
+
+
+-
+
已过时的 API
+已过时的 API 页面列出了所有已过时的 API。一般由于进行了改进并且通常提供了替代的 API, 所以建议不要使用已过时的 API。在将来的实现过程中, 可能会删除已过时的 API。
+
+-
+
索引
+索引 包含按字母顺序排列的所有类, 接口, 构造器, 方法和字段的列表。
+
+-
+
上一个/下一个
+这些链接使您可以转至下一个或上一个类, 接口, 程序包或相关页面。
+
+-
+
框架/无框架
+这些链接用于显示和隐藏 HTML 框架。所有页面均具有有框架和无框架两种显示方式。
+
+-
+
所有类
+所有类链接显示所有类和接口 (除了非静态嵌套类型)。
+
+-
+
序列化表格
+每个可序列化或可外部化的类都有其序列化字段和方法的说明。此信息对重新实现者有用, 而对使用 API 的开发者则没有什么用处。尽管导航栏中没有链接, 但您可以通过下列方式获取此信息: 转至任何序列化类, 然后单击类说明的 "另请参阅" 部分中的 "序列化表格"。
+
+-
+
常量字段值
+常量字段值页面列出了静态最终字段及其值。
+
+
+
此帮助文件适用于使用标准 doclet 生成的 API 文档。
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/index-all.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/index-all.html
new file mode 100644
index 0000000..06a699f
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/index-all.html
@@ -0,0 +1,157 @@
+
+
+
+
+
+索引
+
+
+
+
+
+
+
+
+
+
+
+C G J M
+
+
+
C
+
+- com.wdbyte.comment - 程序包 com.wdbyte.comment
+-
+
+
+
+
+
G
+
+- getMessage(String, String) - 类 中的静态方法com.wdbyte.comment.JavaDocDemo
+-
+
返回一个欢迎信息。
+
+
+
+
+
+
J
+
+- JavaDocDemo - com.wdbyte.comment中的类
+-
+
输出一个名称和地域的问候信息。
+
+- JavaDocDemo() - 类 的构造器com.wdbyte.comment.JavaDocDemo
+-
+
+
+
+
+
M
+
+- main(String[]) - 类 中的静态方法com.wdbyte.comment.JavaDocDemo
+-
+
启动应用程序
+
+
+
C G J M
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/index.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/index.html
new file mode 100644
index 0000000..720515c
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/index.html
@@ -0,0 +1,72 @@
+
+
+
+
+
+生成的文档 (无标题)
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/overview-tree.html b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/overview-tree.html
new file mode 100644
index 0000000..50e2869
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/overview-tree.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+类分层结构
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/package-list b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/package-list
new file mode 100644
index 0000000..84f8f0f
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/package-list
@@ -0,0 +1 @@
+com.wdbyte.comment
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/script.js b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/script.js
new file mode 100644
index 0000000..b346356
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/script.js
@@ -0,0 +1,30 @@
+function show(type)
+{
+ count = 0;
+ for (var key in methods) {
+ var row = document.getElementById(key);
+ if ((methods[key] & type) != 0) {
+ row.style.display = '';
+ row.className = (count++ % 2) ? rowColor : altColor;
+ }
+ else
+ row.style.display = 'none';
+ }
+ updateTabs(type);
+}
+
+function updateTabs(type)
+{
+ for (var value in tabs) {
+ var sNode = document.getElementById(tabs[value][0]);
+ var spanNode = sNode.firstChild;
+ if (value == type) {
+ sNode.className = activeTableTab;
+ spanNode.innerHTML = tabs[value][1];
+ }
+ else {
+ sNode.className = tableTab;
+ spanNode.innerHTML = "" + tabs[value][1] + "";
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/stylesheet.css b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/stylesheet.css
new file mode 100644
index 0000000..98055b2
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/comment/doc/stylesheet.css
@@ -0,0 +1,574 @@
+/* Javadoc style sheet */
+/*
+Overall document style
+*/
+
+@import url('resources/fonts/dejavu.css');
+
+body {
+ background-color:#ffffff;
+ color:#353833;
+ font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
+ font-size:14px;
+ margin:0;
+}
+a:link, a:visited {
+ text-decoration:none;
+ color:#4A6782;
+}
+a:hover, a:focus {
+ text-decoration:none;
+ color:#bb7a2a;
+}
+a:active {
+ text-decoration:none;
+ color:#4A6782;
+}
+a[name] {
+ color:#353833;
+}
+a[name]:hover {
+ text-decoration:none;
+ color:#353833;
+}
+pre {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+}
+h1 {
+ font-size:20px;
+}
+h2 {
+ font-size:18px;
+}
+h3 {
+ font-size:16px;
+ font-style:italic;
+}
+h4 {
+ font-size:13px;
+}
+h5 {
+ font-size:12px;
+}
+h6 {
+ font-size:11px;
+}
+ul {
+ list-style-type:disc;
+}
+code, tt {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+ padding-top:4px;
+ margin-top:8px;
+ line-height:1.4em;
+}
+dt code {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+ padding-top:4px;
+}
+table tr td dt code {
+ font-family:'DejaVu Sans Mono', monospace;
+ font-size:14px;
+ vertical-align:top;
+ padding-top:4px;
+}
+sup {
+ font-size:8px;
+}
+/*
+Document title and Copyright styles
+*/
+.clear {
+ clear:both;
+ height:0px;
+ overflow:hidden;
+}
+.aboutLanguage {
+ float:right;
+ padding:0px 21px;
+ font-size:11px;
+ z-index:200;
+ margin-top:-9px;
+}
+.legalCopy {
+ margin-left:.5em;
+}
+.bar a, .bar a:link, .bar a:visited, .bar a:active {
+ color:#FFFFFF;
+ text-decoration:none;
+}
+.bar a:hover, .bar a:focus {
+ color:#bb7a2a;
+}
+.tab {
+ background-color:#0066FF;
+ color:#ffffff;
+ padding:8px;
+ width:5em;
+ font-weight:bold;
+}
+/*
+Navigation bar styles
+*/
+.bar {
+ background-color:#4D7A97;
+ color:#FFFFFF;
+ padding:.8em .5em .4em .8em;
+ height:auto;/*height:1.8em;*/
+ font-size:11px;
+ margin:0;
+}
+.topNav {
+ background-color:#4D7A97;
+ color:#FFFFFF;
+ float:left;
+ padding:0;
+ width:100%;
+ clear:right;
+ height:2.8em;
+ padding-top:10px;
+ overflow:hidden;
+ font-size:12px;
+}
+.bottomNav {
+ margin-top:10px;
+ background-color:#4D7A97;
+ color:#FFFFFF;
+ float:left;
+ padding:0;
+ width:100%;
+ clear:right;
+ height:2.8em;
+ padding-top:10px;
+ overflow:hidden;
+ font-size:12px;
+}
+.subNav {
+ background-color:#dee3e9;
+ float:left;
+ width:100%;
+ overflow:hidden;
+ font-size:12px;
+}
+.subNav div {
+ clear:left;
+ float:left;
+ padding:0 0 5px 6px;
+ text-transform:uppercase;
+}
+ul.navList, ul.subNavList {
+ float:left;
+ margin:0 25px 0 0;
+ padding:0;
+}
+ul.navList li{
+ list-style:none;
+ float:left;
+ padding: 5px 6px;
+ text-transform:uppercase;
+}
+ul.subNavList li{
+ list-style:none;
+ float:left;
+}
+.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
+ color:#FFFFFF;
+ text-decoration:none;
+ text-transform:uppercase;
+}
+.topNav a:hover, .bottomNav a:hover {
+ text-decoration:none;
+ color:#bb7a2a;
+ text-transform:uppercase;
+}
+.navBarCell1Rev {
+ background-color:#F8981D;
+ color:#253441;
+ margin: auto 5px;
+}
+.skipNav {
+ position:absolute;
+ top:auto;
+ left:-9999px;
+ overflow:hidden;
+}
+/*
+Page header and footer styles
+*/
+.header, .footer {
+ clear:both;
+ margin:0 20px;
+ padding:5px 0 0 0;
+}
+.indexHeader {
+ margin:10px;
+ position:relative;
+}
+.indexHeader span{
+ margin-right:15px;
+}
+.indexHeader h1 {
+ font-size:13px;
+}
+.title {
+ color:#2c4557;
+ margin:10px 0;
+}
+.subTitle {
+ margin:5px 0 0 0;
+}
+.header ul {
+ margin:0 0 15px 0;
+ padding:0;
+}
+.footer ul {
+ margin:20px 0 5px 0;
+}
+.header ul li, .footer ul li {
+ list-style:none;
+ font-size:13px;
+}
+/*
+Heading styles
+*/
+div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
+ background-color:#dee3e9;
+ border:1px solid #d0d9e0;
+ margin:0 0 6px -8px;
+ padding:7px 5px;
+}
+ul.blockList ul.blockList ul.blockList li.blockList h3 {
+ background-color:#dee3e9;
+ border:1px solid #d0d9e0;
+ margin:0 0 6px -8px;
+ padding:7px 5px;
+}
+ul.blockList ul.blockList li.blockList h3 {
+ padding:0;
+ margin:15px 0;
+}
+ul.blockList li.blockList h2 {
+ padding:0px 0 20px 0;
+}
+/*
+Page layout container styles
+*/
+.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
+ clear:both;
+ padding:10px 20px;
+ position:relative;
+}
+.indexContainer {
+ margin:10px;
+ position:relative;
+ font-size:12px;
+}
+.indexContainer h2 {
+ font-size:13px;
+ padding:0 0 3px 0;
+}
+.indexContainer ul {
+ margin:0;
+ padding:0;
+}
+.indexContainer ul li {
+ list-style:none;
+ padding-top:2px;
+}
+.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
+ font-size:12px;
+ font-weight:bold;
+ margin:10px 0 0 0;
+ color:#4E4E4E;
+}
+.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
+ margin:5px 0 10px 0px;
+ font-size:14px;
+ font-family:'DejaVu Sans Mono',monospace;
+}
+.serializedFormContainer dl.nameValue dt {
+ margin-left:1px;
+ font-size:1.1em;
+ display:inline;
+ font-weight:bold;
+}
+.serializedFormContainer dl.nameValue dd {
+ margin:0 0 0 1px;
+ font-size:1.1em;
+ display:inline;
+}
+/*
+List styles
+*/
+ul.horizontal li {
+ display:inline;
+ font-size:0.9em;
+}
+ul.inheritance {
+ margin:0;
+ padding:0;
+}
+ul.inheritance li {
+ display:inline;
+ list-style:none;
+}
+ul.inheritance li ul.inheritance {
+ margin-left:15px;
+ padding-left:15px;
+ padding-top:1px;
+}
+ul.blockList, ul.blockListLast {
+ margin:10px 0 10px 0;
+ padding:0;
+}
+ul.blockList li.blockList, ul.blockListLast li.blockList {
+ list-style:none;
+ margin-bottom:15px;
+ line-height:1.4;
+}
+ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
+ padding:0px 20px 5px 10px;
+ border:1px solid #ededed;
+ background-color:#f8f8f8;
+}
+ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
+ padding:0 0 5px 8px;
+ background-color:#ffffff;
+ border:none;
+}
+ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
+ margin-left:0;
+ padding-left:0;
+ padding-bottom:15px;
+ border:none;
+}
+ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
+ list-style:none;
+ border-bottom:none;
+ padding-bottom:0;
+}
+table tr td dl, table tr td dl dt, table tr td dl dd {
+ margin-top:0;
+ margin-bottom:1px;
+}
+/*
+Table styles
+*/
+.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {
+ width:100%;
+ border-left:1px solid #EEE;
+ border-right:1px solid #EEE;
+ border-bottom:1px solid #EEE;
+}
+.overviewSummary, .memberSummary {
+ padding:0px;
+}
+.overviewSummary caption, .memberSummary caption, .typeSummary caption,
+.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {
+ position:relative;
+ text-align:left;
+ background-repeat:no-repeat;
+ color:#253441;
+ font-weight:bold;
+ clear:none;
+ overflow:hidden;
+ padding:0px;
+ padding-top:10px;
+ padding-left:1px;
+ margin:0px;
+ white-space:pre;
+}
+.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,
+.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,
+.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,
+.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,
+.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,
+.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,
+.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,
+.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {
+ color:#FFFFFF;
+}
+.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,
+.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {
+ white-space:nowrap;
+ padding-top:5px;
+ padding-left:12px;
+ padding-right:12px;
+ padding-bottom:7px;
+ display:inline-block;
+ float:left;
+ background-color:#F8981D;
+ border: none;
+ height:16px;
+}
+.memberSummary caption span.activeTableTab span {
+ white-space:nowrap;
+ padding-top:5px;
+ padding-left:12px;
+ padding-right:12px;
+ margin-right:3px;
+ display:inline-block;
+ float:left;
+ background-color:#F8981D;
+ height:16px;
+}
+.memberSummary caption span.tableTab span {
+ white-space:nowrap;
+ padding-top:5px;
+ padding-left:12px;
+ padding-right:12px;
+ margin-right:3px;
+ display:inline-block;
+ float:left;
+ background-color:#4D7A97;
+ height:16px;
+}
+.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab {
+ padding-top:0px;
+ padding-left:0px;
+ padding-right:0px;
+ background-image:none;
+ float:none;
+ display:inline;
+}
+.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,
+.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {
+ display:none;
+ width:5px;
+ position:relative;
+ float:left;
+ background-color:#F8981D;
+}
+.memberSummary .activeTableTab .tabEnd {
+ display:none;
+ width:5px;
+ margin-right:3px;
+ position:relative;
+ float:left;
+ background-color:#F8981D;
+}
+.memberSummary .tableTab .tabEnd {
+ display:none;
+ width:5px;
+ margin-right:3px;
+ position:relative;
+ background-color:#4D7A97;
+ float:left;
+
+}
+.overviewSummary td, .memberSummary td, .typeSummary td,
+.useSummary td, .constantsSummary td, .deprecatedSummary td {
+ text-align:left;
+ padding:0px 0px 12px 10px;
+}
+th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,
+td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{
+ vertical-align:top;
+ padding-right:0px;
+ padding-top:8px;
+ padding-bottom:3px;
+}
+th.colFirst, th.colLast, th.colOne, .constantsSummary th {
+ background:#dee3e9;
+ text-align:left;
+ padding:8px 3px 3px 7px;
+}
+td.colFirst, th.colFirst {
+ white-space:nowrap;
+ font-size:13px;
+}
+td.colLast, th.colLast {
+ font-size:13px;
+}
+td.colOne, th.colOne {
+ font-size:13px;
+}
+.overviewSummary td.colFirst, .overviewSummary th.colFirst,
+.useSummary td.colFirst, .useSummary th.colFirst,
+.overviewSummary td.colOne, .overviewSummary th.colOne,
+.memberSummary td.colFirst, .memberSummary th.colFirst,
+.memberSummary td.colOne, .memberSummary th.colOne,
+.typeSummary td.colFirst{
+ width:25%;
+ vertical-align:top;
+}
+td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
+ font-weight:bold;
+}
+.tableSubHeadingColor {
+ background-color:#EEEEFF;
+}
+.altColor {
+ background-color:#FFFFFF;
+}
+.rowColor {
+ background-color:#EEEEEF;
+}
+/*
+Content styles
+*/
+.description pre {
+ margin-top:0;
+}
+.deprecatedContent {
+ margin:0;
+ padding:10px 0;
+}
+.docSummary {
+ padding:0;
+}
+
+ul.blockList ul.blockList ul.blockList li.blockList h3 {
+ font-style:normal;
+}
+
+div.block {
+ font-size:14px;
+ font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
+}
+
+td.colLast div {
+ padding-top:0px;
+}
+
+
+td.colLast a {
+ padding-bottom:3px;
+}
+/*
+Formatting effect styles
+*/
+.sourceLineNo {
+ color:green;
+ padding:0 30px 0 0;
+}
+h1.hidden {
+ visibility:hidden;
+ overflow:hidden;
+ font-size:10px;
+}
+.block {
+ display:block;
+ margin:3px 10px 2px 0px;
+ color:#474747;
+}
+.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
+.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
+.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink {
+ font-weight:bold;
+}
+.deprecationComment, .emphasizedPhrase, .interfaceName {
+ font-style:italic;
+}
+
+div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase,
+div.block div.block span.interfaceName {
+ font-style:normal;
+}
+
+div.contentContainer ul.blockList li.blockList h2{
+ padding-bottom:0px;
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCalc.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCalc.java
new file mode 100644
index 0000000..5c39fa8
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCalc.java
@@ -0,0 +1,68 @@
+package com.wdbyte.date;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/04/26
+ */
+public class JavaDateCalc {
+ public static void main(String[] args) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+ Date date = new Date();
+ System.out.println(String.format("当前时间:%s", sdf.format(date)));
+ date = new JavaDateCalc().addDay(date, 3);
+ System.out.println(String.format("增加三天:%s", sdf.format(date)));
+ date = new JavaDateCalc().minDay(date, 1);
+ System.out.println(String.format("减去一天:%s", sdf.format(date)));
+ date = new JavaDateCalc().addMonth(date, 2);
+ System.out.println(String.format("增加两个月:%s", sdf.format(date)));
+ }
+
+ /**
+ * 增加天数
+ *
+ * @param date
+ * @param addDay
+ * @return
+ */
+ public Date addDay(Date date, int addDay) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.DATE, addDay);
+ Date newDate = cal.getTime();
+ return newDate;
+ }
+
+ /**
+ * 减少天数
+ *
+ * @param date
+ * @param minDay
+ * @return
+ */
+ public Date minDay(Date date, int minDay) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.DATE, -minDay);
+ Date newDate = cal.getTime();
+ return newDate;
+ }
+
+ /**
+ * 增加月份
+ *
+ * @param date
+ * @param addMonth
+ * @return
+ */
+ public Date addMonth(Date date, int addMonth) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.MONTH, addMonth);
+ Date newDate = cal.getTime();
+ return newDate;
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCalc2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCalc2.java
new file mode 100644
index 0000000..922030f
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCalc2.java
@@ -0,0 +1,24 @@
+package com.wdbyte.date;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/04/26
+ */
+public class JavaDateCalc2 {
+ public static void main(String[] args) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+ Date date = new Date();
+ System.out.println(String.format("当前时间:%s", sdf.format(date)));
+ // 三天的毫秒数:3 * 24 * 3600 * 1000
+ date = new Date(date.getTime() + 3 * 24 * 3600 * 1000);
+ System.out.println(String.format("增加三天:%s", sdf.format(date)));
+
+ date = new Date(date.getTime() - 1 * 60 * 1000);
+ System.out.println(String.format("减去一分钟:%s", sdf.format(date)));
+ }
+
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCreate.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCreate.java
new file mode 100644
index 0000000..44c6bbb
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateCreate.java
@@ -0,0 +1,22 @@
+package com.wdbyte.date;
+
+import java.util.Date;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/04/25
+ */
+public class JavaDateCreate {
+ public static void main(String[] args) {
+ Date date = new Date();
+ // 输出时间
+ System.out.println(date); // Tue Apr 25 20:28:23 CST 2023
+ // 输出毫秒数
+ System.out.println(date.getTime()); // 1682425703429
+
+ // 当前毫秒数创建对象
+ //Date date2 = new Date(System.currentTimeMillis());
+ Date date2 = new Date(1682425703429L);
+ System.out.println(date2); // Tue Apr 25 20:28:23 CST 2023
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateDiff.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateDiff.java
new file mode 100644
index 0000000..09e3363
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateDiff.java
@@ -0,0 +1,54 @@
+package com.wdbyte.date;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/04/25
+ */
+public class JavaDateDiff {
+
+ public static void main(String[] args) throws InterruptedException {
+ // 获取当前时间
+ Date date1 = new Date();
+ // 休眠 3 秒
+ Thread.sleep(3000);
+ // 再获取一次当前时间
+ Date date2 = new Date();
+
+ // 很明显 date1 在 date2 之前,,所以 true
+ boolean before = date1.before(date2);
+ System.out.println(before); // true
+
+ // 很明显 date2 在 date1 之后,所以 true
+ boolean after = date2.after(date1);
+ System.out.println(after); // true
+
+ // date2 不在 date1 之前,所以 false
+ System.out.println(date2.before(date1)); // false
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+ System.out.println("date1:"+sdf.format(date1));
+ System.out.println("date2:"+sdf.format(date2));
+ Long diff = date1.getTime() - date2.getTime();
+ if (diff > 0) {
+ System.out.println("date1 > date2");
+ }
+ if (diff < 0) {
+ System.out.println("date1 < date2");
+ }
+ if (diff == 0) {
+ System.out.println("date1 = date2");
+ }
+ exec();
+ }
+
+ public static void exec() throws InterruptedException {
+ long start = System.currentTimeMillis();
+ // 做点什么
+ Thread.sleep(3000);
+ long end = System.currentTimeMillis();
+ System.out.println("耗时:" + (end - start) + "ms");
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateFormat.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateFormat.java
new file mode 100644
index 0000000..96a3c89
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/date/JavaDateFormat.java
@@ -0,0 +1,32 @@
+package com.wdbyte.date;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/04/25
+ */
+public class JavaDateFormat {
+
+ public static void main(String[] args) throws ParseException {
+ Date date = new Date();
+
+ // 时间格式化,yyyy 年份,MM 月份, dd 当月第多少天, hh:mm:ss 分别为时分秒
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+ String formatDate = simpleDateFormat.format(date);
+ System.out.println(formatDate);
+
+ SimpleDateFormat sdf1 = new SimpleDateFormat("当前日期是: yyyy-MM-dd");
+ SimpleDateFormat sdf2 = new SimpleDateFormat("当前时间是: hh:mm:ss");
+ System.out.println(sdf1.format(date));
+ System.out.println(sdf2.format(date));
+
+
+ String strDate = "2023-01-19 10:30:00";
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+ Date myDate = sdf.parse(strDate);
+ System.out.println(sdf.format(myDate));
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Calc.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Calc.java
new file mode 100644
index 0000000..d42ac62
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Calc.java
@@ -0,0 +1,30 @@
+package com.wdbyte.enum2;
+
+/**
+ * 计算枚举类
+ */
+public enum Calc {
+ // 加法
+ PLUS {
+ public int apply(int x, int y) {
+ return x + y;
+ }
+ },
+ // 减法
+ MINUS {
+ public int apply(int x, int y) {
+ return x - y;
+ }
+ },
+ // 乘法
+ MULTIPLY {
+ public int apply(int x, int y) {
+ return x * y;
+ }
+ };
+
+ public int apply(int x, int y){
+ // todo
+ return x + y;
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/CalcTest.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/CalcTest.java
new file mode 100644
index 0000000..56e2465
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/CalcTest.java
@@ -0,0 +1,19 @@
+package com.wdbyte.enum2;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/05/01
+ */
+public class CalcTest {
+ public static void main(String[] args) {
+ // 加法
+ int res = Calc.PLUS.apply(2, 3);
+ System.out.println(res);
+ // 减法
+ res = Calc.MINUS.apply(2, 3);
+ System.out.println(res);
+ // 乘法
+ res = Calc.MULTIPLY.apply(2, 3);
+ System.out.println(res);
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Rectangle.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Rectangle.java
new file mode 100644
index 0000000..43ba0ac
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Rectangle.java
@@ -0,0 +1,28 @@
+package com.wdbyte.enum2;
+
+/**
+ * 矩形枚举类
+ */
+public enum Rectangle implements Shape {
+ SMALL(3, 4),
+ MEDIUM(4, 5),
+ LARGE(5, 6);
+
+ private int length;
+ private int width;
+
+ Rectangle(int length, int width) {
+ this.length = length;
+ this.width = width;
+ }
+
+ public double getArea() {
+ return length * width;
+ }
+
+ public static void main(String[] args) {
+ Shape shape = Rectangle.LARGE;
+ double shapeArea = shape.getArea();
+ System.out.println(shapeArea);
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Shape.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Shape.java
new file mode 100644
index 0000000..8bc2d2d
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Shape.java
@@ -0,0 +1,12 @@
+package com.wdbyte.enum2;
+
+/**
+ * 形状接口
+ */
+public interface Shape {
+ /**
+ * 计算面积
+ * @return
+ */
+ double getArea();
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Weekday.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Weekday.java
new file mode 100644
index 0000000..e8aa799
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/Weekday.java
@@ -0,0 +1,11 @@
+package com.wdbyte.enum2;
+
+public enum Weekday {
+ MONDAY,
+ TUESDAY,
+ WEDNESDAY,
+ THURSDAY,
+ FRIDAY,
+ SATURDAY,
+ SUNDAY
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/WeekdayTest.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/WeekdayTest.java
new file mode 100644
index 0000000..30e6fd8
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/enum2/WeekdayTest.java
@@ -0,0 +1,30 @@
+package com.wdbyte.enum2;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/05/01
+ */
+public class WeekdayTest {
+ public static void main(String[] args) {
+ Weekday day = Weekday.MONDAY;
+ if (day == Weekday.MONDAY) {
+ System.out.println("Today is Monday.");
+ }
+
+ Weekday[] weekdays = Weekday.values();
+ for (Weekday weekday : weekdays) {
+ System.out.println(weekday);
+ }
+
+ for (Weekday weekday : weekdays) {
+ System.out.println(weekday.ordinal());
+ }
+ Weekday monday = Weekday.MONDAY;
+ switch (monday){
+ case MONDAY :{System.out.println("周一");break;}
+ case SUNDAY :{System.out.println("周末");break;}
+ }
+ System.out.println(Weekday.valueOf("MONDAY"));
+ System.out.println(Weekday.valueOf("MONDAY1"));
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException1.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException1.java
new file mode 100644
index 0000000..8fe2506
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException1.java
@@ -0,0 +1,12 @@
+package com.wdbyte.exception;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class JavaException1 {
+
+ public static void main(String[] args) {
+ String str = null;
+ System.out.println(str.length());
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException2.java
new file mode 100644
index 0000000..c5b2386
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException2.java
@@ -0,0 +1,13 @@
+package com.wdbyte.exception;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class JavaException2 {
+
+ public static void main(String[] args) {
+ String[] strArr = {"www", "wdbyte", "com"};
+ System.out.println(strArr[0]);
+ System.out.println(strArr[3]);
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException3.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException3.java
new file mode 100644
index 0000000..5e37b10
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException3.java
@@ -0,0 +1,19 @@
+package com.wdbyte.exception;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class JavaException3 {
+
+ public static void main(String[] args) {
+ String[] strArr = {"www", "wdbyte", "com"};
+ try {
+ System.out.println(strArr[0]);
+ System.out.println(strArr[3]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println("发生数组访问越界异常,不能访问超过数组长度的元素,数组长度为:" + strArr.length);
+ System.out.println("异常描述:" + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException4.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException4.java
new file mode 100644
index 0000000..0ba0f3d
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException4.java
@@ -0,0 +1,19 @@
+package com.wdbyte.exception;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class JavaException4 {
+
+ public static void main(String[] args) {
+ String[] strArr = {"www", "wdbyte", "com"};
+ try {
+ System.out.println(strArr[0]);
+ System.out.println(strArr[3]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ //throw e;
+ throw new RuntimeException(e);
+ }
+ System.out.println("执行完成。");
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException5.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException5.java
new file mode 100644
index 0000000..9366d98
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException5.java
@@ -0,0 +1,35 @@
+package com.wdbyte.exception;
+
+import org.apache.commons.lang3.ObjectUtils.Null;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class JavaException5 {
+
+ public static void main(String[] args) {
+ String[] strArr = {"www", null, "com"};
+ try {
+ System.out.println(strArr[0].length());
+ // 空指针异常
+ System.out.println(strArr[1].length());
+ System.out.println(strArr[3].length());
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println("发生数组访问越界异常,不能访问超过数组长度的元素,数组长度为:" + strArr.length);
+ } catch (NullPointerException e) {
+ System.out.println("发现空指针异常");
+ }
+ System.out.println("执行完成。");
+
+ try {
+ System.out.println(strArr[0].length());
+ // 空指针异常
+ System.out.println(strArr[1].length());
+ // 越界异常
+ System.out.println(strArr[3].length());
+ } catch (Exception e) {
+ System.out.println("发生异常:" + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException6.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException6.java
new file mode 100644
index 0000000..2b68230
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException6.java
@@ -0,0 +1,20 @@
+package com.wdbyte.exception;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/04/27
+ */
+public class JavaException6 {
+
+ public static void main(String[] args) {
+ try {
+ Files.readAllLines(Paths.get("c:/abc.txt"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException7.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException7.java
new file mode 100644
index 0000000..bdbbc19
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException7.java
@@ -0,0 +1,22 @@
+package com.wdbyte.exception;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/04/27
+ */
+public class JavaException7 {
+
+ public static void main(String[] args) {
+ try {
+ Files.readAllLines(Paths.get("c:/abc.txt"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException8.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException8.java
new file mode 100644
index 0000000..1f86646
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/JavaException8.java
@@ -0,0 +1,33 @@
+package com.wdbyte.exception;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class JavaException8 {
+
+ public static void main(String[] args) {
+ int result = 0;
+ try {
+ result = calc(4, 2);
+ System.out.println("4 / 2 = " + result);
+ } catch (MyException e) { // 不处理异常会报错
+ e.printStackTrace();
+ }
+
+ try {
+ result = calc(4, 0);
+ System.out.println("4 / 0 = " + result);
+ } catch (MyException e) { // 不处理异常会报错
+ e.printStackTrace();
+ }
+ }
+
+ public static int calc(int a, int b) throws MyException {
+ if (b == 0) {
+ throw new MyException("除数不能为0");
+ }
+ return a / b;
+ }
+}
+
+
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/MyException.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/MyException.java
new file mode 100644
index 0000000..a91c4a2
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/MyException.java
@@ -0,0 +1,7 @@
+package com.wdbyte.exception;
+
+public class MyException extends Exception {
+ public MyException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/ReadFile.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/ReadFile.java
new file mode 100644
index 0000000..664cfc3
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/ReadFile.java
@@ -0,0 +1,45 @@
+package com.wdbyte.exception;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class ReadFile {
+
+ public static void main(String[] args) {
+
+ File file = new File("pom2.xml");
+ FileReader fileReader = null;
+ BufferedReader bufferedReader = null;
+ try {
+ fileReader = new FileReader(file);
+ bufferedReader = new BufferedReader(fileReader);
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ System.out.println(line);
+ }
+ bufferedReader.close();
+ fileReader.close();
+ } catch (FileNotFoundException e) {
+ System.out.println("文件不存在");
+ } catch (IOException e) {
+ System.out.println("读取文件失败");
+ } finally {
+ try {
+ System.out.println("开始关闭资源");
+ if (bufferedReader != null) {
+ bufferedReader.close();
+ System.out.println("关闭 bufferedReader");
+ }
+ if (fileReader != null) {
+ fileReader.close();
+ System.out.println("关闭 fileReader");
+ }
+ } catch (IOException e) {
+ System.out.println("关闭文件失败");
+ }
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/ReadFile2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/ReadFile2.java
new file mode 100644
index 0000000..d238afb
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/exception/ReadFile2.java
@@ -0,0 +1,25 @@
+package com.wdbyte.exception;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class ReadFile2 {
+
+ public static void main(String[] args) {
+ File file = new File("pom.xml");
+ try (FileReader fileReader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(
+ fileReader);) {
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ System.out.println(line);
+ }
+ } catch (FileNotFoundException e) {
+ System.out.println("文件不存在");
+ } catch (IOException e) {
+ System.out.println("读取文件失败");
+ }
+ }
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/JavaExtends.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/JavaExtends.java
index 7811d7f..df818b3 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/JavaExtends.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/JavaExtends.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/31
*/
public class JavaExtends {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/AbsPerson.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/AbsPerson.java
index 062bb70..c142711 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/AbsPerson.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/AbsPerson.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.abs;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/17
*/
public abstract class AbsPerson {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/AbsPerson2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/AbsPerson2.java
new file mode 100644
index 0000000..2617065
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/AbsPerson2.java
@@ -0,0 +1,13 @@
+package com.wdbyte.oop.abs;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public abstract class AbsPerson2 {
+
+ public void sayHello() {
+ System.out.println("say hello");
+ }
+
+ public abstract void sleep();
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/PersonTest.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/PersonTest.java
index 3c8d06e..02144e2 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/PersonTest.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/PersonTest.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.abs;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/17
*/
public class PersonTest {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Student.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Student.java
index bd9060f..dbfa7b7 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Student.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Student.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.abs;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/17
*/
public class Student extends AbsPerson {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Teacher.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Teacher.java
index 8c790c8..1db8158 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Teacher.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/abs/Teacher.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.abs;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/17
*/
public class Teacher extends AbsPerson {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/InterfacePerson.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/InterfacePerson.java
new file mode 100644
index 0000000..0cd8562
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/InterfacePerson.java
@@ -0,0 +1,9 @@
+package com.wdbyte.oop.interfac;
+
+public interface InterfacePerson {
+ default void sayHello(){
+ System.out.println("say hello");
+ }
+
+ void sleep();
+}
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface.java
index 7359a11..e700d09 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.interfac;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/13
*/
public class JavaInterface {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface2.java
index b4bce89..db299b1 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface2.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface2.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.interfac;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/13
*/
public class JavaInterface2 {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface3.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface3.java
index d4a75a9..abd9ff9 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface3.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/interfac/JavaInterface3.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.interfac;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/14
*/
public class JavaInterface3 {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/AliyunOss.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/AliyunOss.java
index d6229c3..3bedb6c 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/AliyunOss.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/AliyunOss.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.polymorphism;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/18
*/
public class AliyunOss implements Oss {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/Oss.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/Oss.java
index f7466eb..8fd2af8 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/Oss.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/Oss.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.polymorphism;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/18
*/
public interface Oss {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/OssUtil.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/OssUtil.java
index 1e9eeef..5a07fc1 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/OssUtil.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/OssUtil.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.polymorphism;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/18
*/
public class OssUtil {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/TencentOss.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/TencentOss.java
index ece1f22..4993abd 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/TencentOss.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/TencentOss.java
@@ -1,7 +1,7 @@
package com.wdbyte.oop.polymorphism;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/18
*/
public class TencentOss implements Oss {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test.java
index 7565cd6..9d15814 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test.java
@@ -4,7 +4,7 @@
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/18
*/
public class Test {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test2.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test2.java
index 778c203..a1b7e3b 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test2.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/oop/polymorphism/inter/Test2.java
@@ -2,7 +2,7 @@
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/04/18
*/
public class Test2 {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaString.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/string/JavaString.java
similarity index 97%
rename from core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaString.java
rename to core-java-modules/core-java-base/src/main/java/com/wdbyte/string/JavaString.java
index 31890ee..bc4d4e6 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaString.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/string/JavaString.java
@@ -1,7 +1,7 @@
-package com.wdbyte;
+package com.wdbyte.string;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/22
*/
public class JavaString {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaStringBuilder.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/string/JavaStringBuilder.java
similarity index 94%
rename from core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaStringBuilder.java
rename to core-java-modules/core-java-base/src/main/java/com/wdbyte/string/JavaStringBuilder.java
index b492031..514054b 100644
--- a/core-java-modules/core-java-base/src/main/java/com/wdbyte/JavaStringBuilder.java
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/string/JavaStringBuilder.java
@@ -1,7 +1,7 @@
-package com.wdbyte;
+package com.wdbyte.string;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/03/30
*/
public class JavaStringBuilder {
diff --git a/core-java-modules/core-java-base/src/main/java/com/wdbyte/thread/CompletableFutureTest.java b/core-java-modules/core-java-base/src/main/java/com/wdbyte/thread/CompletableFutureTest.java
new file mode 100644
index 0000000..7887015
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/java/com/wdbyte/thread/CompletableFutureTest.java
@@ -0,0 +1,74 @@
+package com.wdbyte.thread;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/11/01
+ */
+public class CompletableFutureTest {
+
+ /**
+ * 异步执行程序后,对正常响应和异常响应进行处理
+ */
+ @Test
+ public void completableFutureTest1() {
+ CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
+ sleep(2000);
+ System.out.println("do.....");
+ return 1;
+ });
+
+ completableFuture1.thenAccept(res -> {
+ System.out.println("收到结果:" + res
+ );
+ });
+
+ System.out.println("等待");
+ sleep(10 * 1000);
+ }
+ @Test
+ public void completableFutureTest2() {
+ CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
+ sleep(2000);
+ System.out.println("do2.....");
+ return 10 / 0;
+ });
+ completableFuture2.exceptionally(except -> {
+ System.out.println("发生异常:" + except.getMessage());
+ return 0;
+ });
+
+ System.out.println("等待");
+ sleep(10 * 1000);
+ }
+
+ @Test
+ public void completableFutureTest3() {
+ CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
+ sleep(2000);
+ System.out.println("do.....");
+ return 1;
+ });
+
+ completableFuture1.thenAccept(res -> {
+ System.out.println("收到结果:" + res
+ );
+ });
+
+ System.out.println("等待");
+ sleep(10 * 1000);
+ }
+
+ void sleep(long millis){
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-base/src/main/resources/META-INF/maven/archetype.xml b/core-java-modules/core-java-base/src/main/resources/META-INF/maven/archetype.xml
new file mode 100644
index 0000000..5cfc7cc
--- /dev/null
+++ b/core-java-modules/core-java-base/src/main/resources/META-INF/maven/archetype.xml
@@ -0,0 +1,9 @@
+
+ core-java-base
+
+ src/main/java/App.java
+
+
+ src/test/java/AppTest.java
+
+
diff --git "a/core-java-modules/core-java-base/\351\233\206\345\220\210\346\241\206\346\236\266\345\205\263\347\263\273\345\233\276.uml" "b/core-java-modules/core-java-base/\351\233\206\345\220\210\346\241\206\346\236\266\345\205\263\347\263\273\345\233\276.uml"
new file mode 100644
index 0000000..1e2c5c9
--- /dev/null
+++ "b/core-java-modules/core-java-base/\351\233\206\345\220\210\346\241\206\346\236\266\345\205\263\347\263\273\345\233\276.uml"
@@ -0,0 +1,138 @@
+
+
+ JAVA
+ java.util.ArrayList
+
+ java.util.HashSet
+ com.sun.jmx.remote.internal.ArrayQueue
+ java.util.Vector
+ java.util.Set
+ java.util.TreeSet
+ java.util.concurrent.ArrayBlockingQueue
+ java.util.List
+ java.util.TreeMap
+ java.util.concurrent.ConcurrentHashMap
+ java.util.LinkedHashSet
+ java.util.Stack
+ java.util.concurrent.DelayQueue
+ java.util.Map
+ java.util.LinkedList
+ java.lang.Iterable
+ java.util.AbstractList
+ java.util.Collection
+ java.util.HashMap
+ java.util.Queue
+ java.util.LinkedHashMap
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ All
+ private
+
+
diff --git a/core-java-modules/core-java-collect/src/main/java/com/wdbyte/collection/EnumMapTest.java b/core-java-modules/core-java-collect/src/main/java/com/wdbyte/collection/EnumMapTest.java
new file mode 100644
index 0000000..1370449
--- /dev/null
+++ b/core-java-modules/core-java-collect/src/main/java/com/wdbyte/collection/EnumMapTest.java
@@ -0,0 +1,25 @@
+package com.wdbyte.collection;
+
+import java.util.EnumMap;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/10/20
+ */
+public class EnumMapTest {
+ public static void main(String[] args) {
+ EnumMap enumMap = new EnumMap(Week.class);
+ enumMap.put(Week.a,null);
+ System.out.println(enumMap.get(Week.a));
+ }
+}
+
+enum Week {
+ a,
+ b,
+ c,
+ d,
+ e,
+ f,
+ g
+}
diff --git a/core-java-modules/core-java-collect/src/main/java/com/wdbyte/collection/JavaArrays.java b/core-java-modules/core-java-collect/src/main/java/com/wdbyte/collection/JavaArrays.java
new file mode 100644
index 0000000..144cdcb
--- /dev/null
+++ b/core-java-modules/core-java-collect/src/main/java/com/wdbyte/collection/JavaArrays.java
@@ -0,0 +1,146 @@
+package com.wdbyte.collection;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.function.IntFunction;
+import java.util.function.ToIntFunction;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2024/03/04
+ */
+public class JavaArrays {
+
+ @Test
+ public void print() {
+ String[] arr = new String[] {"a", "b", "c", "d"};
+ System.out.println(Arrays.toString(arr));
+ }
+
+ @Test
+ public void init() {
+ String[] arr = new String[] {"a", "b", "c", "d"};
+ String[] copyOf2 = Arrays.copyOf(arr, 2);
+ String[] copyOfRange = Arrays.copyOfRange(arr, 1, 3);
+
+ System.out.println(Arrays.toString(arr));
+ System.out.println(Arrays.toString(copyOf2));
+ System.out.println(Arrays.toString(copyOfRange));
+
+ // 目标大小大于原始大小,则copyOf 会用null填充数组 。
+ String[] copyOf10 = Arrays.copyOf(arr, 10);
+ System.out.println(Arrays.toString(copyOf10));
+ }
+
+ @Test
+ public void fill() {
+ String[] arr = new String[5];
+ Arrays.fill(arr, "java");
+ System.out.println(Arrays.toString(arr));
+
+ // 生成 100以内的 随机数
+ IntFunction intFunction = i -> new Random().nextInt(100);
+ Integer[] intArr = new Integer[5];
+ Arrays.setAll(intArr, intFunction);
+ System.out.println(Arrays.toString(intArr));
+ }
+
+ @Test
+ public void diff() {
+ String[] arr = new String[] {"a", "b", "c", "d"};
+ Object[] arr1 = new Object[] {arr, new String[] {"a", "b", "c", "d"}};
+ Object[] arr2 = new Object[] {arr, arr};
+
+ System.out.println(Arrays.equals(arr1, arr2));
+ System.out.println(Arrays.deepEquals(arr1, arr2));
+
+ // hashCode
+ System.out.println(Arrays.hashCode(arr2));
+ System.out.println(Arrays.deepHashCode(arr2));
+
+ arr[0] = null;
+ System.out.println(Arrays.hashCode(arr2));
+ System.out.println(Arrays.deepHashCode(arr2));
+ }
+
+ @Test
+ public void sort() {
+ // 生成 100以内的 随机数
+ IntFunction intFunction = i -> new Random().nextInt(100);
+ Integer[] intArr = new Integer[5];
+ Arrays.setAll(intArr, intFunction);
+ System.out.println(Arrays.toString(intArr));
+
+ Arrays.sort(intArr);
+ System.out.println(Arrays.toString(intArr));
+
+ //long cost = 0;
+ //for (int ii = 0; ii < 10; ii++) {
+ // IntFunction intFunction = i -> new Random().nextInt(100000);
+ // Integer[] intArr = new Integer[100000];
+ // Arrays.setAll(intArr, intFunction);
+ //
+ // long start = System.currentTimeMillis();
+ // Arrays.sort(intArr);
+ // long end = System.currentTimeMillis();
+ // cost = cost + (end - start);
+ //}
+ //System.out.println(cost / 10);
+ //
+ //cost = 0;
+ //for (int ii = 0; ii < 10; ii++) {
+ // IntFunction intFunction = i -> new Random().nextInt(100000);
+ // Integer[] intArr = new Integer[100000];
+ // Arrays.setAll(intArr, intFunction);
+ //
+ // long start = System.currentTimeMillis();
+ // Arrays.parallelSort(intArr);
+ // long end = System.currentTimeMillis();
+ // cost = cost + (end - start);
+ //}
+ //System.out.println(cost / 10);
+ }
+
+ @Test
+ public void search() {
+ Integer[] intArr = new Integer[] {2, 3, 4, 5, 6, 7, 8, 9};
+ int index = Arrays.binarySearch(intArr, 3);
+ System.out.println("index:"+index);
+ System.out.println(intArr[index]);
+ }
+
+ @Test
+ public void stream() {
+ Integer[] intArr = new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ System.out.println(Arrays.stream(intArr).count());
+ ToIntFunction toIntFunction = i -> (int)i;
+ System.out.println(Arrays.stream(intArr).mapToInt(toIntFunction).sum());
+ }
+
+ @Test
+ public void cast() {
+ String[] arr = new String[] {"a", "b", "c", "d"};
+ Object[] arr2 = new Object[] {arr, arr};
+
+ System.out.println(Arrays.toString(arr));
+ System.out.println(Arrays.toString(arr2));
+
+ System.out.println(Arrays.deepToString(arr));
+ System.out.println(Arrays.deepToString(arr2));
+
+ List list = Arrays.asList(arr);
+ System.out.println(list);
+ System.out.println(list.getClass());
+ // list.add("e"); 报错
+ }
+
+ @Test
+ public void prefix() {
+ Integer[] intArr = new Integer[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ Arrays.parallelPrefix(intArr, (left, right) -> left + right);
+ System.out.println(Arrays.toString(intArr));
+ }
+}
diff --git a/core-java-modules/core-java-io/README.md b/core-java-modules/core-java-io/README.md
index 5d1fb00..85360a7 100644
--- a/core-java-modules/core-java-io/README.md
+++ b/core-java-modules/core-java-io/README.md
@@ -2,5 +2,8 @@
当前模块包含 IO 相关代码
### 相关文章
-
+- [Java 创建和写入文件](https://www.wdbyte.com/java/io/file-create-write/)
+- [Java 读取文件](https://www.wdbyte.com/java/io/file-read/)
+- [Java 追加内容到文件](https://www.wdbyte.com/java/io/file-append/)
+- [Java 如何删除文件](https://www.wdbyte.com/java/io/file-delete/)
- [字符图案,我用字符画个冰墩墩](https://www.wdbyte.com/java/char-image.html)
\ No newline at end of file
diff --git a/core-java-modules/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml
index 2fb5dba..30c75c1 100644
--- a/core-java-modules/core-java-io/pom.xml
+++ b/core-java-modules/core-java-io/pom.xml
@@ -14,18 +14,22 @@
jar
- 1.8
- 1.8
+ 21
+ 21
com.google.guava
guava
- 31.0.1-jre
- jar
- provided
+ 32.1.3-jre
+
+ commons-io
+ commons-io
+ 2.7
+
+
diff --git a/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileAppendDemo.java b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileAppendDemo.java
new file mode 100644
index 0000000..53879c8
--- /dev/null
+++ b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileAppendDemo.java
@@ -0,0 +1,179 @@
+package com.wdbyte.io.file;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.FileWriteMode;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/12/12
+ */
+public class FileAppendDemo {
+
+ @Test
+ public void appendLine1() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/test1.txt");
+ // 写入一行数据
+ Files.write(path, "line append1".getBytes(StandardCharsets.UTF_8),
+ StandardOpenOption.CREATE, StandardOpenOption.APPEND);
+ // 写入一个换行符
+ Files.write(path, System.lineSeparator().getBytes(StandardCharsets.UTF_8),
+ StandardOpenOption.APPEND);
+ }
+
+ @Test
+ public void appendLine2() throws IOException {
+ String path = "/Users/darcy/wdbyte/test1.txt";
+ try (FileWriter fileWriter = new FileWriter(path, true)) {
+ fileWriter.write("line append2");
+ fileWriter.write(System.lineSeparator());
+ }
+ }
+ @Test
+ public void appendLine3() throws IOException {
+ String path = "/Users/darcy/wdbyte/test1.txt";
+ try (FileWriter fileWriter = new FileWriter(path, true)) {
+ BufferedWriter bw = new BufferedWriter(fileWriter);
+ bw.write("line append3");
+ bw.newLine();
+ }
+ }
+
+ @Test
+ public void appendLine4() throws IOException {
+ String path = "/Users/darcy/wdbyte/test1.txt";
+ try (FileOutputStream fileOutputStream = new FileOutputStream(path, true)) {
+ fileOutputStream.write("line append4".getBytes(StandardCharsets.UTF_8));
+ fileOutputStream.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8));
+ }
+ }
+
+ /**
+ * java 11 Files.writeString
+ * @throws IOException
+ */
+ public void appendLineJava11() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/test1.txt");
+ Files.writeString(path, "line appendLineJava11",
+ StandardOpenOption.CREATE,
+ StandardOpenOption.APPEND);
+ }
+
+
+ /**
+ * Java 8
+ *
+ * @throws IOException
+ */
+ @Test
+ public void appendLineJava8() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/test1.txt");
+ List dataList = new ArrayList<>();
+ dataList.add("line1 appendLineJava8");
+ dataList.add("line2 appendLineJava8");
+ dataList.add("line3 appendLineJava8");
+
+ Files.write(path, dataList,
+ StandardOpenOption.CREATE,
+ StandardOpenOption.APPEND);
+
+ Files.write(path, System.lineSeparator().getBytes(StandardCharsets.UTF_8),
+ StandardOpenOption.CREATE,
+ StandardOpenOption.APPEND);
+ }
+
+ @Test
+ public void appendLineList() throws IOException {
+ String path = "/Users/darcy/wdbyte/test1.txt";
+ List dataList = new ArrayList<>();
+ dataList.add("line1 appendLineList");
+ dataList.add("line2 appendLineList");
+ dataList.add("line3 appendLineList");
+
+ try (FileWriter fileWriter = new FileWriter(path, true)) {
+ BufferedWriter bw = new BufferedWriter(fileWriter);
+ for (String data : dataList) {
+ bw.write(data);
+ bw.newLine();
+ }
+ }
+ }
+
+ @Test
+ public void appendByCommonsIo() throws IOException {
+ File file = new File("/Users/darcy/wdbyte/test1.txt");
+ String content = "hello commons io,appendByCommonsIo";
+ FileUtils.writeStringToFile(file, content, StandardCharsets.UTF_8, true);
+ FileUtils.writeStringToFile(file, System.lineSeparator(), StandardCharsets.UTF_8, true);
+ }
+
+ @Test
+ public void appendListByCommonsIo() throws IOException {
+ File file = new File("/Users/darcy/wdbyte/test1.txt");
+ List dataList = new ArrayList<>();
+ dataList.add("line1 hello commons io,appendListByCommonsIo");
+ dataList.add("line2 hello commons io,appendListByCommonsIo");
+ dataList.add("line3 hello commons io,appendListByCommonsIo");
+ FileUtils.writeLines(file, dataList, true);
+ }
+
+ @Test
+ public void appendData(){
+ // 创建File对象指向要追加内容的文件
+ File file = new File("/Users/darcy/wdbyte/test1.txt");
+ // 要追加的内容
+ String contentToAppend = "Hello, Guava!";
+ try {
+ // 使用Guava的Files类以追加模式写入内容
+ com.google.common.io.Files.asCharSink(file, Charsets.UTF_8, FileWriteMode.APPEND)
+ .write(contentToAppend);
+
+ // 如果需要追加新行,可以使用下面的代码
+ com.google.common.io.Files.asCharSink(file, Charsets.UTF_8, com.google.common.io.FileWriteMode.APPEND)
+ .write(contentToAppend + System.lineSeparator());
+ System.out.println("Content appended successfully.");
+ } catch (IOException e) {
+ System.err.println("Error appending content to file: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void appendDataListByGuava(){
+ // 创建File对象指向要追加内容的文件
+ File file = new File("/Users/darcy/wdbyte/test1.txt");
+
+ // 要追加的内容
+ List dataList = new ArrayList<>();
+ dataList.add("line1 hello commons io,appendDataListByGuava");
+ dataList.add("line2 hello commons io,appendDataListByGuava");
+ dataList.add("line3 hello commons io,appendDataListByGuava");
+
+ try {
+ // 使用Guava的Files类以追加模式写入内容
+ com.google.common.io.Files.asCharSink(file, Charsets.UTF_8, FileWriteMode.APPEND)
+ .writeLines(dataList);
+
+ System.out.println("Content appended successfully.");
+ } catch (IOException e) {
+ System.err.println("Error appending content to file: " + e.getMessage());
+ }
+ }
+
+
+
+
+}
diff --git a/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileCreateAndWriteDemo.java b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileCreateAndWriteDemo.java
new file mode 100644
index 0000000..158942d
--- /dev/null
+++ b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileCreateAndWriteDemo.java
@@ -0,0 +1,108 @@
+package com.wdbyte.io.file;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/11/06
+ */
+public class FileCreateAndWriteDemo {
+
+ @Test
+ public void test0() throws IOException {
+ String content = "www.wdbyte.com,java 7";
+ String filePath = "/Users/darcy/wdbyte/test0.txt";
+ try (FileWriter fw = new FileWriter(filePath);
+ BufferedWriter bw = new BufferedWriter(fw)) {
+ bw.write(content);
+ bw.newLine();
+ }
+
+ // 追加模式
+ try (FileWriter fw = new FileWriter(filePath, true);
+ BufferedWriter bw = new BufferedWriter(fw)) {
+ bw.write(content);
+ bw.newLine();
+ }
+ }
+
+ /**
+ * JDK 7
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test1() throws IOException {
+ String content = "www.wdbyte.com, java 7";
+ Path path = Paths.get("/Users/darcy/wdbyte/test1.txt");
+ // string -> bytes
+ Files.write(path, content.getBytes(StandardCharsets.UTF_8));
+ }
+
+ /**
+ * JDK 7 追加
+ * @throws IOException
+ */
+ @Test
+ public void test2() throws IOException {
+ String content = "www.wdbyte.com,java 7" + System.lineSeparator();
+ Path path = Paths.get("/Users/darcy/wdbyte/test2.txt");
+ Files.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE,
+ StandardOpenOption.APPEND);
+ Files.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE,
+ StandardOpenOption.APPEND);
+ }
+
+ /**
+ * JDK 7 写入 List
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test3() throws IOException {
+ List dataList = Arrays.asList("www", "wdbyte", "com", "java 7");
+ Path path = Paths.get("/Users/darcy/wdbyte/test3.txt");
+ Files.write(path, dataList);
+ }
+
+ @Test
+ public void test4() throws IOException {
+ String content = "www.wdbyte.com,java 7";
+ Path path = Paths.get("/Users/darcy/wdbyte/test4.txt");
+ // 默认 utf_8
+ try (BufferedWriter bw = Files.newBufferedWriter(path)) {
+ bw.write(content);
+ bw.newLine();
+ }
+ // 追加模式
+ try (BufferedWriter bw = Files.newBufferedWriter(path,
+ StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
+ bw.write(content);
+ bw.newLine();
+ }
+ }
+
+ /**
+ * JDK 11
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test5() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/test5.txt");
+ Files.writeString(path, "www.wdbyte.com,java 11");
+ }
+
+
+}
diff --git a/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileDelete.java b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileDelete.java
new file mode 100644
index 0000000..f865382
--- /dev/null
+++ b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileDelete.java
@@ -0,0 +1,73 @@
+package com.wdbyte.io.file;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/12/18
+ */
+public class FileDelete {
+
+ @Test
+ public void deleteFile() {
+ Path path = Paths.get("/Users/darcy/wdbyte/test.txt");
+ try {
+ Files.delete(path);
+ System.out.println("文件删除成功");
+ } catch (Exception e) {
+ System.out.println("文件删除失败");
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void deleteIfExists() {
+ Path path = Paths.get("/Users/darcy/wdbyte/test.txt");
+ try {
+ boolean deleted = Files.deleteIfExists(path);
+ if (deleted) {
+ System.out.println("文件删除成功");
+ } else {
+ System.out.println("文件不存在或者无法删除");
+ }
+ } catch (Exception e) {
+ System.out.println("文件删除失败");
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void delete() {
+ File file = new File("/Users/darcy/wdbyte/test.txt");
+ if (file.delete()) {
+ System.out.println("文件删除成功");
+ } else {
+ System.out.println("文件删除失败");
+ }
+ }
+
+ @Test
+ public void deleteOnExit() {
+ File file = new File("/Users/darcy/wdbyte/test.txt");
+ file.deleteOnExit();
+ }
+
+ @Test
+ public void forceDelete() {
+ File file = new File("/Users/darcy/wdbyte/test.txt");
+ try {
+ FileUtils.forceDelete(file);
+ System.out.println("文件删除成功");
+ } catch (Exception e) {
+ System.out.println("文件删除失败");
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileReadDemo.java b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileReadDemo.java
new file mode 100644
index 0000000..276e0e8
--- /dev/null
+++ b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/file/FileReadDemo.java
@@ -0,0 +1,178 @@
+package com.wdbyte.io.file;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Scanner;
+import java.util.stream.Stream;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author www.wdbyte.com
+ * @date 2023/11/08
+ */
+public class FileReadDemo {
+
+ public static void main(String[] args) {
+ Path path = Paths.get("/Users/darcy/wdbyte");
+ System.out.println(Files.isDirectory(path));
+ System.out.println(path.toFile().isFile());
+ System.out.println(path.toFile().isDirectory());
+ }
+
+ /**
+ * java 8
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test1() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
+ List lines = Files.readAllLines(path, StandardCharsets.UTF_8);
+ for (String line : lines) {
+ System.out.println(line);
+ }
+ }
+
+ /**
+ * java 8
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test2() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
+ byte[] bytes = Files.readAllBytes(path);
+ String content = new String(bytes, StandardCharsets.UTF_8);
+ System.out.println(content);
+ }
+
+ /**
+ * java 8
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test3() throws IOException, InterruptedException {
+ Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
+ try (Stream stream = Files.lines(path);) {
+ stream.forEach(System.out::println);
+ }
+ try (Stream stream = Files.lines(path);) {
+ stream.parallel().forEachOrdered(System.out::println);
+ }
+ }
+
+ /**
+ * java 11
+ * 要求:文件小于2G
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test4() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
+ String content = Files.readString(path, StandardCharsets.UTF_8);
+ System.out.println(content);
+ }
+
+ @Test
+ public void test5() {
+ File file = new File("/Users/darcy/wdbyte/log.txt");
+ String line;
+ // 默认读取缓冲区大小 8K
+ try (BufferedReader br = new BufferedReader(new FileReader(file))) {
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ // 定义缓冲区大小为 128 K
+ int buffer = 128 * 1024;
+ try (BufferedReader br = new BufferedReader(new FileReader(file), buffer)) {
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * java 8
+ *
+ * @throws IOException
+ */
+ @Test
+ public void test6() throws IOException {
+ Path path = Paths.get("/Users/darcy/wdbyte/log.txt");
+ String line;
+ try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8);) {
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ }
+ }
+
+ /**
+ * 自古以来
+ */
+ @Test
+ public void test7() {
+ File file = new File("/Users/darcy/wdbyte/log.txt");
+ try (Scanner sc = new Scanner(new FileReader(file))) {
+ while (sc.hasNextLine()) {
+ String line = sc.nextLine();
+ System.out.println(line);
+ }
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 自古以来
+ */
+ @Test
+ public void test8() {
+ File file = new File("/Users/darcy/wdbyte/log.txt");
+ try (FileInputStream fis = new FileInputStream(file);
+ BufferedInputStream bis = new BufferedInputStream(fis);) {
+
+ StringBuilder content = new StringBuilder();
+ int data;
+ while ((data = bis.read()) != -1) {
+ content.append((char)data);
+ }
+ System.out.println(content.toString());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void readFileByApacheCommons() throws IOException {
+ File file = new File("/Users/darcy/wdbyte/test.txt");
+ List list = FileUtils.readLines(file, StandardCharsets.UTF_8);
+ for (String data : list) {
+ System.out.println(data);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/image/GeneratorTextImageMini.java b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/image/GeneratorTextImageMini.java
new file mode 100644
index 0000000..4bad1d8
--- /dev/null
+++ b/core-java-modules/core-java-io/src/main/java/com/wdbyte/io/image/GeneratorTextImageMini.java
@@ -0,0 +1,89 @@
+package com.wdbyte.io.image;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+/**
+ *
+ * 根据图片生成字符图案
+ * 1.图片大小缩放
+ * 2.遍历图片像素点
+ * 3.获取图片像素点亮度
+ * 4.匹配字符
+ * 5.输出图案
+ *
+ * @website https://www.wdbyte.com
+ */
+public class GeneratorTextImageMini {
+
+ public static void main(String[] args) throws Exception {
+ //BufferedImage image = resizeImage("/Users/darcy/Downloads/sanli.jpg", 120);
+ BufferedImage image = ImageIO.read(new File("/Users/darcy/Downloads/刘看山.jpg"));
+ printImage(image);
+ }
+
+ /**
+ * 图片缩放
+ *
+ * @param srcImagePath 图片路径
+ * @param targetWidth 目标宽度
+ * @return
+ * @throws IOException
+ */
+ public static BufferedImage resizeImage(String srcImagePath, int targetWidth) throws IOException {
+ Image srcImage = ImageIO.read(new File(srcImagePath));
+ int targetHeight = getTargetHeight(targetWidth, srcImage);
+ BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
+ Graphics2D graphics2D = resizedImage.createGraphics();
+ graphics2D.drawImage(srcImage, 0, 0, targetWidth, targetHeight, null);
+ graphics2D.dispose();
+ return resizedImage;
+ }
+
+ /**
+ * 根据指定宽度,计算等比例高度
+ *
+ * @param targetWidth 目标宽度
+ * @param srcImage 图片信息
+ * @return
+ */
+ private static int getTargetHeight(int targetWidth, Image srcImage) {
+ int targetHeight = srcImage.getHeight(null);
+ if (targetWidth < srcImage.getWidth(null)) {
+ targetHeight = Math.round((float)targetHeight / ((float)srcImage.getWidth(null) / (float)targetWidth));
+ }
+ return targetHeight;
+ }
+
+ /**
+ * 图片打印
+ *
+ * @param image
+ * @throws IOException
+ */
+ public static void printImage(BufferedImage image) throws IOException {
+ final char[] PIXEL_CHAR_ARRAY = {'W', '@', '#', '8', '&', '*', 'o', ':', '.', ' '};
+ //final char[] PIXEL_CHAR_ARRAY = {',', '.', ' '};
+ int width = image.getWidth();
+ int height = image.getHeight();
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ int rgb = image.getRGB(j, i);
+ Color color = new Color(rgb);
+ int red = color.getRed();
+ int green = color.getGreen();
+ int blue = color.getBlue();
+ // 一个用于计算RGB像素点灰度的公式
+ Double grayscale = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
+ double index = grayscale / (Math.ceil(255 / PIXEL_CHAR_ARRAY.length) + 0.5);
+ System.out.print(PIXEL_CHAR_ARRAY[(int)(Math.floor(index))]);
+ }
+ System.out.println();
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-io/target/classes/bingdundun.jpeg b/core-java-modules/core-java-io/target/classes/bingdundun.jpeg
new file mode 100644
index 0000000..8243a8a
Binary files /dev/null and b/core-java-modules/core-java-io/target/classes/bingdundun.jpeg differ
diff --git a/core-java-modules/core-java-os/.gitignore b/core-java-modules/core-java-os/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/core-java-modules/core-java-os/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/core-java-modules/core-java-os/README.md b/core-java-modules/core-java-os/README.md
new file mode 100644
index 0000000..bfb1c8a
--- /dev/null
+++ b/core-java-modules/core-java-os/README.md
@@ -0,0 +1,6 @@
+## core-java-os
+当前模块包含操作系统操作相关代码
+
+### 相关文章
+
+- [ProcessBuilder API 使用教程](https://www.wdbyte.com/java/os/processbuilder/)
\ No newline at end of file
diff --git a/core-java-modules/core-java-os/pom.xml b/core-java-modules/core-java-os/pom.xml
new file mode 100644
index 0000000..721644b
--- /dev/null
+++ b/core-java-modules/core-java-os/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+ com.wdbyte.core-java-modules
+ core-java-modules
+ 1.0.0-SNAPSHOT
+
+
+ core-java-os
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ commons-io
+ commons-io
+ 2.12.0
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ExecDemo.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ExecDemo.java
new file mode 100644
index 0000000..4b73eb6
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ExecDemo.java
@@ -0,0 +1,18 @@
+package com.wdbyte.os.process;
+
+import java.io.IOException;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class ExecDemo {
+
+ public static void main(String[] args) throws InterruptedException {
+ System.out.println("开始处理数据...");
+ for (int i = 0; i < 10; i++) {
+ Thread.sleep(1000);
+ System.out.println(i);
+ }
+ System.out.println("数据处理完毕");
+ }
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest1.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest1.java
new file mode 100644
index 0000000..919fb7f
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest1.java
@@ -0,0 +1,52 @@
+package com.wdbyte.os.process;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Process 输出Java 版本号
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest1 {
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ // 构建执行命令
+ ProcessBuilder processBuilder = new ProcessBuilder("java","-version");
+ // 重定向 ERROR 流(有些 JDK 版本 Java 命令通过 ERROR 流输出)
+ processBuilder.redirectErrorStream(true);
+ // 运行命令 java -version
+ Process process = processBuilder.start();
+ // 过去PID
+ long pid = process.pid();
+ // 一次性获取运行结果
+ //String result = convertInputStreamToString(process.getInputStream());
+ String result = IOUtils.toString(process.getInputStream());
+ // 等到运行结束
+ int exitCode = process.waitFor();
+
+ System.out.println("pid:" + pid);
+ System.out.println("result:" + result);
+ System.out.println("exitCode:" + exitCode);
+ }
+
+ public static String convertInputStreamToString(InputStream inputStream) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
+ String line = null;
+ while ((line = bufferedReader.readLine()) != null) {
+ sb.append(line);
+ sb.append(System.lineSeparator());
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ inputStream.close();
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest10.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest10.java
new file mode 100644
index 0000000..6c980d9
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest10.java
@@ -0,0 +1,42 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest10 {
+ private static String BASE_DIR = "/Users/darcy/git/JavaNotes/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process";
+
+ public static void main(String[] args) throws InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(new File(BASE_DIR));
+ processBuilder.command("java", "ExecDemo.java");
+ // 把子线程 I/O 输出重定向当前进程
+ processBuilder.inheritIO();
+
+ // 创建 CompletableFuture 对象
+ CompletableFuture future = CompletableFuture.supplyAsync(() -> {
+ try {
+ // 命令执行
+ Process process = processBuilder.start();
+ // 任务超时时间
+ process.waitFor();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ });
+
+ // 注册回调函数,处理异步等待的结果
+ future.thenAccept(result -> {
+ System.out.println("进程执行结束");
+ });
+ System.out.println("主进程等待");
+ Thread.sleep(20 * 1000);
+ }
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest2.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest2.java
new file mode 100644
index 0000000..7075784
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest2.java
@@ -0,0 +1,32 @@
+package com.wdbyte.os.process;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.commons.io.IOUtils;
+
+/**
+ * 修改环境变量
+ *
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest2 {
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ Map environment = processBuilder.environment();
+ environment.forEach((k, v) -> System.out.println(k + ":" + v));
+ System.out.println("--------------");
+ processBuilder.environment().put("my_website", "www.wdbyte.com");
+ processBuilder.command("/bin/bash", "-c", "echo $my_website");
+
+ Process process = processBuilder.start();
+ long pid = process.pid();
+ String result = IOUtils.toString(process.getInputStream());
+ int exitCode = process.waitFor();
+
+ System.out.println("pid:" + pid);
+ System.out.println("result:" + result);
+ System.out.println("exitCode:" + exitCode);
+ }
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest3.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest3.java
new file mode 100644
index 0000000..3042923
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest3.java
@@ -0,0 +1,31 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.IOUtils;
+
+/**
+ * 修改工作目录
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest3 {
+
+ private static String BASE_DIR = "/Users/darcy/git/JavaNotes/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process";
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(new File(BASE_DIR));
+ processBuilder.command("/bin/bash", "-c", "pwd");
+ Process process = processBuilder.start();
+
+ long pid = process.pid();
+ String result = IOUtils.toString(process.getInputStream());
+ int exitCode = process.waitFor();
+
+ System.out.println("pid:" + pid);
+ System.out.println("result:" + result);
+ System.out.println("exitCode:" + exitCode);
+ }
+
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest4.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest4.java
new file mode 100644
index 0000000..73d91be
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest4.java
@@ -0,0 +1,36 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/**
+ * 输出日志到指定文件
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest4 {
+ private static String BASE_DIR = "/Users/darcy/git/JavaNotes/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process";
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(new File(BASE_DIR));
+ processBuilder.command("/bin/bash", "-c", "ls -l");
+
+ File logFile = new File(BASE_DIR + "/process_log.txt");
+ // 输出到日志文件
+ processBuilder.redirectOutput(logFile);
+ // 追加日志到文件
+ // processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(logFile));
+ // 是否输出ERROR日志到文件
+ processBuilder.redirectErrorStream(true);
+
+ Process process = processBuilder.start();
+ long pid = process.pid();
+ int exitCode = process.waitFor();
+ System.out.println("pid:" + pid);
+ System.out.println("exitCode:" + exitCode);
+
+ // 读取日志
+ Files.lines(logFile.toPath()).forEach(System.out::println);
+ }
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest5.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest5.java
new file mode 100644
index 0000000..54c4752
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest5.java
@@ -0,0 +1,40 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/**
+ * 输出日志到指定文件
+ *
+ * @author https://www.wdbyte.com
+ **
+ */
+public class ProcessBuilderTest5 {
+ private static String BASE_DIR = "/Users/darcy/git/JavaNotes/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process";
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(new File(BASE_DIR));
+ // 执行命令 xxx,命令不存在,会报 ERROR 日志
+ processBuilder.command("/bin/bash", "-c", "xxx");
+
+ File infoLogFile = new File(BASE_DIR + "/process_log_info.txt");
+ File errorLogFile = new File(BASE_DIR + "/process_log_error.txt");
+ // 日志输出到文件
+ processBuilder.redirectOutput(infoLogFile);
+ processBuilder.redirectError(errorLogFile);
+ Process process = processBuilder.start();
+
+ long pid = process.pid();
+ int exitCode = process.waitFor();
+
+ System.out.println("pid:" + pid);
+ System.out.println("exitCode:" + exitCode);
+
+ // 读取 ERROR 日志
+ Files.lines(errorLogFile.toPath()).forEach(System.out::println);
+ }
+
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest6.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest6.java
new file mode 100644
index 0000000..8c71d3b
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest6.java
@@ -0,0 +1,23 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 子线程 I/O 重定向到当前线程
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest6 {
+ public static void main(String[] args) throws IOException, InterruptedException {
+
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(new File("./"));
+ processBuilder.command("/bin/bash", "-c", "ls -l");
+ // 把子线程 I/O 输出重定向当前进程
+ processBuilder.inheritIO();
+ Process process = processBuilder.start();
+ int exitCode = process.waitFor();
+ System.out.println("exitCode:" + exitCode);
+ }
+
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest7.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest7.java
new file mode 100644
index 0000000..bbcf647
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest7.java
@@ -0,0 +1,30 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 运行一个 Java 程序
+ *
+ * @author https://www.wdbyte.com
+ **
+ */
+public class ProcessBuilderTest7 {
+ private static String BASE_DIR = "/Users/darcy/git/JavaNotes/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process";
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(new File(BASE_DIR));
+ processBuilder.command("java", "ExecDemo.java");
+ // 把子线程 I/O 输出重定向当前进程
+ processBuilder.inheritIO();
+ Process process = processBuilder.start();
+
+ long pid = process.pid();
+ int exitCode = process.waitFor();
+
+ System.out.println("pid:" + pid);
+ System.out.println("exitCode:" + exitCode);
+ }
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest8.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest8.java
new file mode 100644
index 0000000..d38fbec
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest8.java
@@ -0,0 +1,40 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.ProcessBuilder.Redirect;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Java 9 中新增的管道操作
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest8 {
+ private static String BASE_DIR = "/Users/darcy/git/JavaNotes/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process";
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ ProcessBuilder ls = new ProcessBuilder("/bin/bash", "-c", "ls -l");
+ ProcessBuilder wc = new ProcessBuilder("wc", "-l");
+ // 追加日志到文件
+ File pipeLineLogFile = getFile(BASE_DIR + "/pipe_line_log.txt");
+ wc.redirectOutput(Redirect.appendTo(pipeLineLogFile));
+
+ List processes = ProcessBuilder.startPipeline(Arrays.asList(ls, wc));
+ Process process = processes.get(processes.size() - 1);
+
+ System.out.println("pid:" + process.pid());
+ System.out.println("exitCode:" + process.waitFor());
+
+ Files.lines(pipeLineLogFile.toPath()).forEach(System.out::println);
+ }
+
+ public static File getFile(String filePath) throws IOException {
+ File logFile = new File(filePath);
+ if (!logFile.exists()) {
+ logFile.createNewFile();
+ }
+ return logFile;
+ }
+}
diff --git a/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest9.java b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest9.java
new file mode 100644
index 0000000..6ee7b23
--- /dev/null
+++ b/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process/ProcessBuilderTest9.java
@@ -0,0 +1,34 @@
+package com.wdbyte.os.process;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 运行一个 Java 程序
+ * 等待一定时间后检查状态,未结束则直接杀死进程。
+ *
+ * @author https://www.wdbyte.com
+ */
+public class ProcessBuilderTest9 {
+ private static String BASE_DIR = "/Users/darcy/git/JavaNotes/core-java-modules/core-java-os/src/main/java/com/wdbyte/os/process";
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.directory(new File(BASE_DIR));
+ processBuilder.command("java", "ExecDemo.java");
+ // 把子线程 I/O 输出重定向当前进程
+ processBuilder.inheritIO();
+ Process process = processBuilder.start();
+ // 等待一定时间
+ boolean waitFor = process.waitFor(3, TimeUnit.SECONDS);
+ System.out.println("waitFor:" + waitFor);
+ // 若未退出,杀死子进程
+ if (!waitFor) {
+ process.destroyForcibly();
+ process.waitFor();
+ System.out.println("杀死进程:" + process);
+ }
+
+ }
+}
diff --git a/core-java-modules/core-java-performance-code/src/main/java/com/wdbyte/HashMapKey.java b/core-java-modules/core-java-performance-code/src/main/java/com/wdbyte/HashMapKey.java
index 1fc032e..31e622b 100644
--- a/core-java-modules/core-java-performance-code/src/main/java/com/wdbyte/HashMapKey.java
+++ b/core-java-modules/core-java-performance-code/src/main/java/com/wdbyte/HashMapKey.java
@@ -3,13 +3,18 @@
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OperationsPerInvocation;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
@@ -20,9 +25,12 @@
* @author https://www.wdbyte.com
* @date 2021/12/06
*/
-@State(Scope.Benchmark)
+@State(Scope.Thread)
+@Fork(2)
@Warmup(iterations = 3, time = 3)
@Measurement(iterations = 5, time = 3)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class HashMapKey {
private int size = 1024;
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
index 55a59a8..b3a49a2 100644
--- a/core-java-modules/pom.xml
+++ b/core-java-modules/pom.xml
@@ -14,20 +14,32 @@
pom
- 1.8
- 1.8
+ 21
+ 21
core-java-performance
core-java-8
core-java-9
+ core-java-18
+ core-java-20
+ core-java-21
core-java-performance-code
core-java-io
core-java-string
- core-java-18
core-java-collect
core-java-base
+ core-java-os
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.9.1
+
+
+
+
\ No newline at end of file
diff --git a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode388_LengthLongestPath.java b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode388_LengthLongestPath.java
index 8a41422..46a0ea9 100644
--- a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode388_LengthLongestPath.java
+++ b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode388_LengthLongestPath.java
@@ -6,7 +6,7 @@
* 388. 文件的最长绝对路径
* https://leetcode-cn.com/problems/longest-absolute-file-path/
*
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/20
*/
public class LeetCode388_LengthLongestPath {
diff --git a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode396_MaxRotateFunction.java b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode396_MaxRotateFunction.java
index adbe6e1..2e563ef 100644
--- a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode396_MaxRotateFunction.java
+++ b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode396_MaxRotateFunction.java
@@ -22,7 +22,7 @@
* F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 0 + 2 + 12 + 12 = 26
* 所以 F(0), F(1), F(2), F(3) 中的最大值是 F(3) = 26 。
*
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/22
*/
public class LeetCode396_MaxRotateFunction {
diff --git a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode515_FindLargeValueInEachTreeRow.java b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode515_FindLargeValueInEachTreeRow.java
index 141a534..3560d97 100644
--- a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode515_FindLargeValueInEachTreeRow.java
+++ b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode515_FindLargeValueInEachTreeRow.java
@@ -8,7 +8,7 @@
*
* 515. 在每个树行中找最大值
*
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/06/24
*/
public class LeetCode515_FindLargeValueInEachTreeRow {
diff --git a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode587_OuterTrees.java b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode587_OuterTrees.java
new file mode 100644
index 0000000..ed2a356
--- /dev/null
+++ b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode587_OuterTrees.java
@@ -0,0 +1,48 @@
+package com.wdbyte.leetcode;
+
+/**
+ * https://leetcode-cn.com/problems/erect-the-fence/
+ * 587. 安装栅栏
+ * 在一个二维的花园中,有一些用 (x, y) 坐标表示的树。由于安装费用十分昂贵,你的任务是先用最短的绳子围起
+ * 所有的树。只有当所有的树都被绳子包围时,花园才能围好栅栏。你需要找到正好位于栅栏边界上的树的坐标。
+ *
+ * @author https://www.wdbyte.com
+ * @date 2022/04/23
+ */
+public class LeetCode587_OuterTrees {
+ public static void main(String[] args) {
+ int[][] trees = {{1, 1}, {2, 2}, {2, 0}, {2, 4}, {3, 3}, {4, 2}};
+ System.out.println(multi(trees[2], trees[2], trees[4]));
+ }
+
+ public int[][] outerTrees(int[][] trees) {
+ // 1. 找到最左边的一个点
+ int startX = 0;
+ int startY = 0;
+ for (int[] tree : trees) {
+ int x = tree[0];
+ int y = tree[1];
+ if (x < startX) {
+ startX = x;
+ startY = y;
+ }
+ }
+ // 2. 从最左边的一个点开始,寻找最大角度的点的连线
+ return null;
+ }
+
+ static int[][] sort(int[][] trees) {
+ return trees;
+ }
+
+ //计算叉积,p1,p2,p0都为点
+ static double multi(int[] p1, int[] p2, int[] p0) {
+ double x1, y1, x2, y2;
+ x1 = p1[0] - p0[0];
+ y1 = p1[1] - p0[1];
+ x2 = p2[0] - p0[0];
+ y2 = p2[1] - p0[1];
+ return x1 * y2 - x2 * y1;
+ }
+
+}
diff --git a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode824_ToGoatLatin.java b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode824_ToGoatLatin.java
index 43a4c12..dbe5e05 100644
--- a/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode824_ToGoatLatin.java
+++ b/leetcode/src/main/java/com/wdbyte/leetcode/LeetCode824_ToGoatLatin.java
@@ -4,7 +4,7 @@
* https://leetcode-cn.com/problems/goat-latin/
* 824. 山羊拉丁文
*
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/04/21
*/
public class LeetCode824_ToGoatLatin {
diff --git a/pom.xml b/pom.xml
index 3110d06..b55b3df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,14 +9,18 @@
1.0.0-SNAPSHOT
core-java-modules
- core-java-rate-limiter
- junit5-jupiter-starter
+ tool-java-rate-limiter
+ tool-java-junit5-jupiter-starter
leetcode
tool-java-apache-httpclient
tool-java-object-pool
tool-java-jackson
tool-java-apache-common
tool-java-hotcode
+ tool-java-protobuf
+ tool-java-jcommander
+ tool-java-classloader
+ tool-java-guava
parent-modules
Parent for all java modules
@@ -41,10 +45,5 @@
commons-lang3
${commons-lang3.version}
-
- org.projectlombok
- lombok
- ${lombok.version}
-
diff --git a/spring-ai/spring-mcp-server-manual/.mvn/wrapper/maven-wrapper.properties b/spring-ai/spring-mcp-server-manual/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..8dea6c2
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,3 @@
+wrapperVersion=3.3.4
+distributionType=only-script
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
diff --git a/spring-ai/spring-mcp-server-manual/README.md b/spring-ai/spring-mcp-server-manual/README.md
new file mode 100644
index 0000000..af5c1b2
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/README.md
@@ -0,0 +1,26 @@
+这个基于 Spring Boot 和 Fastjson 的 MCP(Model Context Protocol)服务实现,是一个遵循 JSON-RPC 2.0 规范的轻量级工具服务端,旨在为大语言模型(LLM)提供标准化的外部能力接口 36。
+
+以下是该实现的核心架构与技术特点介绍:
+
+### 1. 核心协议架构
+该实现采用了 MCP 的 Streamable HTTP 传输机制,通过单一的 HTTP POST 端点(/mcp)处理所有交互逻辑 26。
+
+消息格式:所有请求和响应均严格遵循 JSON-RPC 2.0 结构,包含 jsonrpc、id、method 和 params 字段 6。
+生命周期管理:手动实现了 MCP 协议定义的完整链路,包括初始化握手(initialize)、初始化完成通知(notifications/initialized)、工具发现(tools/list)以及工具执行(tools/call) 56。
+### 2. Java 21 技术优化
+利用 Java 21 的现代语法特性极大简化了协议模版代码:
+
+Record 记录类:使用 record 定义 JsonRpcRequest、Tool 和 ToolCallResult 等数据模型。这消除了 Getter/Setter 等样板代码,确保了消息对象的不可变性,并自动支持 JSON 序列化。
+Switch 表达式:在控制器中使用增强的 switch 表达式处理 method 分发。这种方式比传统的 if-else 更具读性,且利用 yield 关键字实现了逻辑的紧凑闭环。
+文本块(Text Blocks):利用 """ 语法定义工具的 JSON Schema。这使得复杂的输入参数描述(如 inputSchema)在代码中能以原始 JSON 格式直观呈现,便于维护 5。
+### 3. 工具定义与执行逻辑
+该服务模拟了一个名为 getWeather 的城市天气查询工具:
+
+工具发现:在 tools/list 阶段,服务端会返回该工具的名称、描述以及基于 JSON Schema 的参数定义(要求必填 city 字符串),以便 LLM 理解如何调用该工具 56。
+参数解析:通过 Fastjson 的 JSONObject 直接处理动态参数。在 tools/call 触发时,程序会从 arguments 映射中提取城市名称,并返回标准化的内容结构。
+响应规范:响应体封装在 content 数组中,并包含 isError 标识,这符合 MCP 对工具执行结果的标准化要求 6。
+### 4. 最佳实践体现
+轻量化:不依赖于复杂的 MCP 官方 SDK,仅通过 Spring Boot 基础框架和 Fastjson 实现,适合快速集成到现有生产微服务中 2。
+无状态处理:服务设计为无状态,符合 MCP Streamable HTTP 的简化模式,便于水平扩展。
+错误处理基础:虽然为简易版,但结构上预留了 isError 字段,允许在工具内部出错时让 LLM 感知并尝试自我修正 6。
+这种实现方式展示了如何通过极简的代码量构建符合开放协议标准的 AI 插件系统,降低了 LLM 与私有数据源及外部工具对接的复杂度 13。
\ No newline at end of file
diff --git a/spring-ai/spring-mcp-server-manual/mvnw b/spring-ai/spring-mcp-server-manual/mvnw
new file mode 100755
index 0000000..bd8896b
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/mvnw
@@ -0,0 +1,295 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.3.4
+#
+# Optional ENV vars
+# -----------------
+# JAVA_HOME - location of a JDK home dir, required when download maven via java source
+# MVNW_REPOURL - repo url base for downloading maven distribution
+# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
+# ----------------------------------------------------------------------------
+
+set -euf
+[ "${MVNW_VERBOSE-}" != debug ] || set -x
+
+# OS specific support.
+native_path() { printf %s\\n "$1"; }
+case "$(uname)" in
+CYGWIN* | MINGW*)
+ [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
+ native_path() { cygpath --path --windows "$1"; }
+ ;;
+esac
+
+# set JAVACMD and JAVACCMD
+set_java_home() {
+ # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
+ if [ -n "${JAVA_HOME-}" ]; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACCMD="$JAVA_HOME/jre/sh/javac"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ JAVACCMD="$JAVA_HOME/bin/javac"
+
+ if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
+ echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
+ echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
+ return 1
+ fi
+ fi
+ else
+ JAVACMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v java
+ )" || :
+ JAVACCMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v javac
+ )" || :
+
+ if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
+ echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
+ return 1
+ fi
+ fi
+}
+
+# hash string like Java String::hashCode
+hash_string() {
+ str="${1:-}" h=0
+ while [ -n "$str" ]; do
+ char="${str%"${str#?}"}"
+ h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
+ str="${str#?}"
+ done
+ printf %x\\n $h
+}
+
+verbose() { :; }
+[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
+
+die() {
+ printf %s\\n "$1" >&2
+ exit 1
+}
+
+trim() {
+ # MWRAPPER-139:
+ # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
+ # Needed for removing poorly interpreted newline sequences when running in more
+ # exotic environments such as mingw bash on Windows.
+ printf "%s" "${1}" | tr -d '[:space:]'
+}
+
+scriptDir="$(dirname "$0")"
+scriptName="$(basename "$0")"
+
+# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
+while IFS="=" read -r key value; do
+ case "${key-}" in
+ distributionUrl) distributionUrl=$(trim "${value-}") ;;
+ distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
+ esac
+done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+
+case "${distributionUrl##*/}" in
+maven-mvnd-*bin.*)
+ MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
+ case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
+ *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
+ :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
+ :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
+ :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
+ *)
+ echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
+ distributionPlatform=linux-amd64
+ ;;
+ esac
+ distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
+ ;;
+maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
+*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+esac
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
+distributionUrlName="${distributionUrl##*/}"
+distributionUrlNameMain="${distributionUrlName%.*}"
+distributionUrlNameMain="${distributionUrlNameMain%-bin}"
+MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
+MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
+
+exec_maven() {
+ unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
+ exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
+}
+
+if [ -d "$MAVEN_HOME" ]; then
+ verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ exec_maven "$@"
+fi
+
+case "${distributionUrl-}" in
+*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
+*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
+esac
+
+# prepare tmp dir
+if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
+ clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
+ trap clean HUP INT TERM EXIT
+else
+ die "cannot create temp dir"
+fi
+
+mkdir -p -- "${MAVEN_HOME%/*}"
+
+# Download and Install Apache Maven
+verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+verbose "Downloading from: $distributionUrl"
+verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+# select .zip or .tar.gz
+if ! command -v unzip >/dev/null; then
+ distributionUrl="${distributionUrl%.zip}.tar.gz"
+ distributionUrlName="${distributionUrl##*/}"
+fi
+
+# verbose opt
+__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
+[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
+
+# normalize http auth
+case "${MVNW_PASSWORD:+has-password}" in
+'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+esac
+
+if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
+ verbose "Found wget ... using wget"
+ wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
+elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
+ verbose "Found curl ... using curl"
+ curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
+elif set_java_home; then
+ verbose "Falling back to use Java to download"
+ javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
+ targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
+ cat >"$javaSource" <<-END
+ public class Downloader extends java.net.Authenticator
+ {
+ protected java.net.PasswordAuthentication getPasswordAuthentication()
+ {
+ return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
+ }
+ public static void main( String[] args ) throws Exception
+ {
+ setDefault( new Downloader() );
+ java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
+ }
+ }
+ END
+ # For Cygwin/MinGW, switch paths to Windows format before running javac and java
+ verbose " - Compiling Downloader.java ..."
+ "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
+ verbose " - Running Downloader.java ..."
+ "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
+fi
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+if [ -n "${distributionSha256Sum-}" ]; then
+ distributionSha256Result=false
+ if [ "$MVN_CMD" = mvnd.sh ]; then
+ echo "Checksum validation is not supported for maven-mvnd." >&2
+ echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ elif command -v sha256sum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ elif command -v shasum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
+ echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ fi
+ if [ $distributionSha256Result = false ]; then
+ echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
+ echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+# unzip and move
+if command -v unzip >/dev/null; then
+ unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
+else
+ tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
+fi
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+actualDistributionDir=""
+
+# First try the expected directory name (for regular distributions)
+if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
+ if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$distributionUrlNameMain"
+ fi
+fi
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if [ -z "$actualDistributionDir" ]; then
+ # enable globbing to iterate over items
+ set +f
+ for dir in "$TMP_DOWNLOAD_DIR"/*; do
+ if [ -d "$dir" ]; then
+ if [ -f "$dir/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$(basename "$dir")"
+ break
+ fi
+ fi
+ done
+ set -f
+fi
+
+if [ -z "$actualDistributionDir" ]; then
+ verbose "Contents of $TMP_DOWNLOAD_DIR:"
+ verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
+ die "Could not find Maven distribution directory in extracted archive"
+fi
+
+verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+clean || :
+exec_maven "$@"
diff --git a/spring-ai/spring-mcp-server-manual/mvnw.cmd b/spring-ai/spring-mcp-server-manual/mvnw.cmd
new file mode 100644
index 0000000..92450f9
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/mvnw.cmd
@@ -0,0 +1,189 @@
+<# : batch portion
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.3.4
+@REM
+@REM Optional ENV vars
+@REM MVNW_REPOURL - repo url base for downloading maven distribution
+@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
+@REM ----------------------------------------------------------------------------
+
+@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
+@SET __MVNW_CMD__=
+@SET __MVNW_ERROR__=
+@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
+@SET PSModulePath=
+@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
+ IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
+)
+@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
+@SET __MVNW_PSMODULEP_SAVE=
+@SET __MVNW_ARG0_NAME__=
+@SET MVNW_USERNAME=
+@SET MVNW_PASSWORD=
+@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
+@echo Cannot start maven from wrapper >&2 && exit /b 1
+@GOTO :EOF
+: end batch / begin powershell #>
+
+$ErrorActionPreference = "Stop"
+if ($env:MVNW_VERBOSE -eq "true") {
+ $VerbosePreference = "Continue"
+}
+
+# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
+$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
+if (!$distributionUrl) {
+ Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+}
+
+switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
+ "maven-mvnd-*" {
+ $USE_MVND = $true
+ $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
+ $MVN_CMD = "mvnd.cmd"
+ break
+ }
+ default {
+ $USE_MVND = $false
+ $MVN_CMD = $script -replace '^mvnw','mvn'
+ break
+ }
+}
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+if ($env:MVNW_REPOURL) {
+ $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+ $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
+}
+$distributionUrlName = $distributionUrl -replace '^.*/',''
+$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
+
+$MAVEN_M2_PATH = "$HOME/.m2"
+if ($env:MAVEN_USER_HOME) {
+ $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
+}
+
+if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
+ New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
+}
+
+$MAVEN_WRAPPER_DISTS = $null
+if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
+ $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
+} else {
+ $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
+}
+
+$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
+
+if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
+ Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+ exit $?
+}
+
+if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
+ Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
+}
+
+# prepare tmp dir
+$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
+$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
+$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
+trap {
+ if ($TMP_DOWNLOAD_DIR.Exists) {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+ }
+}
+
+New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
+
+# Download and Install Apache Maven
+Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+Write-Verbose "Downloading from: $distributionUrl"
+Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+$webclient = New-Object System.Net.WebClient
+if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
+ $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
+}
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
+if ($distributionSha256Sum) {
+ if ($USE_MVND) {
+ Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
+ }
+ Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
+ if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
+ Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
+ }
+}
+
+# unzip and move
+Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+$actualDistributionDir = ""
+
+# First try the expected directory name (for regular distributions)
+$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
+$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
+if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
+ $actualDistributionDir = $distributionUrlNameMain
+}
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if (!$actualDistributionDir) {
+ Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
+ $testPath = Join-Path $_.FullName "bin/$MVN_CMD"
+ if (Test-Path -Path $testPath -PathType Leaf) {
+ $actualDistributionDir = $_.Name
+ }
+ }
+}
+
+if (!$actualDistributionDir) {
+ Write-Error "Could not find Maven distribution directory in extracted archive"
+}
+
+Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
+try {
+ Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
+} catch {
+ if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
+ Write-Error "fail to move MAVEN_HOME"
+ }
+} finally {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+}
+
+Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
diff --git a/spring-ai/spring-mcp-server-manual/pom.xml b/spring-ai/spring-mcp-server-manual/pom.xml
new file mode 100644
index 0000000..1e9f19e
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 4.0.1
+
+
+ com.wdbyte.ai.mcp.manual
+ spring-mcp-server-manual
+ 0.0.1-SNAPSHOT
+ spring-mcp-server-manual
+ spring-mcp-server-manual
+
+ 21
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webmvc
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.60
+ compile
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-ai/spring-mcp-server-manual/src/main/java/com/wdbyte/ai/mcp/manual/McpWeatherController.java b/spring-ai/spring-mcp-server-manual/src/main/java/com/wdbyte/ai/mcp/manual/McpWeatherController.java
new file mode 100644
index 0000000..76f2cb8
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/src/main/java/com/wdbyte/ai/mcp/manual/McpWeatherController.java
@@ -0,0 +1,119 @@
+package com.wdbyte.ai.mcp.manual;
+
+import java.util.List;
+import java.util.Map;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONWriter.Feature;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/mcp")
+public class McpWeatherController {
+
+ private static final Logger log = LoggerFactory.getLogger(McpWeatherController.class);
+
+ // 1. 静态化工具定义,使 tools/list 极其简洁
+ private static final List AVAILABLE_TOOLS = List.of(
+ new Tool("getWeather", "获取指定城市的天气预报",
+ JSONObject.parseObject("""
+ {
+ "type": "object",
+ "properties": { "city": { "type": "string", "description": "城市名" } },
+ "required": ["city"],
+ "additionalProperties": false
+ }
+ """))
+ );
+
+ @PostMapping(consumes = "application/json", produces = "application/json")
+ public ResponseEntity> handleMcpRequest(@RequestBody JsonRpcRequest request) {
+ Object id = request.id();
+
+ var response = switch (request.method()) {
+ case "initialize" -> ok(id, new InitializeResult());
+ case "notifications/initialized" -> accepted();
+ case "ping" -> ok(id, Map.of());
+ case "tools/list" -> ok(id, Map.of("tools", AVAILABLE_TOOLS));
+ case "tools/call" -> handleToolCall(id, request.params());
+ default -> ResponseEntity.notFound().build();
+ };
+ log.info("\nrequest: {}\nresponse: {}", JSON.toJSONString(request), JSON.toJSONString(response.getBody()));
+ return response;
+ }
+
+ /**
+ * 优雅处理工具调用:直接通过 JSONObject 转换,无需 String 二次中转
+ */
+ private ResponseEntity> handleToolCall(Object id, JSONObject params) {
+ if (params == null) return badRequest();
+
+ var callParams = params.toJavaObject(ToolCallParams.class);
+
+ // 使用 switch 处理多工具扩展性更好
+ return switch (callParams.name()) {
+ case "getWeather" -> {
+ String city = String.valueOf(callParams.arguments().getOrDefault("city", "未知城市"));
+ yield ok(id, new ToolCallResult(city + "今日雷暴雨,建议居家"));
+ }
+ default -> badRequest();
+ };
+ }
+
+ // --- 辅助方法 ---
+ private static ResponseEntity ok(Object id, Object result) {
+ return ResponseEntity.ok(new JsonRpcResponse(id, result));
+ }
+
+ private static ResponseEntity accepted() {
+ return ResponseEntity.status(202).build();
+ }
+
+ private static ResponseEntity badRequest() {
+ return ResponseEntity.badRequest().build();
+ }
+
+ // --- MCP 协议 Records (Java 21) ---
+
+ // 将 params 定义为 JSONObject,方便后续 toJavaObject 转换
+ public record JsonRpcRequest(String jsonrpc, Object id, String method, JSONObject params) {}
+
+ public record JsonRpcResponse(String jsonrpc, Object id, Object result) {
+ public JsonRpcResponse(Object id, Object result) {
+ this("2.0", id, result);
+ }
+ }
+
+ // 初始化结果模型
+ public record InitializeResult(String protocolVersion, Capabilities capabilities, ServerInfo serverInfo) {
+ public InitializeResult() {
+ this("2025-06-18", new Capabilities(new Tools(false)), new ServerInfo("mcp-weather-server", "1.0.0"));
+ }
+ }
+
+ public record ServerInfo(String name, String version) {}
+ public record Capabilities(Tools tools) {}
+ public record Tools(boolean listChanged) {}
+
+ // 工具定义模型
+ public record Tool(String name, String description, Object inputSchema) {}
+
+ // 工具调用参数模型
+ public record ToolCallParams(String name, Map arguments) {}
+
+ // 响应内容模型
+ public record Content(String type, String text) {
+ public Content(String text) { this("text", text); }
+ }
+
+ public record ToolCallResult(List content, boolean isError) {
+ public ToolCallResult(String text) {
+ this(List.of(new Content(text)), false);
+ }
+ }
+}
diff --git a/spring-ai/spring-mcp-server-manual/src/main/java/com/wdbyte/ai/mcp/manual/SpringMcpServerManualApplication.java b/spring-ai/spring-mcp-server-manual/src/main/java/com/wdbyte/ai/mcp/manual/SpringMcpServerManualApplication.java
new file mode 100644
index 0000000..48f4ffe
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/src/main/java/com/wdbyte/ai/mcp/manual/SpringMcpServerManualApplication.java
@@ -0,0 +1,13 @@
+package com.wdbyte.ai.mcp.manual;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringMcpServerManualApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringMcpServerManualApplication.class, args);
+ }
+
+}
diff --git a/spring-ai/spring-mcp-server-manual/src/main/resources/application.properties b/spring-ai/spring-mcp-server-manual/src/main/resources/application.properties
new file mode 100644
index 0000000..bbc9400
--- /dev/null
+++ b/spring-ai/spring-mcp-server-manual/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.application.name=spring-mcp-server-manual
diff --git a/springboot/springboot-hello/.mvn/wrapper/maven-wrapper.jar b/springboot/springboot-hello/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..cb28b0e
Binary files /dev/null and b/springboot/springboot-hello/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/springboot/springboot-hello/.mvn/wrapper/maven-wrapper.properties b/springboot/springboot-hello/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..5f0536e
--- /dev/null
+++ b/springboot/springboot-hello/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/springboot/springboot-hello/README.md b/springboot/springboot-hello/README.md
new file mode 100644
index 0000000..c038db4
--- /dev/null
+++ b/springboot/springboot-hello/README.md
@@ -0,0 +1 @@
+# Srping Boot 简单 Web 接口
diff --git a/springboot/springboot-hello/mvnw b/springboot/springboot-hello/mvnw
new file mode 100755
index 0000000..66df285
--- /dev/null
+++ b/springboot/springboot-hello/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/springboot/springboot-hello/mvnw.cmd b/springboot/springboot-hello/mvnw.cmd
new file mode 100644
index 0000000..95ba6f5
--- /dev/null
+++ b/springboot/springboot-hello/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/springboot/springboot-hello/pom.xml b/springboot/springboot-hello/pom.xml
new file mode 100644
index 0000000..343a330
--- /dev/null
+++ b/springboot/springboot-hello/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.3
+
+
+ com.wdbyte
+ springboot-hello
+ 0.0.1-SNAPSHOT
+ springboot-hello
+ Demo project for Spring Boot
+
+ 21
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/springboot/springboot-hello/src/main/java/com/wdbyte/start/HelloController.java b/springboot/springboot-hello/src/main/java/com/wdbyte/start/HelloController.java
new file mode 100644
index 0000000..e887c46
--- /dev/null
+++ b/springboot/springboot-hello/src/main/java/com/wdbyte/start/HelloController.java
@@ -0,0 +1,20 @@
+package com.wdbyte.start;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@RestController
+public class HelloController {
+
+ @GetMapping("/hello")
+ public String hello(String username) {
+ if (username == null) {
+ return "Hello,Who are you?";
+ }
+ return "Hello," + username;
+ }
+
+}
diff --git a/springboot/springboot-hello/src/main/java/com/wdbyte/start/SpringBootApp.java b/springboot/springboot-hello/src/main/java/com/wdbyte/start/SpringBootApp.java
new file mode 100644
index 0000000..6f46204
--- /dev/null
+++ b/springboot/springboot-hello/src/main/java/com/wdbyte/start/SpringBootApp.java
@@ -0,0 +1,16 @@
+package com.wdbyte.start;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@SpringBootApplication
+public class SpringBootApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootApp.class, args);
+ }
+
+}
diff --git a/springboot/springboot-hello/src/main/resources/application.properties b/springboot/springboot-hello/src/main/resources/application.properties
new file mode 100644
index 0000000..a3ac65c
--- /dev/null
+++ b/springboot/springboot-hello/src/main/resources/application.properties
@@ -0,0 +1 @@
+server.port=8080
\ No newline at end of file
diff --git a/springboot/springboot-sqlite-jpa/.mvn/wrapper/maven-wrapper.jar b/springboot/springboot-sqlite-jpa/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..cb28b0e
Binary files /dev/null and b/springboot/springboot-sqlite-jpa/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/springboot/springboot-sqlite-jpa/.mvn/wrapper/maven-wrapper.properties b/springboot/springboot-sqlite-jpa/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..5f0536e
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/springboot/springboot-sqlite-jpa/README.md b/springboot/springboot-sqlite-jpa/README.md
new file mode 100644
index 0000000..5be62f4
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/README.md
@@ -0,0 +1,42 @@
+# Srping Boot + JPA + Sqlite
+
+使用 **Spring Boot** 可以快速的创建一个基于Spring 的、独立的、生产级的应用程序,并且可以直接运行。Spring Boot 采用习惯性配置,整合大量 Spring 组建和第三方库,让你只需要少量的修改就可以轻松上手。
+
+- [Spring Boot 系列(一)Spring Boot 入门篇](https://www.wdbyte.com/2019/01/springboot/springboot01-quick-start/)
+- [Spring Boot 系列(二)Spring Boot 配置文件](https://www.wdbyte.com/2019/01/springboot/springboot01-config/)
+- [Spring Boot 系列(三)Spring Boot 自动配置](https://www.wdbyte.com/2019/01/springboot/springboot03-auto-config/)
+- [Spring Boot 系列(四)Spring Boot 日志框架](https://www.wdbyte.com/2019/01/springboot/springboot04-log/)
+- [Spring Boot 系列(五)Web 开发之静态资源和模版引擎](https://www.wdbyte.com/2019/02/springboot/springboot-05-web-static-template/)
+- [Spring Boot 系列(六)Web 开发之拦截器和三大组件](https://www.wdbyte.com/2019/02/springboot/springboot-06-web-filter-apo-webbase/)
+- [Spring Boot 系列(七)Web 开发之异常错误处理机制剖析](https://www.wdbyte.com/2019/02/springboot/springboot-07-web-exception/)
+- [Spring Boot 系列(八)动态 Banner 与图片转字符图案的手动实现](https://www.wdbyte.com/2019/02/springboot/springboot-08-banner/)
+- [Spring Boot 系列(九)使用 Spring JDBC 和 Druid 数据源监控](https://www.wdbyte.com/2019/02/springboot/springboot-09-data-jdbc/)
+- [Spring Boot 系列(十)使用 Spring data jpa 访问数据库](https://www.wdbyte.com/2019/03/springboot/springboot-10-data-jpa/)
+- [Spring Boot 系列(十一)使用 Mybatis(自动生成插件) 访问数据库](https://www.wdbyte.com/2019/03/springboot/springboot-11-data-mybatis/)
+- [Spring Boot 系列(十二)使用 Mybatis 集成 pagehelper 分页插件和 mapper 插件](https://www.wdbyte.com/2019/03/springboot/springboot-12-data-mybatis-page/)
+- [Spring Boot 系列(十三)使用邮件服务](https://www.wdbyte.com/2019/03/springboot/springboot-13-email/)
+- [Spring Boot 系列(十四)迅速启用 HTTPS 加密你的网站](https://www.wdbyte.com/2019/08/springboot/springboot-14-https/)
+- [Spring Boot 系列(十五)如何编写自己的 Springboot starter](https://www.wdbyte.com/2019/11/springboot/springboot-15-my-starter/)
+- [Spring Boot 系列(十六)你真的了解 Swagger 文档吗?](https://www.wdbyte.com/2019/11/springboot/springboot-16-web-swagger/)
+- [Spring Boot 系列(十七)迅速使用 Spring Boot Admin 监控你的 Spring Boot 程序](https://www.wdbyte.com/2019/12/springboot/springboot-17-admin/)
+- [Spring Boot 系列(十八)最详细的 Spring Boot 多模块开发与排坑指南](https://www.wdbyte.com/2020/03/springboot/springboot-18-module/)
+- [Spring Boot 系列(十九)SpringBoot 的多数据源配置](https://www.wdbyte.com/2020/12/springboot/springboot-multiple-datasource/)
+- [Spring Boot 系列(二十)Spring Boot,JPA与SQLite 的快速启动](https://www.wdbyte.com/springboot/sqlite/)
+-
+### Reference Documentation
+For further reference, please consider the following sections:
+
+* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
+* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.2.3/maven-plugin/reference/html/)
+* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.2.3/maven-plugin/reference/html/#build-image)
+* [Spring Web](https://docs.spring.io/spring-boot/docs/3.2.3/reference/htmlsingle/index.html#web)
+* [Spring Data JPA](https://docs.spring.io/spring-boot/docs/3.2.3/reference/htmlsingle/index.html#data.sql.jpa-and-spring-data)
+
+### Guides
+The following guides illustrate how to use some features concretely:
+
+* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
+* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
+* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)
+* [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/)
+
diff --git a/springboot/springboot-sqlite-jpa/mvnw b/springboot/springboot-sqlite-jpa/mvnw
new file mode 100755
index 0000000..66df285
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/springboot/springboot-sqlite-jpa/mvnw.cmd b/springboot/springboot-sqlite-jpa/mvnw.cmd
new file mode 100644
index 0000000..95ba6f5
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/springboot/springboot-sqlite-jpa/pom.xml b/springboot/springboot-sqlite-jpa/pom.xml
new file mode 100644
index 0000000..47d85ed
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/pom.xml
@@ -0,0 +1,81 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.3
+
+
+ com.wdbyte
+ springboot-sqlite-jpa
+ 0.0.1-SNAPSHOT
+ springboot-sqlite-jpa
+ Demo project for Spring Boot
+
+ 21
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-community-dialects
+ 6.4.3.Final
+
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.45.1.0
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.apache.commons
+ commons-lang3
+ 3.13.0
+
+
+ commons-codec
+ commons-codec
+ 1.16.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
diff --git a/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/SpringBootSqliteApp.java b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/SpringBootSqliteApp.java
new file mode 100644
index 0000000..f54d63a
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/SpringBootSqliteApp.java
@@ -0,0 +1,16 @@
+package com.wdbyte.springsqlite;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@SpringBootApplication
+public class SpringBootSqliteApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootSqliteApp.class, args);
+ }
+
+}
diff --git a/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/controller/SqliteController.java b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/controller/SqliteController.java
new file mode 100644
index 0000000..b78d228
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/controller/SqliteController.java
@@ -0,0 +1,68 @@
+package com.wdbyte.springsqlite.controller;
+
+import java.time.LocalDateTime;
+
+import com.wdbyte.springsqlite.model.WebsiteUser;
+import com.wdbyte.springsqlite.repository.WebsiteUserRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@Slf4j
+@RestController
+public class SqliteController {
+
+ @Autowired
+ private WebsiteUserRepository userRepository;
+
+ @GetMapping("/sqlite/init")
+ public String init() {
+ for (int i = 0; i < 10; i++) {
+ WebsiteUser websiteUser = new WebsiteUser();
+ // 随机4个字母
+ websiteUser.setUsername(RandomStringUtils.randomAlphabetic(4));
+ // 随机16个字符用于密码加盐加密
+ websiteUser.setSalt(RandomStringUtils.randomAlphanumeric(16));
+ String password = "123456";
+ // 密码存储 = md5(密码+盐)
+ password = password + websiteUser.getSalt();
+ websiteUser.setPassword(DigestUtils.md5Hex(password));
+ websiteUser.setCreatedAt(LocalDateTime.now());
+ websiteUser.setUpdatedAt(LocalDateTime.now());
+ websiteUser.setStatus("active");
+ WebsiteUser saved = userRepository.save(websiteUser);
+ log.info("init user {}", saved.getUsername());
+ }
+ return "init success";
+ }
+
+ @GetMapping("/sqlite/find")
+ public String findByUsername(String username) {
+ WebsiteUser websiteUser = userRepository.findByUsername(username);
+ if (websiteUser == null) {
+ return null;
+ }
+ return websiteUser.toString();
+ }
+
+ @GetMapping("/sqlite/login")
+ public String findByUsername(String username, String password) {
+ WebsiteUser websiteUser = userRepository.findByUsername(username);
+ if (websiteUser == null) {
+ return "login failed";
+ }
+ password = password + websiteUser.getSalt();
+ if (StringUtils.equals(DigestUtils.md5Hex(password), websiteUser.getPassword())) {
+ return "login succeeded";
+ } else {
+ return "login failed";
+ }
+ }
+}
diff --git a/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/model/WebsiteUser.java b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/model/WebsiteUser.java
new file mode 100644
index 0000000..264eec0
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/model/WebsiteUser.java
@@ -0,0 +1,43 @@
+package com.wdbyte.springsqlite.model;
+
+import java.time.LocalDateTime;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Entity
+@Getter
+@Setter
+@ToString
+@Table(name = "website_user")
+public class WebsiteUser {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Integer id;
+
+ @Column(name = "username", nullable = false, unique = true, length = 64)
+ private String username;
+
+ @Column(name = "password", nullable = false, length = 255)
+ private String password;
+
+ @Column(name = "salt", nullable = false, length = 16)
+ private String salt;
+
+ @Column(name = "status", nullable = false, length = 16, columnDefinition = "VARCHAR(16) DEFAULT 'active'")
+ private String status;
+
+ @Column(name = "created_at", nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private LocalDateTime createdAt;
+
+ @Column(name = "updated_at", nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private LocalDateTime updatedAt;
+}
diff --git a/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/repository/WebsiteUserRepository.java b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/repository/WebsiteUserRepository.java
new file mode 100644
index 0000000..12b6af0
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/src/main/java/com/wdbyte/springsqlite/repository/WebsiteUserRepository.java
@@ -0,0 +1,16 @@
+package com.wdbyte.springsqlite.repository;
+
+import com.wdbyte.springsqlite.model.WebsiteUser;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface WebsiteUserRepository extends CrudRepository {
+
+ /**
+ * 根据 username 查询数据
+ * @param name
+ * @return
+ */
+ WebsiteUser findByUsername(String name);
+}
\ No newline at end of file
diff --git a/springboot/springboot-sqlite-jpa/src/main/resources/application.properties b/springboot/springboot-sqlite-jpa/src/main/resources/application.properties
new file mode 100644
index 0000000..3ee254a
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.datasource.url=jdbc:sqlite:springboot-sqlite-jpa.db
+spring.datasource.driver-class-name=org.sqlite.JDBC
+# JPA Properties
+spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
+# create ?????????update?????????
+spring.jpa.hibernate.ddl-auto=update
+spring.jpa.show-sql=true
\ No newline at end of file
diff --git a/springboot/springboot-sqlite-jpa/src/test/java/com/wdbyte/springbootsqlitejpa/SpringbootSqliteJpaApplicationTests.java b/springboot/springboot-sqlite-jpa/src/test/java/com/wdbyte/springbootsqlitejpa/SpringbootSqliteJpaApplicationTests.java
new file mode 100644
index 0000000..7d48850
--- /dev/null
+++ b/springboot/springboot-sqlite-jpa/src/test/java/com/wdbyte/springbootsqlitejpa/SpringbootSqliteJpaApplicationTests.java
@@ -0,0 +1,13 @@
+package com.wdbyte.springbootsqlitejpa;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class SpringbootSqliteJpaApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/.mvn/wrapper/maven-wrapper.jar b/springboot/springboot-weixin-qrcode-login/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..cb28b0e
Binary files /dev/null and b/springboot/springboot-weixin-qrcode-login/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/springboot/springboot-weixin-qrcode-login/.mvn/wrapper/maven-wrapper.properties b/springboot/springboot-weixin-qrcode-login/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..5f0536e
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/springboot/springboot-weixin-qrcode-login/README.md b/springboot/springboot-weixin-qrcode-login/README.md
new file mode 100644
index 0000000..30d0f64
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/README.md
@@ -0,0 +1 @@
+# Srping Boot 微信扫码登录示例
diff --git a/springboot/springboot-weixin-qrcode-login/mvnw b/springboot/springboot-weixin-qrcode-login/mvnw
new file mode 100755
index 0000000..66df285
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/springboot/springboot-weixin-qrcode-login/mvnw.cmd b/springboot/springboot-weixin-qrcode-login/mvnw.cmd
new file mode 100644
index 0000000..95ba6f5
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/springboot/springboot-weixin-qrcode-login/pom.xml b/springboot/springboot-weixin-qrcode-login/pom.xml
new file mode 100644
index 0000000..4c1a316
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/pom.xml
@@ -0,0 +1,98 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.3
+
+
+ com.wdbyte
+ springboot-weixin-qrcode-login
+ 0.0.1-SNAPSHOT
+ springboot-weixin-qrcode-login
+ Demo project for Spring Boot
+
+ 21
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ 2.15.2
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.14.0
+
+
+
+ commons-codec
+ commons-codec
+ 1.16.0
+
+
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+ 5.1.3
+
+
+
+ org.apache.httpcomponents.client5
+ httpclient5-fluent
+ 5.1.3
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.45
+
+
+
+ com.google.guava
+ guava
+ 33.0.0-jre
+
+
+
+
+ com.auth0
+ java-jwt
+ 4.4.0
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/SpringBootApp.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/SpringBootApp.java
new file mode 100644
index 0000000..5720502
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/SpringBootApp.java
@@ -0,0 +1,18 @@
+package com.wdbyte.weixin;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@SpringBootApplication
+@ServletComponentScan(basePackages = "com.wdbyte.weixin.config")
+public class SpringBootApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootApp.class, args);
+ }
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/config/JwtFilter.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/config/JwtFilter.java
new file mode 100644
index 0000000..03de5c5
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/config/JwtFilter.java
@@ -0,0 +1,91 @@
+package com.wdbyte.weixin.config;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.auth0.jwt.interfaces.Claim;
+import com.wdbyte.weixin.util.ApiResultUtil;
+import com.wdbyte.weixin.util.JwtUtil;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.annotation.WebFilter;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * JWT过滤器,拦截 /user/* 请求
+ */
+@Slf4j
+@WebFilter(filterName = "JwtFilter", urlPatterns = {"/user/*"})
+public class JwtFilter implements Filter {
+ private static List EXCLUDE_PATH_LIST = new ArrayList<>();
+
+ static {
+ EXCLUDE_PATH_LIST.add("/user/qrcode");
+ EXCLUDE_PATH_LIST.add("/user/login/qrcode");
+ EXCLUDE_PATH_LIST.add("/weixin/check");
+ }
+
+ private JwtUtil jwtUtil;
+
+ public JwtFilter(JwtUtil jwtUtil) {
+ this.jwtUtil = jwtUtil;
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException {
+
+ final HttpServletRequest request = (HttpServletRequest)req;
+ final HttpServletResponse response = (HttpServletResponse)res;
+ log.info("session id:{}", request.getRequestedSessionId());
+
+ response.setCharacterEncoding("UTF-8");
+ String path = request.getRequestURI();
+ for (String excludePath : EXCLUDE_PATH_LIST) {
+ if (excludePath.startsWith(path)) {
+ chain.doFilter(request, response);
+ return;
+ }
+ }
+ // 除OPTIONS外,其他请求应由JWT进行检查
+ if ("OPTIONS".equals(request.getMethod())) {
+ response.setStatus(HttpServletResponse.SC_OK);
+ chain.doFilter(request, response);
+ return;
+ }
+
+ //获取请求头里的token
+ String authorization = request.getHeader("Authorization");
+ if (authorization == null || !StringUtils.startsWith(authorization, "Bearer ")) {
+ response.getWriter().write(ApiResultUtil.error("authentication failed"));
+ return;
+ }
+ authorization = StringUtils.replaceOnce(authorization, "Bearer ", StringUtils.EMPTY);
+ Map userData = jwtUtil.verifyToken(authorization);
+ if (userData == null) {
+ response.getWriter().write(ApiResultUtil.error("authentication failed"));
+ return;
+ }
+ String openId = userData.get(JwtUtil.OPEN_ID).asString();
+ //拦截器 拿到用户信息,放到request中
+ request.setAttribute(JwtUtil.OPEN_ID, openId);
+ chain.doFilter(req, res);
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
\ No newline at end of file
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/controller/WeixinServerController.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/controller/WeixinServerController.java
new file mode 100644
index 0000000..95740bc
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/controller/WeixinServerController.java
@@ -0,0 +1,51 @@
+package com.wdbyte.weixin.controller;
+
+import com.wdbyte.weixin.service.WeixinUserService;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@Slf4j
+@RestController
+public class WeixinServerController {
+
+ @Autowired
+ private WeixinUserService weixinUserService;
+
+ @GetMapping(value = "/weixin/check")
+ public String weixinCheck(HttpServletRequest request) {
+ String signature = request.getParameter("signature");
+ String timestamp = request.getParameter("timestamp");
+ String nonce = request.getParameter("nonce");
+ String echostr = request.getParameter("echostr");
+
+ if (StringUtils.isEmpty(signature) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(nonce)) {
+ return "";
+ }
+ weixinUserService.checkSignature(signature, timestamp, nonce);
+ return echostr;
+ }
+
+ @PostMapping(value = "/weixin/check")
+ public String weixinMsg(@RequestBody String requestBody, @RequestParam("signature") String signature,
+ @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {
+
+ log.debug("requestBody:{}", requestBody);
+ log.debug("signature:{}", signature);
+ log.debug("timestamp:{}", timestamp);
+ log.debug("nonce:{}", nonce);
+
+ weixinUserService.checkSignature(signature, timestamp, nonce);
+ return weixinUserService.handleWeixinMsg(requestBody);
+ }
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/controller/WeixinUserController.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/controller/WeixinUserController.java
new file mode 100644
index 0000000..074022d
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/controller/WeixinUserController.java
@@ -0,0 +1,56 @@
+package com.wdbyte.weixin.controller;
+
+import com.wdbyte.weixin.model.WeixinQrCode;
+import com.wdbyte.weixin.util.ApiResultUtil;
+import com.wdbyte.weixin.util.JwtUtil;
+import com.wdbyte.weixin.util.WeixinApiUtil;
+import com.wdbyte.weixin.util.WeixinQrCodeCacheUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@CrossOrigin(origins = {"https://www.wdbyte.com", "https://bing.wdbyte.com", "http://localhost:8000"})
+@Slf4j
+@RestController
+public class WeixinUserController {
+
+ @Autowired
+ private WeixinApiUtil weixinApiUtil;
+
+ @Autowired
+ private JwtUtil jwtUtil;
+
+ @GetMapping(value = "/user/qrcode")
+ public String getQrCode() {
+ WeixinQrCode qrCode = weixinApiUtil.getQrCode();
+ qrCode.setUrl(null);
+ qrCode.setExpireSeconds(null);
+ return ApiResultUtil.success(qrCode);
+ }
+
+ /**
+ * 校验是否扫描完成
+ * 完成,返回 JWT
+ * 未完成,返回 check faild
+ *
+ * @param ticket
+ * @return
+ */
+ @GetMapping(value = "/user/login/qrcode")
+ public String userLogin(String ticket) {
+ String openId = WeixinQrCodeCacheUtil.get(ticket);
+ if (StringUtils.isNotEmpty(openId)) {
+ log.info("login success,open id:{}", openId);
+ return ApiResultUtil.success(jwtUtil.createToken(openId));
+ }
+ log.info("login error,ticket:{}", ticket);
+ return ApiResultUtil.error("check faild");
+ }
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/ApiResult.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/ApiResult.java
new file mode 100644
index 0000000..83c4279
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/ApiResult.java
@@ -0,0 +1,31 @@
+package com.wdbyte.weixin.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@Slf4j
+@Getter
+@Setter
+public class ApiResult {
+ private Integer code;
+ private String message;
+ private Object data;
+
+ public ApiResult() {
+ }
+
+ public ApiResult(Integer code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+ public ApiResult(Integer code, String message, Object data) {
+ this.code = code;
+ this.message = message;
+ this.data = data;
+ }
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/ReceiveMessage.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/ReceiveMessage.java
new file mode 100644
index 0000000..38f8d13
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/ReceiveMessage.java
@@ -0,0 +1,58 @@
+package com.wdbyte.weixin.model;
+
+import lombok.Data;
+
+@Data
+public class ReceiveMessage {
+ /**
+ * 开发者微信号
+ */
+ private String toUserName;
+ /**
+ * 发送方账号(一个openid)
+ */
+ private String fromUserName;
+ /**
+ * 消息创建时间(整形)
+ */
+ private String createTime;
+ /**
+ * 消息类型
+ */
+ private String msgType;
+ /**
+ * 文本消息内容
+ */
+ private String content;
+ /**
+ * 消息ID 64位
+ */
+ String msgId;
+ /**
+ * 消息的数据ID 消息来自文章才有
+ */
+ private String msgDataId;
+ /**
+ * 多图文时第几篇文章,从1开始 消息如果来自文章才有
+ */
+ private String idx;
+ /**
+ * 订阅事件 subscribe 订阅 unsbscribe 取消订阅
+ */
+ private String event;
+ /**
+ * 扫码 - ticket
+ */
+ private String ticket;
+
+ public String getReplyTextMsg(String msg) {
+ String xml = "\n"
+ + " \n"
+ + " \n"
+ + " " + System.currentTimeMillis() + "\n"
+ + " \n"
+ + " \n"
+ + " ";
+ return xml;
+ }
+}
\ No newline at end of file
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/WeixinQrCode.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/WeixinQrCode.java
new file mode 100644
index 0000000..66bdf65
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/model/WeixinQrCode.java
@@ -0,0 +1,15 @@
+package com.wdbyte.weixin.model;
+
+import lombok.Data;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@Data
+public class WeixinQrCode {
+
+ private String ticket;
+ private Long expireSeconds;
+ private String url;
+ private String qrCodeUrl;
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/service/WeixinUserService.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/service/WeixinUserService.java
new file mode 100644
index 0000000..2d1cd71
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/service/WeixinUserService.java
@@ -0,0 +1,12 @@
+package com.wdbyte.weixin.service;
+
+/**
+ * @Author 公众号:程序猿阿朗
+ */
+public interface WeixinUserService {
+
+ void checkSignature(String signature, String timestamp, String nonce);
+
+ String handleWeixinMsg(String body);
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/service/impl/WeixinUserServiceImpl.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/service/impl/WeixinUserServiceImpl.java
new file mode 100644
index 0000000..78939d0
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/service/impl/WeixinUserServiceImpl.java
@@ -0,0 +1,69 @@
+package com.wdbyte.weixin.service.impl;
+
+import java.util.Arrays;
+
+import com.wdbyte.weixin.model.ReceiveMessage;
+import com.wdbyte.weixin.service.WeixinUserService;
+import com.wdbyte.weixin.util.WeixinMsgUtil;
+import com.wdbyte.weixin.util.WeixinQrCodeCacheUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author 公众号:程序猿阿朗
+ */
+@Slf4j
+@Service
+public class WeixinUserServiceImpl implements WeixinUserService {
+
+ @Value("${weixin.token}")
+ private String token;
+
+ @Override
+ public void checkSignature(String signature, String timestamp, String nonce) {
+ String[] arr = new String[] {token, timestamp, nonce};
+ Arrays.sort(arr);
+ StringBuilder content = new StringBuilder();
+ for (String str : arr) {
+ content.append(str);
+ }
+ String tmpStr = DigestUtils.sha1Hex(content.toString());
+ if (tmpStr.equals(signature)) {
+ log.info("check success");
+ return;
+ }
+ log.error("check fail");
+ throw new RuntimeException("check fail");
+ }
+
+ @Override
+ public String handleWeixinMsg(String requestBody) {
+ ReceiveMessage receiveMessage = WeixinMsgUtil.msgToReceiveMessage(requestBody);
+ // 扫码登录
+ if (WeixinMsgUtil.isScanQrCode(receiveMessage)) {
+ return handleScanLogin(receiveMessage);
+ }
+ // 关注
+ if (WeixinMsgUtil.isEventAndSubscribe(receiveMessage)) {
+ return receiveMessage.getReplyTextMsg("欢迎关注【程序猿阿朗】公众号");
+ }
+ return receiveMessage.getReplyTextMsg("收到(自动回复)");
+ }
+
+ /**
+ * 处理扫码登录
+ *
+ * @param receiveMessage
+ * @return
+ */
+ private String handleScanLogin(ReceiveMessage receiveMessage) {
+ String qrCodeTicket = WeixinMsgUtil.getQrCodeTicket(receiveMessage);
+ if (WeixinQrCodeCacheUtil.get(qrCodeTicket) == null) {
+ String openId = receiveMessage.getFromUserName();
+ WeixinQrCodeCacheUtil.put(qrCodeTicket, openId);
+ }
+ return receiveMessage.getReplyTextMsg("你已成功登录!");
+ }
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/AesUtils.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/AesUtils.java
new file mode 100644
index 0000000..5c1cd39
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/AesUtils.java
@@ -0,0 +1,64 @@
+package com.wdbyte.weixin.util;
+
+import java.util.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * Java 使用 AES 加密算法进行加密解密
+ */
+@Component
+public class AesUtils {
+
+ /**
+ * 秘钥(需要使用长度为16、24或32的字节数组作为AES算法的密钥,否则就会遇到java.security.InvalidKeyException异常)
+ */
+ @Value("${ase.util.secret}")
+ public String key;
+
+ /**
+ * AES算法加密
+ *
+ * @Param:text原文
+ * @Param:key密钥
+ */
+
+ @SneakyThrows
+ public String aesEncrypt(String text) {
+ // 创建AES加密算法实例(根据传入指定的秘钥进行加密)
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+ SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
+ // 初始化为加密模式,并将密钥注入到算法中
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec);
+ // 将传入的文本加密
+ byte[] encrypted = cipher.doFinal(text.getBytes());
+ //生成密文
+ // 将密文进行Base64编码,方便传输
+ return Base64.getEncoder().encodeToString(encrypted);
+ }
+
+ /**
+ * AES算法解密
+ *
+ * @Param:base64Encrypted密文
+ * @Param:key密钥
+ */
+ public String aesDecrypt(String base64Encrypted) throws Exception {
+ // 创建AES解密算法实例
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+ SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
+
+ // 初始化为解密模式,并将密钥注入到算法中
+ cipher.init(Cipher.DECRYPT_MODE, keySpec);
+ // 将Base64编码的密文解码
+ byte[] encrypted = Base64.getDecoder().decode(base64Encrypted);
+ // 解密
+ byte[] decrypted = cipher.doFinal(encrypted);
+ return new String(decrypted);
+ }
+}
\ No newline at end of file
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/ApiResultUtil.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/ApiResultUtil.java
new file mode 100644
index 0000000..d68f622
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/ApiResultUtil.java
@@ -0,0 +1,29 @@
+package com.wdbyte.weixin.util;
+
+import com.alibaba.fastjson2.JSON;
+
+import com.wdbyte.weixin.model.ApiResult;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class ApiResultUtil {
+
+ private static Integer SUCCESS_CODE = 200;
+ private static String SUCCESS_MESSAGE = "success";
+ private static Integer ERROR_CODE = -1;
+ private static String ERROR_MESSAGE = "error";
+
+ public static String success() {
+ return JSON.toJSONString(new ApiResult(SUCCESS_CODE, SUCCESS_MESSAGE, new Object()));
+ }
+
+ public static String success(Object data) {
+ return JSON.toJSONString(new ApiResult(SUCCESS_CODE, SUCCESS_MESSAGE, data));
+ }
+
+ public static String error(Object data) {
+ return JSON.toJSONString(new ApiResult(ERROR_CODE, ERROR_MESSAGE, data));
+ }
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/HttpUtil.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/HttpUtil.java
new file mode 100644
index 0000000..d536530
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/HttpUtil.java
@@ -0,0 +1,44 @@
+package com.wdbyte.weixin.util;
+
+import java.io.IOException;
+
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.fluent.Request;
+import org.apache.hc.client5.http.fluent.Response;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+public class HttpUtil {
+
+ public static String get(String url) {
+ String result = null;
+ try {
+ Response response = Request.get(url).execute();
+ result = response.returnContent().asString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ public static String post(String url, String jsonBody) {
+ String result = null;
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));
+ try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
+ try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
+ // 获取响应信息
+ result = EntityUtils.toString(response.getEntity());
+ }
+ } catch (IOException | ParseException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/JwtUtil.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/JwtUtil.java
new file mode 100644
index 0000000..581a0a3
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/JwtUtil.java
@@ -0,0 +1,88 @@
+package com.wdbyte.weixin.util;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.auth0.jwt.interfaces.Claim;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import jakarta.annotation.PostConstruct;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * Jwt工具类,生成JWT和认证
+ */
+@Slf4j
+@Component
+public class JwtUtil {
+
+ @Autowired
+ private AesUtils aesUtils;
+
+ @Value("${key.jwt.secret}")
+ public String secret;
+
+ private JWTVerifier verifier;
+
+ @PostConstruct
+ public synchronized void init() {
+ log.info("init jwt verifier");
+ verifier = JWT.require(Algorithm.HMAC256(secret)).build();
+ }
+
+ /**
+ * 过期时间,单位为秒,3天
+ **/
+ private static final long EXPIRATION = 3 * 24 * 3600L;
+ /**
+ * open id
+ */
+ public static final String OPEN_ID = "oid";
+
+ /**
+ * 生成用户token,设置token超时时间
+ */
+ public String createToken(String openId) {
+ Date expireDate = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
+ Map map = new HashMap<>();
+ map.put("alg", "HS256");
+ map.put("typ", "JWT");
+ String token = JWT.create()
+ // 添加头部
+ .withHeader(map)
+ // 可以将基本信息放到claims中
+ .withClaim(OPEN_ID, openId)
+ //超时设置,设置过期的日期
+ .withExpiresAt(expireDate)
+ //签发时间
+ .withIssuedAt(new Date())
+ //SECRET加密
+ .sign(Algorithm.HMAC256(secret));
+ return aesUtils.aesEncrypt(token);
+ }
+
+ /**
+ * 校验token并解析token
+ */
+ public Map verifyToken(String token) {
+ try {
+ token = aesUtils.aesDecrypt(token);
+ DecodedJWT jwt = verifier.verify(token);
+ return jwt.getClaims();
+ } catch (Exception e) {
+ log.error(String.format("verifyToken error,token:%s,msg:%s", token, e.getMessage()), e);
+ if (e instanceof TokenExpiredException) {
+ throw new RuntimeException("jwt verify token error");
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/KeyUtils.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/KeyUtils.java
new file mode 100644
index 0000000..d56ebe0
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/KeyUtils.java
@@ -0,0 +1,24 @@
+package com.wdbyte.weixin.util;
+
+import java.util.UUID;
+
+import org.apache.commons.lang3.RandomStringUtils;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class KeyUtils {
+
+ public synchronized static String key6() {
+ return RandomStringUtils.randomAlphanumeric(6);
+ }
+
+ public synchronized static String key16() {
+ return RandomStringUtils.randomAlphanumeric(16);
+ }
+
+ public static String uuid32() {
+ return UUID.randomUUID().toString().replace("-", "");
+ }
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinApiUtil.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinApiUtil.java
new file mode 100644
index 0000000..6a3f8b0
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinApiUtil.java
@@ -0,0 +1,79 @@
+package com.wdbyte.weixin.util;
+
+import java.net.URI;
+import java.time.LocalDateTime;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+
+import com.wdbyte.weixin.model.WeixinQrCode;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@Slf4j
+@Component
+public class WeixinApiUtil {
+
+ @Value("${weixin.appid}")
+ public String appId;
+
+ @Value("${weixin.appsecret}")
+ public String appSecret;
+
+ private static String QR_CODE_URL_PREFIX = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";
+
+ private static String ACCESS_TOKEN = null;
+ private static LocalDateTime ACCESS_TOKEN_EXPIRE_TIME = null;
+ /**
+ * 二维码 Ticket 过期时间
+ */
+ private static int QR_CODE_TICKET_TIMEOUT = 10 * 60;
+
+ /**
+ * 获取 access token
+ *
+ * @return
+ */
+ public synchronized String getAccessToken() {
+ if (ACCESS_TOKEN != null && ACCESS_TOKEN_EXPIRE_TIME.isAfter(LocalDateTime.now())) {
+ return ACCESS_TOKEN;
+ }
+ String api = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret="
+ + appSecret;
+ String result = HttpUtil.get(api);
+ JSONObject jsonObject = JSON.parseObject(result);
+ ACCESS_TOKEN = jsonObject.getString("access_token");
+ ACCESS_TOKEN_EXPIRE_TIME = LocalDateTime.now().plusSeconds(jsonObject.getLong("expires_in") - 10);
+ return ACCESS_TOKEN;
+ }
+
+ /**
+ * 获取二维码 Ticket
+ *
+ * https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
+ *
+ * @return
+ */
+ public WeixinQrCode getQrCode() {
+ String api = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + getAccessToken();
+ String jsonBody = String.format("{\n"
+ + " \"expire_seconds\": %d,\n"
+ + " \"action_name\": \"QR_STR_SCENE\",\n"
+ + " \"action_info\": {\n"
+ + " \"scene\": {\n"
+ + " \"scene_str\": \"%s\"\n"
+ + " }\n"
+ + " }\n"
+ + "}", QR_CODE_TICKET_TIMEOUT, KeyUtils.uuid32());
+ String result = HttpUtil.post(api, jsonBody);
+ log.info("get qr code params:{}", jsonBody);
+ log.info("get qr code result:{}", result);
+ WeixinQrCode weixinQrCode = JSON.parseObject(result, WeixinQrCode.class);
+ weixinQrCode.setQrCodeUrl(QR_CODE_URL_PREFIX + URI.create(weixinQrCode.getTicket()).toASCIIString());
+ return weixinQrCode;
+ }
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinMsgUtil.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinMsgUtil.java
new file mode 100644
index 0000000..a48c0cb
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinMsgUtil.java
@@ -0,0 +1,67 @@
+package com.wdbyte.weixin.util;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+
+import com.wdbyte.weixin.model.ReceiveMessage;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class WeixinMsgUtil {
+
+ // 事件-关注
+ private static String EVENT_SUBSCRIBE = "subscribe";
+
+ /**
+ * 微信消息转对象
+ *
+ * @param xml
+ * @return
+ */
+ public static ReceiveMessage msgToReceiveMessage(String xml) {
+ JSONObject jsonObject = JSON.parseObject(XmlUtil.xml2json(xml));
+ ReceiveMessage receiveMessage = new ReceiveMessage();
+ receiveMessage.setToUserName(jsonObject.getString("ToUserName"));
+ receiveMessage.setFromUserName(jsonObject.getString("FromUserName"));
+ receiveMessage.setCreateTime(jsonObject.getString("CreateTime"));
+ receiveMessage.setMsgType(jsonObject.getString("MsgType"));
+ receiveMessage.setContent(jsonObject.getString("Content"));
+ receiveMessage.setMsgId(jsonObject.getString("MsgId"));
+ receiveMessage.setEvent(jsonObject.getString("Event"));
+ receiveMessage.setTicket(jsonObject.getString("Ticket"));
+ return receiveMessage;
+ }
+
+ /**
+ * 是否是订阅事件
+ *
+ * @param receiveMessage
+ * @return
+ */
+ public static boolean isEventAndSubscribe(ReceiveMessage receiveMessage) {
+ return StringUtils.equals(receiveMessage.getEvent(), EVENT_SUBSCRIBE);
+ }
+
+ /**
+ * 是否是二维码扫描事件
+ *
+ * @param receiveMessage
+ * @return
+ */
+ public static boolean isScanQrCode(ReceiveMessage receiveMessage) {
+ return StringUtils.isNotEmpty(receiveMessage.getTicket());
+ }
+
+ /**
+ * 获取扫描的二维码 Ticket
+ *
+ * @param receiveMessage
+ * @return
+ */
+ public static String getQrCodeTicket(ReceiveMessage receiveMessage) {
+ return receiveMessage.getTicket();
+ }
+
+}
\ No newline at end of file
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinQrCodeCacheUtil.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinQrCodeCacheUtil.java
new file mode 100644
index 0000000..1e55d9e
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/WeixinQrCodeCacheUtil.java
@@ -0,0 +1,34 @@
+package com.wdbyte.weixin.util;
+
+import java.util.LinkedHashMap;
+
+/**
+ * 微信二维码缓存工具类
+ *
+ * @author https://www.wdbyte.com
+ */
+public class WeixinQrCodeCacheUtil {
+ private static long MAX_CACHE_SIZE = 10000;
+ private static LinkedHashMap QR_CODE_TICKET_MAP = new LinkedHashMap<>();
+
+ /**
+ * 增加一个 Ticket
+ * 首次 put:value 为 ""
+ * 再次 put: value 有 openId,若openId已经存在,则已被扫码
+ *
+ * @param key
+ * @param value
+ */
+ public synchronized static void put(String key, String value) {
+ QR_CODE_TICKET_MAP.put(key, value);
+ if (QR_CODE_TICKET_MAP.size() > MAX_CACHE_SIZE) {
+ String first = QR_CODE_TICKET_MAP.keySet().stream().findFirst().get();
+ QR_CODE_TICKET_MAP.remove(first);
+ }
+ }
+
+ public synchronized static String get(String key) {
+ return QR_CODE_TICKET_MAP.remove(key);
+ }
+
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/XmlUtil.java b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/XmlUtil.java
new file mode 100644
index 0000000..bc56199
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/java/com/wdbyte/weixin/util/XmlUtil.java
@@ -0,0 +1,28 @@
+package com.wdbyte.weixin.util;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@Slf4j
+public class XmlUtil {
+
+ public static String xml2json(String requestBody) {
+ requestBody = StringUtils.trim(requestBody);
+ XmlMapper xmlMapper = new XmlMapper();
+ JsonNode node = null;
+ try {
+ node = xmlMapper.readTree(requestBody.getBytes());
+ ObjectMapper jsonMapper = new ObjectMapper();
+ return jsonMapper.writeValueAsString(node);
+ } catch (Exception e) {
+ log.error("xml 2 json error,msg:" + e.getMessage(), e);
+ }
+ return null;
+ }
+}
diff --git a/springboot/springboot-weixin-qrcode-login/src/main/resources/application.properties b/springboot/springboot-weixin-qrcode-login/src/main/resources/application.properties
new file mode 100644
index 0000000..453f434
--- /dev/null
+++ b/springboot/springboot-weixin-qrcode-login/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+server.port=
+weixin.appid=
+weixin.appsecret=
+weixin.token=
+ase.util.secret=
+key.jwt.secret=
\ No newline at end of file
diff --git a/tool-java-apache-common/src/main/java/com/wdbyte/string/StringUtilsTest.java b/tool-java-apache-common/src/main/java/com/wdbyte/string/StringUtilsTest.java
index fdaedda..51989b2 100644
--- a/tool-java-apache-common/src/main/java/com/wdbyte/string/StringUtilsTest.java
+++ b/tool-java-apache-common/src/main/java/com/wdbyte/string/StringUtilsTest.java
@@ -6,7 +6,7 @@
/**
* apache common lang StringUtils test
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/01
*/
public class StringUtilsTest {
diff --git a/tool-java-classloader/.gitignore b/tool-java-classloader/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/tool-java-classloader/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/tool-java-classloader/pom.xml b/tool-java-classloader/pom.xml
new file mode 100644
index 0000000..3789735
--- /dev/null
+++ b/tool-java-classloader/pom.xml
@@ -0,0 +1,20 @@
+
+
+ 4.0.0
+
+ com.wdbyte
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+ tool-java-classloader
+
+
+ 8
+ 8
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/tool-java-guava/.gitignore b/tool-java-guava/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/tool-java-guava/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/tool-java-guava/pom.xml b/tool-java-guava/pom.xml
new file mode 100644
index 0000000..64e6b94
--- /dev/null
+++ b/tool-java-guava/pom.xml
@@ -0,0 +1,20 @@
+
+
+ 4.0.0
+
+ com.wdbyte
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+ tool-java-guava
+
+
+ 8
+ 8
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/tool-java-hotcode/src/main/java/com/wdbyte/hotcode/HotCode.java b/tool-java-hotcode/src/main/java/com/wdbyte/hotcode/HotCode.java
index 0750444..0838ffb 100644
--- a/tool-java-hotcode/src/main/java/com/wdbyte/hotcode/HotCode.java
+++ b/tool-java-hotcode/src/main/java/com/wdbyte/hotcode/HotCode.java
@@ -1,6 +1,9 @@
package com.wdbyte.hotcode;
+import java.io.IOException;
import java.math.BigDecimal;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -9,7 +12,7 @@
/**
*
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2023/02/20
*/
public class HotCode {
@@ -33,6 +36,10 @@ public static void main(String[] args) {
thread();
// 运行缓慢的方法
runSlowThread();
+ // 读取文件
+ readFile();
+ // 抛出异常
+ exceMethod();
}
/**
@@ -104,6 +111,7 @@ private static void deadThread() {
System.out.println(Thread.currentThread() + " get ResourceB");
try {
Thread.sleep(1000);
+
} catch (InterruptedException e) {
e.printStackTrace();
}
@@ -194,4 +202,45 @@ public static void slow2() throws InterruptedException {
System.out.println(count);
}
+ /**
+ * 不断读取文件
+ */
+ public static void readFile(){
+ new Thread(() -> {
+ Thread.currentThread().setName("read_file_method");
+ while (true){
+ try {
+ byte[] bytes = Files.readAllBytes(Paths.get("/Users/darcy/Downloads/info.txt"));
+ System.out.println(bytes.length);
+ Thread.sleep(100);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }).start();
+ }
+
+ /**
+ * 不断抛出异常
+ */
+ public static void exceMethod() {
+ new Thread(() -> {
+ Thread.currentThread().setName("exce_method");
+ while (true) {
+ try {
+ System.out.println(exce(0));
+ Thread.sleep(200);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }).start();
+ }
+
+ public static int exce(int a){
+ return 10/a;
+ }
+
}
diff --git a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Cat.java b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Cat.java
index 5492a46..be544cd 100644
--- a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Cat.java
+++ b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Cat.java
@@ -1,15 +1,12 @@
package com.wdbyte.jackson;
import com.fasterxml.jackson.annotation.JsonGetter;
-import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;
-import lombok.Data;
/**
* @author https://www.wdbyte.com
* @date 2022/07/17
*/
-@Data
public class Cat {
@JsonSetter(value = "catName")
@@ -21,4 +18,24 @@ public class Cat {
public String getName() {
return name;
}
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public Cat() {
+ }
+
+ public Cat(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
}
diff --git a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Order.java b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Order.java
index 6318eb3..38eb08d 100644
--- a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Order.java
+++ b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Order.java
@@ -1,24 +1,15 @@
package com.wdbyte.jackson;
-import java.time.LocalDateTime;
-import java.util.Date;
-
import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonSetter;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.ToString;
+
+import java.time.LocalDateTime;
+import java.util.Date;
/**
* @author https://www.wdbyte.com
* @date 2022/07/17
*/
-//@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@ToString
public class Order {
@JsonSetter(value = "orderId")
@@ -54,4 +45,22 @@ public LocalDateTime getUpdateTime() {
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
+
+ @Override
+ public String toString() {
+ return "Order{" +
+ "id=" + id +
+ ", createTime=" + createTime +
+ ", updateTime=" + updateTime +
+ '}';
+ }
+
+ public Order() {
+ }
+
+ public Order(Integer id, Date createTime, LocalDateTime updateTime) {
+ this.id = id;
+ this.createTime = createTime;
+ this.updateTime = updateTime;
+ }
}
diff --git a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Person.java b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Person.java
index 3bc1210..b1f2a72 100644
--- a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Person.java
+++ b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Person.java
@@ -2,16 +2,55 @@
import java.util.List;
-import lombok.Data;
-
/**
* @author https://www.wdbyte.com
* @date 2022/07/16
*/
-@Data
public class Person {
private String name;
private Integer age;
private List skillList;
+
+ @Override
+ public String toString() {
+ return "Person{" +
+ "name='" + name + '\'' +
+ ", age=" + age +
+ ", skillList=" + skillList +
+ '}';
+ }
+
+ public Person(String name, Integer age, List skillList) {
+ this.name = name;
+ this.age = age;
+ this.skillList = skillList;
+ }
+
+ public Person() {
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public List getSkillList() {
+ return skillList;
+ }
+
+ public void setSkillList(List skillList) {
+ this.skillList = skillList;
+ }
}
diff --git a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Student.java b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Student.java
index 377253d..f5baec4 100644
--- a/tool-java-jackson/src/main/java/com/wdbyte/jackson/Student.java
+++ b/tool-java-jackson/src/main/java/com/wdbyte/jackson/Student.java
@@ -1,36 +1,20 @@
package com.wdbyte.jackson;
-import java.util.HashMap;
-import java.util.Map;
-
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.google.common.collect.Maps;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
+
+import java.util.HashMap;
+import java.util.Map;
/**
* @author https://www.wdbyte.com
* @date 2022/07/17
*/
-@ToString
-@AllArgsConstructor
-@NoArgsConstructor
public class Student {
- @Getter
- @Setter
private String name;
- @Getter
- @Setter
private Integer age;
- @Getter
- @Setter
private Map diyMap = new HashMap<>();
@JsonAnyGetter
@@ -45,4 +29,55 @@ public void otherField(String key, String value) {
this.diyMap.put(key, value);
}
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public Map getDiyMap() {
+ return diyMap;
+ }
+
+ public void setDiyMap(Map diyMap) {
+ this.diyMap = diyMap;
+ }
+
+ public Map getInitMap() {
+ return initMap;
+ }
+
+ public void setInitMap(Map initMap) {
+ this.initMap = initMap;
+ }
+
+ public Student() {
+ }
+
+ public Student(String name, Integer age, Map diyMap, Map initMap) {
+ this.name = name;
+ this.age = age;
+ this.diyMap = diyMap;
+ this.initMap = initMap;
+ }
+
+ @Override
+ public String toString() {
+ return "Student{" +
+ "name='" + name + '\'' +
+ ", age=" + age +
+ ", diyMap=" + diyMap +
+ ", initMap=" + initMap +
+ '}';
+ }
}
diff --git a/tool-java-jcommander/.gitignore b/tool-java-jcommander/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/tool-java-jcommander/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/tool-java-jcommander/README.md b/tool-java-jcommander/README.md
new file mode 100644
index 0000000..d52fb9b
--- /dev/null
+++ b/tool-java-jcommander/README.md
@@ -0,0 +1,4 @@
+## tool-java-jcommander
+
+### 相关文章
+- [使用 JCommander 解析命令行参数](https://www.wdbyte.com/tool/jcommander/)
diff --git a/tool-java-jcommander/pom.xml b/tool-java-jcommander/pom.xml
new file mode 100644
index 0000000..cb92565
--- /dev/null
+++ b/tool-java-jcommander/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+ com.wdbyte
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+ tool-java-jcommander
+
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+ com.beust
+ jcommander
+ 1.82
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.1.0
+
+
+
+ com.wdbyte.jcommander.GitApp
+
+
+
+
+ jar-with-dependencies
+
+
+ git-app
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/FilePathConverter.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/FilePathConverter.java
new file mode 100644
index 0000000..bf88b62
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/FilePathConverter.java
@@ -0,0 +1,25 @@
+package com.wdbyte.jcommander;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.beust.jcommander.IStringConverter;
+import com.beust.jcommander.ParameterException;
+
+/**
+ *
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class FilePathConverter implements IStringConverter {
+
+ @Override
+ public Path convert(String filePath) {
+ Path path = Paths.get(filePath);
+ if (Files.exists(path)) {
+ return path;
+ }
+ throw new ParameterException(String.format("文件不存在,path:%s", filePath));
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitApp.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitApp.java
new file mode 100644
index 0000000..20203c7
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitApp.java
@@ -0,0 +1,65 @@
+package com.wdbyte.jcommander;
+
+import java.nio.file.Path;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.ParameterException;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Git APP
+ *
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+public class GitApp {
+ private static GitCommandOptions commandOptions = new GitCommandOptions();
+ private static GitCommandCommit commandCommit = new GitCommandCommit();
+ private static GitCommandAdd commandAdd = new GitCommandAdd();
+ private static JCommander commander;
+
+ static {
+ commander = JCommander.newBuilder()
+ .programName("GitApp")
+ .addObject(commandOptions)
+ .addCommand(commandAdd)
+ .addCommand(commandCommit)
+ .build();
+ }
+
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ commander.usage();
+ return;
+ }
+ try {
+ commander.parse(args);
+ if (commandOptions.isHelp()) {
+ commander.usage();
+ return;
+ }
+ if (commandOptions.isVersion()) {
+ System.out.println("git version 2.24.3 (Apple Git-128)");
+ }
+ if (commandOptions.getCloneUrl() != null) {
+ System.out.printf("开始克隆远程仓库数据:%s%n", commandOptions.getCloneUrl());
+ return;
+ }
+ String parsedCommand = commander.getParsedCommand();
+ if (GitCommandCommit.COMMAND.equals(parsedCommand)) {
+ System.out.printf("提交暂存的文件并注释:%s%n", commandCommit.getComment());
+ return;
+ }
+ if (GitCommandAdd.COMMAND.equals(parsedCommand)) {
+ for (Path file : commandAdd.getFiles()) {
+ System.out.printf("暂存文件:%s%n", file);
+ }
+ return;
+ }
+ } catch (ParameterException e) {
+ System.err.println(e.getMessage());
+ commander.usage();
+ }
+ }
+
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandAdd.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandAdd.java
new file mode 100644
index 0000000..7fc9ff1
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandAdd.java
@@ -0,0 +1,24 @@
+package com.wdbyte.jcommander;
+
+import java.nio.file.Path;
+import java.util.List;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+
+/**
+ * git add file1 file2
+ *
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+@Parameters(commandDescription = "暂存文件", commandNames = "add", separators = " ")
+public class GitCommandAdd {
+ public static final String COMMAND = "add";
+ @Parameter(description = "暂存文件列表", converter = FilePathConverter.class)
+ private List files;
+
+ public List getFiles() {
+ return files;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandCommit.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandCommit.java
new file mode 100644
index 0000000..6710a63
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandCommit.java
@@ -0,0 +1,24 @@
+package com.wdbyte.jcommander;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+
+/**
+ * git commit -m "desc"
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+@Parameters(commandDescription = "提交文件", commandNames = "commit")
+public class GitCommandCommit {
+ public static final String COMMAND = "commit";
+
+ @Parameter(names = {"-comment", "-m"},
+ description = "请输入注释",
+ arity = 1,
+ required = true)
+ private String comment;
+
+ public String getComment() {
+ return comment;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandOptions.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandOptions.java
new file mode 100644
index 0000000..f9cc388
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/GitCommandOptions.java
@@ -0,0 +1,39 @@
+package com.wdbyte.jcommander;
+
+import java.net.URL;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.converters.URLConverter;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+public class GitCommandOptions {
+
+ @Parameter(names = {"help", "-help", "-h"},
+ description = "查看帮助信息",
+ help = true)
+ private boolean help;
+
+ @Parameter(names = {"clone"},
+ description = "克隆远程仓库数据",
+ arity = 1)
+ private String cloneUrl;
+
+ @Parameter(names = {"version", "-version", "-v"},
+ description = "显示当前版本号")
+ private boolean version = false;
+
+ public boolean isHelp() {
+ return help;
+ }
+
+ public boolean isVersion() {
+ return version;
+ }
+
+ public String getCloneUrl() {
+ return cloneUrl;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v1/GitApp.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v1/GitApp.java
new file mode 100644
index 0000000..f03e882
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v1/GitApp.java
@@ -0,0 +1,20 @@
+package com.wdbyte.jcommander.v1;
+
+import com.beust.jcommander.JCommander;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class GitApp {
+
+ public static void main(String[] args) {
+ args = new String[]{"clone","http://www.wdbyte.com/test.git"};
+ GitCommandOptions gitCommandOptions = new GitCommandOptions();
+ JCommander commander = JCommander.newBuilder()
+ .addObject(gitCommandOptions)
+ .build();
+ commander.parse(args);
+ System.out.println("clone " + gitCommandOptions.getCloneUrl());
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v1/GitCommandOptions.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v1/GitCommandOptions.java
new file mode 100644
index 0000000..8e986de
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v1/GitCommandOptions.java
@@ -0,0 +1,17 @@
+package com.wdbyte.jcommander.v1;
+
+import com.beust.jcommander.Parameter;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+public class GitCommandOptions {
+ @Parameter(names = {"clone"},
+ description = "克隆远程仓库数据")
+ private String cloneUrl;
+
+ public String getCloneUrl() {
+ return cloneUrl;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v2/GitApp.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v2/GitApp.java
new file mode 100644
index 0000000..6271d88
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v2/GitApp.java
@@ -0,0 +1,32 @@
+package com.wdbyte.jcommander.v2;
+
+import com.beust.jcommander.JCommander;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class GitApp {
+
+ public static void main(String[] args) {
+ //args = new String[] {"clone", "http://www.wdbyte.com/test.git"};
+ GitCommandOptions gitCommandOptions = new GitCommandOptions();
+ JCommander commander = JCommander.newBuilder()
+ .programName("git-app")
+ .addObject(gitCommandOptions)
+ .build();
+ commander.parse(args);
+ // 打印帮助信息
+ if (gitCommandOptions.isHelp()) {
+ commander.usage();
+ return;
+ }
+ if (gitCommandOptions.isVersion()) {
+ System.out.println("git version 2.24.3 (Apple Git-128)");
+ return;
+ }
+ if (gitCommandOptions.getCloneUrl() != null) {
+ System.out.println("clone " + gitCommandOptions.getCloneUrl());
+ }
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v2/GitCommandOptions.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v2/GitCommandOptions.java
new file mode 100644
index 0000000..cff5d4d
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v2/GitCommandOptions.java
@@ -0,0 +1,39 @@
+package com.wdbyte.jcommander.v2;
+
+import com.beust.jcommander.Parameter;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+public class GitCommandOptions {
+
+ @Parameter(names = {"help", "-help", "-h"},
+ description = "查看帮助信息",
+ order = 1,
+ help = true)
+ private boolean help;
+
+ @Parameter(names = {"clone"},
+ description = "克隆远程仓库数据",
+ order = 3,
+ arity = 1)
+ private String cloneUrl;
+
+ @Parameter(names = {"version", "-version", "-v"},
+ description = "显示当前版本号",
+ order = 2)
+ private boolean version = false;
+
+ public boolean isHelp() {
+ return help;
+ }
+
+ public boolean isVersion() {
+ return version;
+ }
+
+ public String getCloneUrl() {
+ return cloneUrl;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/GitApp.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/GitApp.java
new file mode 100644
index 0000000..9350713
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/GitApp.java
@@ -0,0 +1,32 @@
+package com.wdbyte.jcommander.v3;
+
+import com.beust.jcommander.JCommander;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class GitApp {
+
+ public static void main(String[] args) {
+ //args = new String[] {"clone", "ht2tp://www.wdbyte.com/test.git"};
+ GitCommandOptions gitCommandOptions = new GitCommandOptions();
+ JCommander commander = JCommander.newBuilder()
+ .programName("git-app")
+ .addObject(gitCommandOptions)
+ .build();
+ commander.parse(args);
+ // 打印帮助信息
+ if (gitCommandOptions.isHelp()) {
+ commander.usage();
+ return;
+ }
+ if (gitCommandOptions.isVersion()) {
+ System.out.println("git version 2.24.3 (Apple Git-128)");
+ return;
+ }
+ if (gitCommandOptions.getCloneUrl() != null) {
+ System.out.println("clone " + gitCommandOptions.getCloneUrl());
+ }
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/GitCommandOptions.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/GitCommandOptions.java
new file mode 100644
index 0000000..fd75160
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/GitCommandOptions.java
@@ -0,0 +1,40 @@
+package com.wdbyte.jcommander.v3;
+
+import com.beust.jcommander.Parameter;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+public class GitCommandOptions {
+
+ @Parameter(names = {"help", "-help", "-h"},
+ description = "查看帮助信息",
+ order = 1,
+ help = true)
+ private boolean help;
+
+ @Parameter(names = {"clone"},
+ description = "克隆远程仓库数据",
+ validateWith = UrlParameterValidator.class,
+ order = 3,
+ arity = 1)
+ private String cloneUrl;
+
+ @Parameter(names = {"version", "-version", "-v"},
+ description = "显示当前版本号",
+ order = 2)
+ private boolean version = false;
+
+ public boolean isHelp() {
+ return help;
+ }
+
+ public boolean isVersion() {
+ return version;
+ }
+
+ public String getCloneUrl() {
+ return cloneUrl;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/UrlParameterValidator.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/UrlParameterValidator.java
new file mode 100644
index 0000000..6ff98fa
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v3/UrlParameterValidator.java
@@ -0,0 +1,22 @@
+package com.wdbyte.jcommander.v3;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.beust.jcommander.IParameterValidator;
+import com.beust.jcommander.ParameterException;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class UrlParameterValidator implements IParameterValidator {
+ @Override
+ public void validate(String key, String value) throws ParameterException {
+ try {
+ new URL(value);
+ } catch (MalformedURLException e) {
+ throw new ParameterException("参数 " + key + " 的值必须是 URL 格式");
+ }
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitApp.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitApp.java
new file mode 100644
index 0000000..33d3dfb
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitApp.java
@@ -0,0 +1,38 @@
+package com.wdbyte.jcommander.v4;
+
+import com.beust.jcommander.JCommander;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class GitApp {
+
+ public static void main(String[] args) {
+ //args = new String[] {"clone", "ht2tp://www.wdbyte.com/test.git"};
+ GitCommandOptions gitCommandOptions = new GitCommandOptions();
+ GitCommandCommit commandCommit = new GitCommandCommit();
+ JCommander commander = JCommander.newBuilder()
+ .programName("git-app")
+ .addObject(gitCommandOptions)
+ .addCommand(commandCommit)
+ .build();
+ commander.parse(args);
+ // 打印帮助信息
+ if (gitCommandOptions.isHelp()) {
+ commander.usage();
+ return;
+ }
+ if (gitCommandOptions.isVersion()) {
+ System.out.println("git version 2.24.3 (Apple Git-128)");
+ return;
+ }
+ if (gitCommandOptions.getCloneUrl() != null) {
+ System.out.println("clone " + gitCommandOptions.getCloneUrl());
+ }
+ String parsedCommand = commander.getParsedCommand();
+ if ("commit".equals(parsedCommand)) {
+ System.out.println(commandCommit.getComment());
+ }
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitCommandCommit.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitCommandCommit.java
new file mode 100644
index 0000000..934c723
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitCommandCommit.java
@@ -0,0 +1,24 @@
+package com.wdbyte.jcommander.v4;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+
+/**
+ * git commit -m "desc"
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+@Parameters(commandDescription = "提交文件", commandNames = "commit")
+public class GitCommandCommit {
+ public static final String COMMAND = "commit";
+
+ @Parameter(names = {"-comment", "-m"},
+ description = "请输入注释",
+ arity = 1,
+ required = true)
+ private String comment;
+
+ public String getComment() {
+ return comment;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitCommandOptions.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitCommandOptions.java
new file mode 100644
index 0000000..32dcc40
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/GitCommandOptions.java
@@ -0,0 +1,40 @@
+package com.wdbyte.jcommander.v4;
+
+import com.beust.jcommander.Parameter;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+public class GitCommandOptions {
+
+ @Parameter(names = {"help", "-help", "-h"},
+ description = "查看帮助信息",
+ order = 1,
+ help = true)
+ private boolean help;
+
+ @Parameter(names = {"clone"},
+ description = "克隆远程仓库数据",
+ validateWith = UrlParameterValidator.class,
+ order = 3,
+ arity = 1)
+ private String cloneUrl;
+
+ @Parameter(names = {"version", "-version", "-v"},
+ description = "显示当前版本号",
+ order = 2)
+ private boolean version = false;
+
+ public boolean isHelp() {
+ return help;
+ }
+
+ public boolean isVersion() {
+ return version;
+ }
+
+ public String getCloneUrl() {
+ return cloneUrl;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/UrlParameterValidator.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/UrlParameterValidator.java
new file mode 100644
index 0000000..817bb7f
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v4/UrlParameterValidator.java
@@ -0,0 +1,22 @@
+package com.wdbyte.jcommander.v4;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.beust.jcommander.IParameterValidator;
+import com.beust.jcommander.ParameterException;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class UrlParameterValidator implements IParameterValidator {
+ @Override
+ public void validate(String key, String value) throws ParameterException {
+ try {
+ new URL(value);
+ } catch (MalformedURLException e) {
+ throw new ParameterException("参数 " + key + " 的值必须是 URL 格式");
+ }
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitApp.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitApp.java
new file mode 100644
index 0000000..a7ee225
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitApp.java
@@ -0,0 +1,45 @@
+package com.wdbyte.jcommander.v5;
+
+import com.beust.jcommander.JCommander;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class GitApp {
+
+ public static void main(String[] args) {
+ //args = new String[] {"clone", "ht2tp://www.wdbyte.com/test.git"};
+ GitCommandOptions gitCommandOptions = new GitCommandOptions();
+ GitCommandCommit commandCommit = new GitCommandCommit();
+ GitCommandAdd commandAdd = new GitCommandAdd();
+ JCommander commander = JCommander.newBuilder()
+ .programName("git-app")
+ .addObject(gitCommandOptions)
+ .addCommand(commandCommit)
+ .addCommand(commandAdd)
+ .build();
+ commander.parse(args);
+ // 打印帮助信息
+ if (gitCommandOptions.isHelp()) {
+ commander.usage();
+ return;
+ }
+ if (gitCommandOptions.isVersion()) {
+ System.out.println("git version 2.24.3 (Apple Git-128)");
+ return;
+ }
+ if (gitCommandOptions.getCloneUrl() != null) {
+ System.out.println("clone " + gitCommandOptions.getCloneUrl());
+ }
+ String parsedCommand = commander.getParsedCommand();
+ if ("commit".equals(parsedCommand)) {
+ System.out.println(commandCommit.getComment());
+ }
+ if ("add".equals(parsedCommand)) {
+ for (String file : commandAdd.getFiles()) {
+ System.out.println("暂存文件:" + file);
+ }
+ }
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandAdd.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandAdd.java
new file mode 100644
index 0000000..e1846f3
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandAdd.java
@@ -0,0 +1,23 @@
+package com.wdbyte.jcommander.v5;
+
+import java.util.List;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+
+/**
+ * git add file1 file2
+ *
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+@Parameters(commandDescription = "暂存文件", commandNames = "add", separators = " ")
+public class GitCommandAdd {
+ public static final String COMMAND = "add";
+ @Parameter(description = "暂存文件列表")
+ private List files;
+
+ public List getFiles() {
+ return files;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandCommit.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandCommit.java
new file mode 100644
index 0000000..6b76c65
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandCommit.java
@@ -0,0 +1,24 @@
+package com.wdbyte.jcommander.v5;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+
+/**
+ * git commit -m "desc"
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+@Parameters(commandDescription = "提交文件", commandNames = "commit")
+public class GitCommandCommit {
+ public static final String COMMAND = "commit";
+
+ @Parameter(names = {"-comment", "-m"},
+ description = "请输入注释",
+ arity = 1,
+ required = true)
+ private String comment;
+
+ public String getComment() {
+ return comment;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandOptions.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandOptions.java
new file mode 100644
index 0000000..0f3b3ee
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/GitCommandOptions.java
@@ -0,0 +1,40 @@
+package com.wdbyte.jcommander.v5;
+
+import com.beust.jcommander.Parameter;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/07
+ */
+public class GitCommandOptions {
+
+ @Parameter(names = {"help", "-help", "-h"},
+ description = "查看帮助信息",
+ order = 1,
+ help = true)
+ private boolean help;
+
+ @Parameter(names = {"clone"},
+ description = "克隆远程仓库数据",
+ validateWith = UrlParameterValidator.class,
+ order = 3,
+ arity = 1)
+ private String cloneUrl;
+
+ @Parameter(names = {"version", "-version", "-v"},
+ description = "显示当前版本号",
+ order = 2)
+ private boolean version = false;
+
+ public boolean isHelp() {
+ return help;
+ }
+
+ public boolean isVersion() {
+ return version;
+ }
+
+ public String getCloneUrl() {
+ return cloneUrl;
+ }
+}
diff --git a/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/UrlParameterValidator.java b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/UrlParameterValidator.java
new file mode 100644
index 0000000..cda4988
--- /dev/null
+++ b/tool-java-jcommander/src/main/java/com/wdbyte/jcommander/v5/UrlParameterValidator.java
@@ -0,0 +1,22 @@
+package com.wdbyte.jcommander.v5;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.beust.jcommander.IParameterValidator;
+import com.beust.jcommander.ParameterException;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/06/15
+ */
+public class UrlParameterValidator implements IParameterValidator {
+ @Override
+ public void validate(String key, String value) throws ParameterException {
+ try {
+ new URL(value);
+ } catch (MalformedURLException e) {
+ throw new ParameterException("参数 " + key + " 的值必须是 URL 格式");
+ }
+ }
+}
diff --git a/junit5-jupiter-starter/.gitignore b/tool-java-junit5-jupiter-starter/.gitignore
similarity index 100%
rename from junit5-jupiter-starter/.gitignore
rename to tool-java-junit5-jupiter-starter/.gitignore
diff --git a/junit5-jupiter-starter/README.md b/tool-java-junit5-jupiter-starter/README.md
similarity index 100%
rename from junit5-jupiter-starter/README.md
rename to tool-java-junit5-jupiter-starter/README.md
diff --git a/junit5-jupiter-starter/pom.xml b/tool-java-junit5-jupiter-starter/pom.xml
similarity index 95%
rename from junit5-jupiter-starter/pom.xml
rename to tool-java-junit5-jupiter-starter/pom.xml
index d100632..554f3de 100644
--- a/junit5-jupiter-starter/pom.xml
+++ b/tool-java-junit5-jupiter-starter/pom.xml
@@ -10,7 +10,7 @@
4.0.0
com.wdbyte.junit5
- junit5-jupiter-starter
+ tool-java-junit5-jupiter-starter
1.8
diff --git a/junit5-jupiter-starter/src/main/java/com/wdbyte/test/junit5/Person.java b/tool-java-junit5-jupiter-starter/src/main/java/com/wdbyte/test/junit5/Person.java
similarity index 80%
rename from junit5-jupiter-starter/src/main/java/com/wdbyte/test/junit5/Person.java
rename to tool-java-junit5-jupiter-starter/src/main/java/com/wdbyte/test/junit5/Person.java
index 514c0af..975d7c6 100644
--- a/junit5-jupiter-starter/src/main/java/com/wdbyte/test/junit5/Person.java
+++ b/tool-java-junit5-jupiter-starter/src/main/java/com/wdbyte/test/junit5/Person.java
@@ -1,7 +1,7 @@
package com.wdbyte.test.junit5;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/17
*/
public class Person {
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitBeforeAll.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitBeforeAll.java
similarity index 97%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitBeforeAll.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitBeforeAll.java
index 732fb50..8c28e80 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitBeforeAll.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitBeforeAll.java
@@ -10,7 +10,7 @@
import org.junit.jupiter.api.Test;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/15
*/
class JUnitBeforeAll {
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitJDKVersion.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitJDKVersion.java
similarity index 96%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitJDKVersion.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitJDKVersion.java
index 62230fc..d610a96 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitJDKVersion.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitJDKVersion.java
@@ -11,7 +11,7 @@
import static org.junit.jupiter.api.condition.JRE.JAVA_19;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/17
*/
@TestMethodOrder(OrderAnnotation.class)
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOrder.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOrder.java
similarity index 96%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOrder.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOrder.java
index eef289a..6bd959e 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOrder.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOrder.java
@@ -8,7 +8,7 @@
import org.junit.jupiter.api.TestMethodOrder;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/17
*/
@TestMethodOrder(OrderAnnotation.class)
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOther.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOther.java
similarity index 96%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOther.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOther.java
index aebe289..9951745 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOther.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitOther.java
@@ -9,7 +9,7 @@
import org.junit.jupiter.api.TestMethodOrder;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/17
*/
@TestMethodOrder(OrderAnnotation.class)
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitParam.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitParam.java
similarity index 93%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitParam.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitParam.java
index fe29bbd..388a865 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitParam.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitParam.java
@@ -6,7 +6,7 @@
import org.junit.jupiter.params.provider.ValueSource;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/17
*/
public class JUnitParam {
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitTestIsDog.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitTestIsDog.java
similarity index 94%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitTestIsDog.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitTestIsDog.java
index 5d0cb07..e39c696 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitTestIsDog.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JUnitTestIsDog.java
@@ -5,7 +5,7 @@
import org.junit.jupiter.api.Test;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/15
*/
class JUnitTestIsDog {
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JunitAssert.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JunitAssert.java
similarity index 95%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JunitAssert.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JunitAssert.java
index 0063739..34a29e6 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JunitAssert.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/JunitAssert.java
@@ -5,7 +5,7 @@
import org.junit.jupiter.api.Test;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/17
*/
public class JunitAssert {
diff --git a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/PersonTest.java b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/PersonTest.java
similarity index 92%
rename from junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/PersonTest.java
rename to tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/PersonTest.java
index 0d883ed..d72ef3d 100644
--- a/junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/PersonTest.java
+++ b/tool-java-junit5-jupiter-starter/src/test/java/com/wdbyte/test/junit5/PersonTest.java
@@ -5,7 +5,7 @@
import org.junit.jupiter.api.Test;
/**
- * @author niulang
+ * @author https://www.wdbyte.com
* @date 2022/11/17
*/
@DisplayName("测试 Presion")
diff --git a/tool-java-object-pool/pom.xml b/tool-java-object-pool/pom.xml
index f8c4630..7044006 100644
--- a/tool-java-object-pool/pom.xml
+++ b/tool-java-object-pool/pom.xml
@@ -8,7 +8,7 @@
1.0.0-SNAPSHOT
4.0.0
- objectpool
+ tool-java-object-pool
8
diff --git a/tool-java-protobuf/.gitignore b/tool-java-protobuf/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/tool-java-protobuf/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/tool-java-protobuf/pom.xml b/tool-java-protobuf/pom.xml
new file mode 100644
index 0000000..3c9725c
--- /dev/null
+++ b/tool-java-protobuf/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ com.wdbyte
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../pom.xml
+
+
+ tool-java-protobuf
+
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+ com.google.protobuf
+ protobuf-java
+ 3.22.3
+
+
+
+ com.alibaba
+ fastjson
+ 2.0.7
+
+
+ org.openjdk.jmh
+ jmh-core
+ 1.33
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ 1.33
+ provided
+
+
+
+
\ No newline at end of file
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBook.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBook.java
new file mode 100644
index 0000000..e8e78be
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBook.java
@@ -0,0 +1,725 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: resources/addressbook.proto
+
+package com.wdbyte.tool.protos;
+
+/**
+ * Protobuf type {@code com.wdbyte.protobuf.AddressBook}
+ */
+public final class AddressBook extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:com.wdbyte.protobuf.AddressBook)
+ AddressBookOrBuilder {
+private static final long serialVersionUID = 0L;
+ // Use AddressBook.newBuilder() to construct.
+ private AddressBook(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private AddressBook() {
+ people_ = java.util.Collections.emptyList();
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new AddressBook();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_AddressBook_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_AddressBook_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.AddressBook.class, com.wdbyte.tool.protos.AddressBook.Builder.class);
+ }
+
+ public static final int PEOPLE_FIELD_NUMBER = 1;
+ @SuppressWarnings("serial")
+ private java.util.List people_;
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ @java.lang.Override
+ public java.util.List getPeopleList() {
+ return people_;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ @java.lang.Override
+ public java.util.List extends com.wdbyte.tool.protos.PersonOrBuilder>
+ getPeopleOrBuilderList() {
+ return people_;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ @java.lang.Override
+ public int getPeopleCount() {
+ return people_.size();
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person getPeople(int index) {
+ return people_.get(index);
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ @java.lang.Override
+ public com.wdbyte.tool.protos.PersonOrBuilder getPeopleOrBuilder(
+ int index) {
+ return people_.get(index);
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ for (int i = 0; i < people_.size(); i++) {
+ output.writeMessage(1, people_.get(i));
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ for (int i = 0; i < people_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, people_.get(i));
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.wdbyte.tool.protos.AddressBook)) {
+ return super.equals(obj);
+ }
+ com.wdbyte.tool.protos.AddressBook other = (com.wdbyte.tool.protos.AddressBook) obj;
+
+ if (!getPeopleList()
+ .equals(other.getPeopleList())) return false;
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (getPeopleCount() > 0) {
+ hash = (37 * hash) + PEOPLE_FIELD_NUMBER;
+ hash = (53 * hash) + getPeopleList().hashCode();
+ }
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.AddressBook parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(com.wdbyte.tool.protos.AddressBook prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code com.wdbyte.protobuf.AddressBook}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:com.wdbyte.protobuf.AddressBook)
+ com.wdbyte.tool.protos.AddressBookOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_AddressBook_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_AddressBook_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.AddressBook.class, com.wdbyte.tool.protos.AddressBook.Builder.class);
+ }
+
+ // Construct using com.wdbyte.tool.protos.AddressBook.newBuilder()
+ private Builder() {
+
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ bitField0_ = 0;
+ if (peopleBuilder_ == null) {
+ people_ = java.util.Collections.emptyList();
+ } else {
+ people_ = null;
+ peopleBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000001);
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_AddressBook_descriptor;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.AddressBook getDefaultInstanceForType() {
+ return com.wdbyte.tool.protos.AddressBook.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.AddressBook build() {
+ com.wdbyte.tool.protos.AddressBook result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.AddressBook buildPartial() {
+ com.wdbyte.tool.protos.AddressBook result = new com.wdbyte.tool.protos.AddressBook(this);
+ buildPartialRepeatedFields(result);
+ if (bitField0_ != 0) { buildPartial0(result); }
+ onBuilt();
+ return result;
+ }
+
+ private void buildPartialRepeatedFields(com.wdbyte.tool.protos.AddressBook result) {
+ if (peopleBuilder_ == null) {
+ if (((bitField0_ & 0x00000001) != 0)) {
+ people_ = java.util.Collections.unmodifiableList(people_);
+ bitField0_ = (bitField0_ & ~0x00000001);
+ }
+ result.people_ = people_;
+ } else {
+ result.people_ = peopleBuilder_.build();
+ }
+ }
+
+ private void buildPartial0(com.wdbyte.tool.protos.AddressBook result) {
+ int from_bitField0_ = bitField0_;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.wdbyte.tool.protos.AddressBook) {
+ return mergeFrom((com.wdbyte.tool.protos.AddressBook)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.wdbyte.tool.protos.AddressBook other) {
+ if (other == com.wdbyte.tool.protos.AddressBook.getDefaultInstance()) return this;
+ if (peopleBuilder_ == null) {
+ if (!other.people_.isEmpty()) {
+ if (people_.isEmpty()) {
+ people_ = other.people_;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ } else {
+ ensurePeopleIsMutable();
+ people_.addAll(other.people_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.people_.isEmpty()) {
+ if (peopleBuilder_.isEmpty()) {
+ peopleBuilder_.dispose();
+ peopleBuilder_ = null;
+ people_ = other.people_;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ peopleBuilder_ =
+ com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+ getPeopleFieldBuilder() : null;
+ } else {
+ peopleBuilder_.addAllMessages(other.people_);
+ }
+ }
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10: {
+ com.wdbyte.tool.protos.Person m =
+ input.readMessage(
+ com.wdbyte.tool.protos.Person.parser(),
+ extensionRegistry);
+ if (peopleBuilder_ == null) {
+ ensurePeopleIsMutable();
+ people_.add(m);
+ } else {
+ peopleBuilder_.addMessage(m);
+ }
+ break;
+ } // case 10
+ default: {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+ private int bitField0_;
+
+ private java.util.List people_ =
+ java.util.Collections.emptyList();
+ private void ensurePeopleIsMutable() {
+ if (!((bitField0_ & 0x00000001) != 0)) {
+ people_ = new java.util.ArrayList(people_);
+ bitField0_ |= 0x00000001;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.wdbyte.tool.protos.Person, com.wdbyte.tool.protos.Person.Builder, com.wdbyte.tool.protos.PersonOrBuilder> peopleBuilder_;
+
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public java.util.List getPeopleList() {
+ if (peopleBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(people_);
+ } else {
+ return peopleBuilder_.getMessageList();
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public int getPeopleCount() {
+ if (peopleBuilder_ == null) {
+ return people_.size();
+ } else {
+ return peopleBuilder_.getCount();
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public com.wdbyte.tool.protos.Person getPeople(int index) {
+ if (peopleBuilder_ == null) {
+ return people_.get(index);
+ } else {
+ return peopleBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder setPeople(
+ int index, com.wdbyte.tool.protos.Person value) {
+ if (peopleBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePeopleIsMutable();
+ people_.set(index, value);
+ onChanged();
+ } else {
+ peopleBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder setPeople(
+ int index, com.wdbyte.tool.protos.Person.Builder builderForValue) {
+ if (peopleBuilder_ == null) {
+ ensurePeopleIsMutable();
+ people_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ peopleBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder addPeople(com.wdbyte.tool.protos.Person value) {
+ if (peopleBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePeopleIsMutable();
+ people_.add(value);
+ onChanged();
+ } else {
+ peopleBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder addPeople(
+ int index, com.wdbyte.tool.protos.Person value) {
+ if (peopleBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePeopleIsMutable();
+ people_.add(index, value);
+ onChanged();
+ } else {
+ peopleBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder addPeople(
+ com.wdbyte.tool.protos.Person.Builder builderForValue) {
+ if (peopleBuilder_ == null) {
+ ensurePeopleIsMutable();
+ people_.add(builderForValue.build());
+ onChanged();
+ } else {
+ peopleBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder addPeople(
+ int index, com.wdbyte.tool.protos.Person.Builder builderForValue) {
+ if (peopleBuilder_ == null) {
+ ensurePeopleIsMutable();
+ people_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ peopleBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder addAllPeople(
+ java.lang.Iterable extends com.wdbyte.tool.protos.Person> values) {
+ if (peopleBuilder_ == null) {
+ ensurePeopleIsMutable();
+ com.google.protobuf.AbstractMessageLite.Builder.addAll(
+ values, people_);
+ onChanged();
+ } else {
+ peopleBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder clearPeople() {
+ if (peopleBuilder_ == null) {
+ people_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ onChanged();
+ } else {
+ peopleBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public Builder removePeople(int index) {
+ if (peopleBuilder_ == null) {
+ ensurePeopleIsMutable();
+ people_.remove(index);
+ onChanged();
+ } else {
+ peopleBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public com.wdbyte.tool.protos.Person.Builder getPeopleBuilder(
+ int index) {
+ return getPeopleFieldBuilder().getBuilder(index);
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public com.wdbyte.tool.protos.PersonOrBuilder getPeopleOrBuilder(
+ int index) {
+ if (peopleBuilder_ == null) {
+ return people_.get(index); } else {
+ return peopleBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public java.util.List extends com.wdbyte.tool.protos.PersonOrBuilder>
+ getPeopleOrBuilderList() {
+ if (peopleBuilder_ != null) {
+ return peopleBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(people_);
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public com.wdbyte.tool.protos.Person.Builder addPeopleBuilder() {
+ return getPeopleFieldBuilder().addBuilder(
+ com.wdbyte.tool.protos.Person.getDefaultInstance());
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public com.wdbyte.tool.protos.Person.Builder addPeopleBuilder(
+ int index) {
+ return getPeopleFieldBuilder().addBuilder(
+ index, com.wdbyte.tool.protos.Person.getDefaultInstance());
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ public java.util.List
+ getPeopleBuilderList() {
+ return getPeopleFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.wdbyte.tool.protos.Person, com.wdbyte.tool.protos.Person.Builder, com.wdbyte.tool.protos.PersonOrBuilder>
+ getPeopleFieldBuilder() {
+ if (peopleBuilder_ == null) {
+ peopleBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+ com.wdbyte.tool.protos.Person, com.wdbyte.tool.protos.Person.Builder, com.wdbyte.tool.protos.PersonOrBuilder>(
+ people_,
+ ((bitField0_ & 0x00000001) != 0),
+ getParentForChildren(),
+ isClean());
+ people_ = null;
+ }
+ return peopleBuilder_;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:com.wdbyte.protobuf.AddressBook)
+ }
+
+ // @@protoc_insertion_point(class_scope:com.wdbyte.protobuf.AddressBook)
+ private static final com.wdbyte.tool.protos.AddressBook DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new com.wdbyte.tool.protos.AddressBook();
+ }
+
+ public static com.wdbyte.tool.protos.AddressBook getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public AddressBook parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.AddressBook getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+}
+
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookJava.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookJava.java
new file mode 100644
index 0000000..5d500c4
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookJava.java
@@ -0,0 +1,81 @@
+package com.wdbyte.tool.protos;
+
+import java.util.List;
+
+public class AddressBookJava {
+ List personJavaList;
+
+ public static class PersonJava {
+ private int id;
+ private String name;
+ private String email;
+ private PhoneNumberJava phones;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public PhoneNumberJava getPhones() {
+ return phones;
+ }
+
+ public void setPhones(PhoneNumberJava phones) {
+ this.phones = phones;
+ }
+ }
+
+ public static class PhoneNumberJava {
+ private String number;
+ private PhoneTypeJava phoneTypeJava;
+
+ public String getNumber() {
+ return number;
+ }
+
+ public void setNumber(String number) {
+ this.number = number;
+ }
+
+ public PhoneTypeJava getPhoneTypeJava() {
+ return phoneTypeJava;
+ }
+
+ public void setPhoneTypeJava(PhoneTypeJava phoneTypeJava) {
+ this.phoneTypeJava = phoneTypeJava;
+ }
+ }
+
+ public enum PhoneTypeJava {
+ MOBILE,
+ HOME,
+ WORK;
+ }
+
+ public List getPersonJavaList() {
+ return personJavaList;
+ }
+
+ public void setPersonJavaList(List personJavaList) {
+ this.personJavaList = personJavaList;
+ }
+}
\ No newline at end of file
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookOrBuilder.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookOrBuilder.java
new file mode 100644
index 0000000..e0b5161
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookOrBuilder.java
@@ -0,0 +1,33 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: resources/addressbook.proto
+
+package com.wdbyte.tool.protos;
+
+public interface AddressBookOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:com.wdbyte.protobuf.AddressBook)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ java.util.List
+ getPeopleList();
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ com.wdbyte.tool.protos.Person getPeople(int index);
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ int getPeopleCount();
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ java.util.List extends com.wdbyte.tool.protos.PersonOrBuilder>
+ getPeopleOrBuilderList();
+ /**
+ * repeated .com.wdbyte.protobuf.Person people = 1;
+ */
+ com.wdbyte.tool.protos.PersonOrBuilder getPeopleOrBuilder(
+ int index);
+}
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookProtos.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookProtos.java
new file mode 100644
index 0000000..e1c6788
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/AddressBookProtos.java
@@ -0,0 +1,79 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: resources/addressbook.proto
+
+package com.wdbyte.tool.protos;
+
+public final class AddressBookProtos {
+ private AddressBookProtos() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registerAllExtensions(
+ (com.google.protobuf.ExtensionRegistryLite) registry);
+ }
+ static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_com_wdbyte_protobuf_Person_descriptor;
+ static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_com_wdbyte_protobuf_Person_fieldAccessorTable;
+ static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_com_wdbyte_protobuf_Person_PhoneNumber_descriptor;
+ static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_com_wdbyte_protobuf_Person_PhoneNumber_fieldAccessorTable;
+ static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_com_wdbyte_protobuf_AddressBook_descriptor;
+ static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_com_wdbyte_protobuf_AddressBook_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\033resources/addressbook.proto\022\023com.wdbyt" +
+ "e.protobuf\"\262\002\n\006Person\022\017\n\002id\030\001 \001(\005H\000\210\001\001\022\021" +
+ "\n\004name\030\002 \001(\tH\001\210\001\001\022\022\n\005email\030\003 \001(\tH\002\210\001\001\0227\n" +
+ "\006phones\030\004 \003(\0132\'.com.wdbyte.protobuf.Pers" +
+ "on.PhoneNumber\032p\n\013PhoneNumber\022\023\n\006number\030" +
+ "\001 \001(\tH\000\210\001\001\0228\n\004type\030\002 \001(\0162%.com.wdbyte.pr" +
+ "otobuf.Person.PhoneTypeH\001\210\001\001B\t\n\007_numberB" +
+ "\007\n\005_type\"+\n\tPhoneType\022\n\n\006MOBILE\020\000\022\010\n\004HOM" +
+ "E\020\001\022\010\n\004WORK\020\002B\005\n\003_idB\007\n\005_nameB\010\n\006_email\"" +
+ ":\n\013AddressBook\022+\n\006people\030\001 \003(\0132\033.com.wdb" +
+ "yte.protobuf.PersonB-\n\026com.wdbyte.tool.p" +
+ "rotosB\021AddressBookProtosP\001b\006proto3"
+ };
+ descriptor = com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ });
+ internal_static_com_wdbyte_protobuf_Person_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_com_wdbyte_protobuf_Person_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_com_wdbyte_protobuf_Person_descriptor,
+ new java.lang.String[] { "Id", "Name", "Email", "Phones", "Id", "Name", "Email", });
+ internal_static_com_wdbyte_protobuf_Person_PhoneNumber_descriptor =
+ internal_static_com_wdbyte_protobuf_Person_descriptor.getNestedTypes().get(0);
+ internal_static_com_wdbyte_protobuf_Person_PhoneNumber_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_com_wdbyte_protobuf_Person_PhoneNumber_descriptor,
+ new java.lang.String[] { "Number", "Type", "Number", "Type", });
+ internal_static_com_wdbyte_protobuf_AddressBook_descriptor =
+ getDescriptor().getMessageTypes().get(1);
+ internal_static_com_wdbyte_protobuf_AddressBook_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_com_wdbyte_protobuf_AddressBook_descriptor,
+ new java.lang.String[] { "People", });
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/Person.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/Person.java
new file mode 100644
index 0000000..8ba2d40
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/Person.java
@@ -0,0 +1,1942 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: resources/addressbook.proto
+
+package com.wdbyte.tool.protos;
+
+/**
+ *
+ * 可选消息字段类型:bool int32 float double string
+ * 或者自定义消息类型,如下面的 PhoneNumber
+ * 修饰符:optional: 可选字段,
+ * 修饰符:repeated:可重复,如数组。
+ * 修饰符:required:必要字段,必须给值,否则会报错 RuntimeException,但是在 protobuf 版本 3 中被移除。
+ * 慎用 required,因为一旦被标记 requieds,以后将不能更改,否则可能会出问题。
+ *
+ *
+ * Protobuf type {@code com.wdbyte.protobuf.Person}
+ */
+public final class Person extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:com.wdbyte.protobuf.Person)
+ PersonOrBuilder {
+private static final long serialVersionUID = 0L;
+ // Use Person.newBuilder() to construct.
+ private Person(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private Person() {
+ name_ = "";
+ email_ = "";
+ phones_ = java.util.Collections.emptyList();
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new Person();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.Person.class, com.wdbyte.tool.protos.Person.Builder.class);
+ }
+
+ /**
+ * Protobuf enum {@code com.wdbyte.protobuf.Person.PhoneType}
+ */
+ public enum PhoneType
+ implements com.google.protobuf.ProtocolMessageEnum {
+ /**
+ * MOBILE = 0;
+ */
+ MOBILE(0),
+ /**
+ * HOME = 1;
+ */
+ HOME(1),
+ /**
+ * WORK = 2;
+ */
+ WORK(2),
+ UNRECOGNIZED(-1),
+ ;
+
+ /**
+ * MOBILE = 0;
+ */
+ public static final int MOBILE_VALUE = 0;
+ /**
+ * HOME = 1;
+ */
+ public static final int HOME_VALUE = 1;
+ /**
+ * WORK = 2;
+ */
+ public static final int WORK_VALUE = 2;
+
+
+ public final int getNumber() {
+ if (this == UNRECOGNIZED) {
+ throw new java.lang.IllegalArgumentException(
+ "Can't get the number of an unknown enum value.");
+ }
+ return value;
+ }
+
+ /**
+ * @param value The numeric wire value of the corresponding enum entry.
+ * @return The enum associated with the given numeric wire value.
+ * @deprecated Use {@link #forNumber(int)} instead.
+ */
+ @java.lang.Deprecated
+ public static PhoneType valueOf(int value) {
+ return forNumber(value);
+ }
+
+ /**
+ * @param value The numeric wire value of the corresponding enum entry.
+ * @return The enum associated with the given numeric wire value.
+ */
+ public static PhoneType forNumber(int value) {
+ switch (value) {
+ case 0: return MOBILE;
+ case 1: return HOME;
+ case 2: return WORK;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static final com.google.protobuf.Internal.EnumLiteMap<
+ PhoneType> internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap() {
+ public PhoneType findValueByNumber(int number) {
+ return PhoneType.forNumber(number);
+ }
+ };
+
+ public final com.google.protobuf.Descriptors.EnumValueDescriptor
+ getValueDescriptor() {
+ if (this == UNRECOGNIZED) {
+ throw new java.lang.IllegalStateException(
+ "Can't get the descriptor of an unrecognized enum value.");
+ }
+ return getDescriptor().getValues().get(ordinal());
+ }
+ public final com.google.protobuf.Descriptors.EnumDescriptor
+ getDescriptorForType() {
+ return getDescriptor();
+ }
+ public static final com.google.protobuf.Descriptors.EnumDescriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.Person.getDescriptor().getEnumTypes().get(0);
+ }
+
+ private static final PhoneType[] VALUES = values();
+
+ public static PhoneType valueOf(
+ com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+ if (desc.getType() != getDescriptor()) {
+ throw new java.lang.IllegalArgumentException(
+ "EnumValueDescriptor is not for this type.");
+ }
+ if (desc.getIndex() == -1) {
+ return UNRECOGNIZED;
+ }
+ return VALUES[desc.getIndex()];
+ }
+
+ private final int value;
+
+ private PhoneType(int value) {
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:com.wdbyte.protobuf.Person.PhoneType)
+ }
+
+ public interface PhoneNumberOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:com.wdbyte.protobuf.Person.PhoneNumber)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * optional string number = 1;
+ * @return Whether the number field is set.
+ */
+ boolean hasNumber();
+ /**
+ * optional string number = 1;
+ * @return The number.
+ */
+ java.lang.String getNumber();
+ /**
+ * optional string number = 1;
+ * @return The bytes for number.
+ */
+ com.google.protobuf.ByteString
+ getNumberBytes();
+
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return Whether the type field is set.
+ */
+ boolean hasType();
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return The enum numeric value on the wire for type.
+ */
+ int getTypeValue();
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return The type.
+ */
+ com.wdbyte.tool.protos.Person.PhoneType getType();
+ }
+ /**
+ * Protobuf type {@code com.wdbyte.protobuf.Person.PhoneNumber}
+ */
+ public static final class PhoneNumber extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:com.wdbyte.protobuf.Person.PhoneNumber)
+ PhoneNumberOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use PhoneNumber.newBuilder() to construct.
+ private PhoneNumber(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private PhoneNumber() {
+ number_ = "";
+ type_ = 0;
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new PhoneNumber();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_PhoneNumber_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_PhoneNumber_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.Person.PhoneNumber.class, com.wdbyte.tool.protos.Person.PhoneNumber.Builder.class);
+ }
+
+ private int bitField0_;
+ public static final int NUMBER_FIELD_NUMBER = 1;
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object number_ = "";
+ /**
+ * optional string number = 1;
+ * @return Whether the number field is set.
+ */
+ @java.lang.Override
+ public boolean hasNumber() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ * optional string number = 1;
+ * @return The number.
+ */
+ @java.lang.Override
+ public java.lang.String getNumber() {
+ java.lang.Object ref = number_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ number_ = s;
+ return s;
+ }
+ }
+ /**
+ * optional string number = 1;
+ * @return The bytes for number.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString
+ getNumberBytes() {
+ java.lang.Object ref = number_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ number_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int TYPE_FIELD_NUMBER = 2;
+ private int type_ = 0;
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return Whether the type field is set.
+ */
+ @java.lang.Override public boolean hasType() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return The enum numeric value on the wire for type.
+ */
+ @java.lang.Override public int getTypeValue() {
+ return type_;
+ }
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return The type.
+ */
+ @java.lang.Override public com.wdbyte.tool.protos.Person.PhoneType getType() {
+ com.wdbyte.tool.protos.Person.PhoneType result = com.wdbyte.tool.protos.Person.PhoneType.forNumber(type_);
+ return result == null ? com.wdbyte.tool.protos.Person.PhoneType.UNRECOGNIZED : result;
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ if (((bitField0_ & 0x00000001) != 0)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 1, number_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ output.writeEnum(2, type_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) != 0)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, number_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(2, type_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.wdbyte.tool.protos.Person.PhoneNumber)) {
+ return super.equals(obj);
+ }
+ com.wdbyte.tool.protos.Person.PhoneNumber other = (com.wdbyte.tool.protos.Person.PhoneNumber) obj;
+
+ if (hasNumber() != other.hasNumber()) return false;
+ if (hasNumber()) {
+ if (!getNumber()
+ .equals(other.getNumber())) return false;
+ }
+ if (hasType() != other.hasType()) return false;
+ if (hasType()) {
+ if (type_ != other.type_) return false;
+ }
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (hasNumber()) {
+ hash = (37 * hash) + NUMBER_FIELD_NUMBER;
+ hash = (53 * hash) + getNumber().hashCode();
+ }
+ if (hasType()) {
+ hash = (37 * hash) + TYPE_FIELD_NUMBER;
+ hash = (53 * hash) + type_;
+ }
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.Person.PhoneNumber parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(com.wdbyte.tool.protos.Person.PhoneNumber prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code com.wdbyte.protobuf.Person.PhoneNumber}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:com.wdbyte.protobuf.Person.PhoneNumber)
+ com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_PhoneNumber_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_PhoneNumber_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.Person.PhoneNumber.class, com.wdbyte.tool.protos.Person.PhoneNumber.Builder.class);
+ }
+
+ // Construct using com.wdbyte.tool.protos.Person.PhoneNumber.newBuilder()
+ private Builder() {
+
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ bitField0_ = 0;
+ number_ = "";
+ type_ = 0;
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_PhoneNumber_descriptor;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person.PhoneNumber getDefaultInstanceForType() {
+ return com.wdbyte.tool.protos.Person.PhoneNumber.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person.PhoneNumber build() {
+ com.wdbyte.tool.protos.Person.PhoneNumber result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person.PhoneNumber buildPartial() {
+ com.wdbyte.tool.protos.Person.PhoneNumber result = new com.wdbyte.tool.protos.Person.PhoneNumber(this);
+ if (bitField0_ != 0) { buildPartial0(result); }
+ onBuilt();
+ return result;
+ }
+
+ private void buildPartial0(com.wdbyte.tool.protos.Person.PhoneNumber result) {
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) != 0)) {
+ result.number_ = number_;
+ to_bitField0_ |= 0x00000001;
+ }
+ if (((from_bitField0_ & 0x00000002) != 0)) {
+ result.type_ = type_;
+ to_bitField0_ |= 0x00000002;
+ }
+ result.bitField0_ |= to_bitField0_;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.wdbyte.tool.protos.Person.PhoneNumber) {
+ return mergeFrom((com.wdbyte.tool.protos.Person.PhoneNumber)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.wdbyte.tool.protos.Person.PhoneNumber other) {
+ if (other == com.wdbyte.tool.protos.Person.PhoneNumber.getDefaultInstance()) return this;
+ if (other.hasNumber()) {
+ number_ = other.number_;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ }
+ if (other.hasType()) {
+ setType(other.getType());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10: {
+ number_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000001;
+ break;
+ } // case 10
+ case 16: {
+ type_ = input.readEnum();
+ bitField0_ |= 0x00000002;
+ break;
+ } // case 16
+ default: {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+ private int bitField0_;
+
+ private java.lang.Object number_ = "";
+ /**
+ * optional string number = 1;
+ * @return Whether the number field is set.
+ */
+ public boolean hasNumber() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ * optional string number = 1;
+ * @return The number.
+ */
+ public java.lang.String getNumber() {
+ java.lang.Object ref = number_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ number_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string number = 1;
+ * @return The bytes for number.
+ */
+ public com.google.protobuf.ByteString
+ getNumberBytes() {
+ java.lang.Object ref = number_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ number_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string number = 1;
+ * @param value The number to set.
+ * @return This builder for chaining.
+ */
+ public Builder setNumber(
+ java.lang.String value) {
+ if (value == null) { throw new NullPointerException(); }
+ number_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string number = 1;
+ * @return This builder for chaining.
+ */
+ public Builder clearNumber() {
+ number_ = getDefaultInstance().getNumber();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string number = 1;
+ * @param value The bytes for number to set.
+ * @return This builder for chaining.
+ */
+ public Builder setNumberBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) { throw new NullPointerException(); }
+ checkByteStringIsUtf8(value);
+ number_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+
+ private int type_ = 0;
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return Whether the type field is set.
+ */
+ @java.lang.Override public boolean hasType() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return The enum numeric value on the wire for type.
+ */
+ @java.lang.Override public int getTypeValue() {
+ return type_;
+ }
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @param value The enum numeric value on the wire for type to set.
+ * @return This builder for chaining.
+ */
+ public Builder setTypeValue(int value) {
+ type_ = value;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return The type.
+ */
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person.PhoneType getType() {
+ com.wdbyte.tool.protos.Person.PhoneType result = com.wdbyte.tool.protos.Person.PhoneType.forNumber(type_);
+ return result == null ? com.wdbyte.tool.protos.Person.PhoneType.UNRECOGNIZED : result;
+ }
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @param value The type to set.
+ * @return This builder for chaining.
+ */
+ public Builder setType(com.wdbyte.tool.protos.Person.PhoneType value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ type_ = value.getNumber();
+ onChanged();
+ return this;
+ }
+ /**
+ * optional .com.wdbyte.protobuf.Person.PhoneType type = 2;
+ * @return This builder for chaining.
+ */
+ public Builder clearType() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ type_ = 0;
+ onChanged();
+ return this;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:com.wdbyte.protobuf.Person.PhoneNumber)
+ }
+
+ // @@protoc_insertion_point(class_scope:com.wdbyte.protobuf.Person.PhoneNumber)
+ private static final com.wdbyte.tool.protos.Person.PhoneNumber DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new com.wdbyte.tool.protos.Person.PhoneNumber();
+ }
+
+ public static com.wdbyte.tool.protos.Person.PhoneNumber getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public PhoneNumber parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person.PhoneNumber getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ private int bitField0_;
+ public static final int ID_FIELD_NUMBER = 1;
+ private int id_ = 0;
+ /**
+ * optional int32 id = 1;
+ * @return Whether the id field is set.
+ */
+ @java.lang.Override
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ * optional int32 id = 1;
+ * @return The id.
+ */
+ @java.lang.Override
+ public int getId() {
+ return id_;
+ }
+
+ public static final int NAME_FIELD_NUMBER = 2;
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object name_ = "";
+ /**
+ * optional string name = 2;
+ * @return Whether the name field is set.
+ */
+ @java.lang.Override
+ public boolean hasName() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ * optional string name = 2;
+ * @return The name.
+ */
+ @java.lang.Override
+ public java.lang.String getName() {
+ java.lang.Object ref = name_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ name_ = s;
+ return s;
+ }
+ }
+ /**
+ * optional string name = 2;
+ * @return The bytes for name.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString
+ getNameBytes() {
+ java.lang.Object ref = name_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ name_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int EMAIL_FIELD_NUMBER = 3;
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object email_ = "";
+ /**
+ * optional string email = 3;
+ * @return Whether the email field is set.
+ */
+ @java.lang.Override
+ public boolean hasEmail() {
+ return ((bitField0_ & 0x00000004) != 0);
+ }
+ /**
+ * optional string email = 3;
+ * @return The email.
+ */
+ @java.lang.Override
+ public java.lang.String getEmail() {
+ java.lang.Object ref = email_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ email_ = s;
+ return s;
+ }
+ }
+ /**
+ * optional string email = 3;
+ * @return The bytes for email.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString
+ getEmailBytes() {
+ java.lang.Object ref = email_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ email_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int PHONES_FIELD_NUMBER = 4;
+ @SuppressWarnings("serial")
+ private java.util.List phones_;
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ @java.lang.Override
+ public java.util.List getPhonesList() {
+ return phones_;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ @java.lang.Override
+ public java.util.List extends com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder>
+ getPhonesOrBuilderList() {
+ return phones_;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ @java.lang.Override
+ public int getPhonesCount() {
+ return phones_.size();
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person.PhoneNumber getPhones(int index) {
+ return phones_.get(index);
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder getPhonesOrBuilder(
+ int index) {
+ return phones_.get(index);
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ if (((bitField0_ & 0x00000001) != 0)) {
+ output.writeInt32(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_);
+ }
+ if (((bitField0_ & 0x00000004) != 0)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 3, email_);
+ }
+ for (int i = 0; i < phones_.size(); i++) {
+ output.writeMessage(4, phones_.get(i));
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) != 0)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, name_);
+ }
+ if (((bitField0_ & 0x00000004) != 0)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, email_);
+ }
+ for (int i = 0; i < phones_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, phones_.get(i));
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.wdbyte.tool.protos.Person)) {
+ return super.equals(obj);
+ }
+ com.wdbyte.tool.protos.Person other = (com.wdbyte.tool.protos.Person) obj;
+
+ if (hasId() != other.hasId()) return false;
+ if (hasId()) {
+ if (getId()
+ != other.getId()) return false;
+ }
+ if (hasName() != other.hasName()) return false;
+ if (hasName()) {
+ if (!getName()
+ .equals(other.getName())) return false;
+ }
+ if (hasEmail() != other.hasEmail()) return false;
+ if (hasEmail()) {
+ if (!getEmail()
+ .equals(other.getEmail())) return false;
+ }
+ if (!getPhonesList()
+ .equals(other.getPhonesList())) return false;
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (hasId()) {
+ hash = (37 * hash) + ID_FIELD_NUMBER;
+ hash = (53 * hash) + getId();
+ }
+ if (hasName()) {
+ hash = (37 * hash) + NAME_FIELD_NUMBER;
+ hash = (53 * hash) + getName().hashCode();
+ }
+ if (hasEmail()) {
+ hash = (37 * hash) + EMAIL_FIELD_NUMBER;
+ hash = (53 * hash) + getEmail().hashCode();
+ }
+ if (getPhonesCount() > 0) {
+ hash = (37 * hash) + PHONES_FIELD_NUMBER;
+ hash = (53 * hash) + getPhonesList().hashCode();
+ }
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.Person parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.Person parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(com.wdbyte.tool.protos.Person prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ *
+ * 可选消息字段类型:bool int32 float double string
+ * 或者自定义消息类型,如下面的 PhoneNumber
+ * 修饰符:optional: 可选字段,
+ * 修饰符:repeated:可重复,如数组。
+ * 修饰符:required:必要字段,必须给值,否则会报错 RuntimeException,但是在 protobuf 版本 3 中被移除。
+ * 慎用 required,因为一旦被标记 requieds,以后将不能更改,否则可能会出问题。
+ *
+ *
+ * Protobuf type {@code com.wdbyte.protobuf.Person}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:com.wdbyte.protobuf.Person)
+ com.wdbyte.tool.protos.PersonOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.Person.class, com.wdbyte.tool.protos.Person.Builder.class);
+ }
+
+ // Construct using com.wdbyte.tool.protos.Person.newBuilder()
+ private Builder() {
+
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ bitField0_ = 0;
+ id_ = 0;
+ name_ = "";
+ email_ = "";
+ if (phonesBuilder_ == null) {
+ phones_ = java.util.Collections.emptyList();
+ } else {
+ phones_ = null;
+ phonesBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return com.wdbyte.tool.protos.AddressBookProtos.internal_static_com_wdbyte_protobuf_Person_descriptor;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person getDefaultInstanceForType() {
+ return com.wdbyte.tool.protos.Person.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person build() {
+ com.wdbyte.tool.protos.Person result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person buildPartial() {
+ com.wdbyte.tool.protos.Person result = new com.wdbyte.tool.protos.Person(this);
+ buildPartialRepeatedFields(result);
+ if (bitField0_ != 0) { buildPartial0(result); }
+ onBuilt();
+ return result;
+ }
+
+ private void buildPartialRepeatedFields(com.wdbyte.tool.protos.Person result) {
+ if (phonesBuilder_ == null) {
+ if (((bitField0_ & 0x00000008) != 0)) {
+ phones_ = java.util.Collections.unmodifiableList(phones_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.phones_ = phones_;
+ } else {
+ result.phones_ = phonesBuilder_.build();
+ }
+ }
+
+ private void buildPartial0(com.wdbyte.tool.protos.Person result) {
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) != 0)) {
+ result.id_ = id_;
+ to_bitField0_ |= 0x00000001;
+ }
+ if (((from_bitField0_ & 0x00000002) != 0)) {
+ result.name_ = name_;
+ to_bitField0_ |= 0x00000002;
+ }
+ if (((from_bitField0_ & 0x00000004) != 0)) {
+ result.email_ = email_;
+ to_bitField0_ |= 0x00000004;
+ }
+ result.bitField0_ |= to_bitField0_;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.wdbyte.tool.protos.Person) {
+ return mergeFrom((com.wdbyte.tool.protos.Person)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.wdbyte.tool.protos.Person other) {
+ if (other == com.wdbyte.tool.protos.Person.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasName()) {
+ name_ = other.name_;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ }
+ if (other.hasEmail()) {
+ email_ = other.email_;
+ bitField0_ |= 0x00000004;
+ onChanged();
+ }
+ if (phonesBuilder_ == null) {
+ if (!other.phones_.isEmpty()) {
+ if (phones_.isEmpty()) {
+ phones_ = other.phones_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensurePhonesIsMutable();
+ phones_.addAll(other.phones_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.phones_.isEmpty()) {
+ if (phonesBuilder_.isEmpty()) {
+ phonesBuilder_.dispose();
+ phonesBuilder_ = null;
+ phones_ = other.phones_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ phonesBuilder_ =
+ com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+ getPhonesFieldBuilder() : null;
+ } else {
+ phonesBuilder_.addAllMessages(other.phones_);
+ }
+ }
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 8: {
+ id_ = input.readInt32();
+ bitField0_ |= 0x00000001;
+ break;
+ } // case 8
+ case 18: {
+ name_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000002;
+ break;
+ } // case 18
+ case 26: {
+ email_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000004;
+ break;
+ } // case 26
+ case 34: {
+ com.wdbyte.tool.protos.Person.PhoneNumber m =
+ input.readMessage(
+ com.wdbyte.tool.protos.Person.PhoneNumber.parser(),
+ extensionRegistry);
+ if (phonesBuilder_ == null) {
+ ensurePhonesIsMutable();
+ phones_.add(m);
+ } else {
+ phonesBuilder_.addMessage(m);
+ }
+ break;
+ } // case 34
+ default: {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+ private int bitField0_;
+
+ private int id_ ;
+ /**
+ * optional int32 id = 1;
+ * @return Whether the id field is set.
+ */
+ @java.lang.Override
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ * optional int32 id = 1;
+ * @return The id.
+ */
+ @java.lang.Override
+ public int getId() {
+ return id_;
+ }
+ /**
+ * optional int32 id = 1;
+ * @param value The id to set.
+ * @return This builder for chaining.
+ */
+ public Builder setId(int value) {
+
+ id_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional int32 id = 1;
+ * @return This builder for chaining.
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0;
+ onChanged();
+ return this;
+ }
+
+ private java.lang.Object name_ = "";
+ /**
+ * optional string name = 2;
+ * @return Whether the name field is set.
+ */
+ public boolean hasName() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ * optional string name = 2;
+ * @return The name.
+ */
+ public java.lang.String getName() {
+ java.lang.Object ref = name_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ name_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string name = 2;
+ * @return The bytes for name.
+ */
+ public com.google.protobuf.ByteString
+ getNameBytes() {
+ java.lang.Object ref = name_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ name_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string name = 2;
+ * @param value The name to set.
+ * @return This builder for chaining.
+ */
+ public Builder setName(
+ java.lang.String value) {
+ if (value == null) { throw new NullPointerException(); }
+ name_ = value;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string name = 2;
+ * @return This builder for chaining.
+ */
+ public Builder clearName() {
+ name_ = getDefaultInstance().getName();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string name = 2;
+ * @param value The bytes for name to set.
+ * @return This builder for chaining.
+ */
+ public Builder setNameBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) { throw new NullPointerException(); }
+ checkByteStringIsUtf8(value);
+ name_ = value;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return this;
+ }
+
+ private java.lang.Object email_ = "";
+ /**
+ * optional string email = 3;
+ * @return Whether the email field is set.
+ */
+ public boolean hasEmail() {
+ return ((bitField0_ & 0x00000004) != 0);
+ }
+ /**
+ * optional string email = 3;
+ * @return The email.
+ */
+ public java.lang.String getEmail() {
+ java.lang.Object ref = email_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ email_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string email = 3;
+ * @return The bytes for email.
+ */
+ public com.google.protobuf.ByteString
+ getEmailBytes() {
+ java.lang.Object ref = email_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ email_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string email = 3;
+ * @param value The email to set.
+ * @return This builder for chaining.
+ */
+ public Builder setEmail(
+ java.lang.String value) {
+ if (value == null) { throw new NullPointerException(); }
+ email_ = value;
+ bitField0_ |= 0x00000004;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string email = 3;
+ * @return This builder for chaining.
+ */
+ public Builder clearEmail() {
+ email_ = getDefaultInstance().getEmail();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string email = 3;
+ * @param value The bytes for email to set.
+ * @return This builder for chaining.
+ */
+ public Builder setEmailBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) { throw new NullPointerException(); }
+ checkByteStringIsUtf8(value);
+ email_ = value;
+ bitField0_ |= 0x00000004;
+ onChanged();
+ return this;
+ }
+
+ private java.util.List phones_ =
+ java.util.Collections.emptyList();
+ private void ensurePhonesIsMutable() {
+ if (!((bitField0_ & 0x00000008) != 0)) {
+ phones_ = new java.util.ArrayList(phones_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.wdbyte.tool.protos.Person.PhoneNumber, com.wdbyte.tool.protos.Person.PhoneNumber.Builder, com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder> phonesBuilder_;
+
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public java.util.List getPhonesList() {
+ if (phonesBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(phones_);
+ } else {
+ return phonesBuilder_.getMessageList();
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public int getPhonesCount() {
+ if (phonesBuilder_ == null) {
+ return phones_.size();
+ } else {
+ return phonesBuilder_.getCount();
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public com.wdbyte.tool.protos.Person.PhoneNumber getPhones(int index) {
+ if (phonesBuilder_ == null) {
+ return phones_.get(index);
+ } else {
+ return phonesBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder setPhones(
+ int index, com.wdbyte.tool.protos.Person.PhoneNumber value) {
+ if (phonesBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePhonesIsMutable();
+ phones_.set(index, value);
+ onChanged();
+ } else {
+ phonesBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder setPhones(
+ int index, com.wdbyte.tool.protos.Person.PhoneNumber.Builder builderForValue) {
+ if (phonesBuilder_ == null) {
+ ensurePhonesIsMutable();
+ phones_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ phonesBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder addPhones(com.wdbyte.tool.protos.Person.PhoneNumber value) {
+ if (phonesBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePhonesIsMutable();
+ phones_.add(value);
+ onChanged();
+ } else {
+ phonesBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder addPhones(
+ int index, com.wdbyte.tool.protos.Person.PhoneNumber value) {
+ if (phonesBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePhonesIsMutable();
+ phones_.add(index, value);
+ onChanged();
+ } else {
+ phonesBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder addPhones(
+ com.wdbyte.tool.protos.Person.PhoneNumber.Builder builderForValue) {
+ if (phonesBuilder_ == null) {
+ ensurePhonesIsMutable();
+ phones_.add(builderForValue.build());
+ onChanged();
+ } else {
+ phonesBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder addPhones(
+ int index, com.wdbyte.tool.protos.Person.PhoneNumber.Builder builderForValue) {
+ if (phonesBuilder_ == null) {
+ ensurePhonesIsMutable();
+ phones_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ phonesBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder addAllPhones(
+ java.lang.Iterable extends com.wdbyte.tool.protos.Person.PhoneNumber> values) {
+ if (phonesBuilder_ == null) {
+ ensurePhonesIsMutable();
+ com.google.protobuf.AbstractMessageLite.Builder.addAll(
+ values, phones_);
+ onChanged();
+ } else {
+ phonesBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder clearPhones() {
+ if (phonesBuilder_ == null) {
+ phones_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ onChanged();
+ } else {
+ phonesBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public Builder removePhones(int index) {
+ if (phonesBuilder_ == null) {
+ ensurePhonesIsMutable();
+ phones_.remove(index);
+ onChanged();
+ } else {
+ phonesBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public com.wdbyte.tool.protos.Person.PhoneNumber.Builder getPhonesBuilder(
+ int index) {
+ return getPhonesFieldBuilder().getBuilder(index);
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder getPhonesOrBuilder(
+ int index) {
+ if (phonesBuilder_ == null) {
+ return phones_.get(index); } else {
+ return phonesBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public java.util.List extends com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder>
+ getPhonesOrBuilderList() {
+ if (phonesBuilder_ != null) {
+ return phonesBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(phones_);
+ }
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public com.wdbyte.tool.protos.Person.PhoneNumber.Builder addPhonesBuilder() {
+ return getPhonesFieldBuilder().addBuilder(
+ com.wdbyte.tool.protos.Person.PhoneNumber.getDefaultInstance());
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public com.wdbyte.tool.protos.Person.PhoneNumber.Builder addPhonesBuilder(
+ int index) {
+ return getPhonesFieldBuilder().addBuilder(
+ index, com.wdbyte.tool.protos.Person.PhoneNumber.getDefaultInstance());
+ }
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ public java.util.List
+ getPhonesBuilderList() {
+ return getPhonesFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.wdbyte.tool.protos.Person.PhoneNumber, com.wdbyte.tool.protos.Person.PhoneNumber.Builder, com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder>
+ getPhonesFieldBuilder() {
+ if (phonesBuilder_ == null) {
+ phonesBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+ com.wdbyte.tool.protos.Person.PhoneNumber, com.wdbyte.tool.protos.Person.PhoneNumber.Builder, com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder>(
+ phones_,
+ ((bitField0_ & 0x00000008) != 0),
+ getParentForChildren(),
+ isClean());
+ phones_ = null;
+ }
+ return phonesBuilder_;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:com.wdbyte.protobuf.Person)
+ }
+
+ // @@protoc_insertion_point(class_scope:com.wdbyte.protobuf.Person)
+ private static final com.wdbyte.tool.protos.Person DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new com.wdbyte.tool.protos.Person();
+ }
+
+ public static com.wdbyte.tool.protos.Person getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public Person parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.Person getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+}
+
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/PersonOrBuilder.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/PersonOrBuilder.java
new file mode 100644
index 0000000..6cfb178
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/PersonOrBuilder.java
@@ -0,0 +1,78 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: resources/addressbook.proto
+
+package com.wdbyte.tool.protos;
+
+public interface PersonOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:com.wdbyte.protobuf.Person)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * optional int32 id = 1;
+ * @return Whether the id field is set.
+ */
+ boolean hasId();
+ /**
+ * optional int32 id = 1;
+ * @return The id.
+ */
+ int getId();
+
+ /**
+ * optional string name = 2;
+ * @return Whether the name field is set.
+ */
+ boolean hasName();
+ /**
+ * optional string name = 2;
+ * @return The name.
+ */
+ java.lang.String getName();
+ /**
+ * optional string name = 2;
+ * @return The bytes for name.
+ */
+ com.google.protobuf.ByteString
+ getNameBytes();
+
+ /**
+ * optional string email = 3;
+ * @return Whether the email field is set.
+ */
+ boolean hasEmail();
+ /**
+ * optional string email = 3;
+ * @return The email.
+ */
+ java.lang.String getEmail();
+ /**
+ * optional string email = 3;
+ * @return The bytes for email.
+ */
+ com.google.protobuf.ByteString
+ getEmailBytes();
+
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ java.util.List
+ getPhonesList();
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ com.wdbyte.tool.protos.Person.PhoneNumber getPhones(int index);
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ int getPhonesCount();
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ java.util.List extends com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder>
+ getPhonesOrBuilderList();
+ /**
+ * repeated .com.wdbyte.protobuf.Person.PhoneNumber phones = 4;
+ */
+ com.wdbyte.tool.protos.Person.PhoneNumberOrBuilder getPhonesOrBuilder(
+ int index);
+}
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest1.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest1.java
new file mode 100644
index 0000000..d2f825a
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest1.java
@@ -0,0 +1,37 @@
+package com.wdbyte.tool.protos;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.wdbyte.tool.protos.Person.PhoneNumber;
+import com.wdbyte.tool.protos.Person.PhoneType;
+
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/05/07
+ */
+public class ProtobufTest1 {
+
+ public static void main(String[] args) {
+ // 直接构建
+ PhoneNumber phoneNumber1 = PhoneNumber.newBuilder().setNumber("18388888888").setType(PhoneType.HOME).build();
+ Person person1 = Person.newBuilder().setId(1).setName("www.wdbyte.com").setEmail("xxx@wdbyte.com").addPhones(phoneNumber1).build();
+ AddressBook addressBook1 = AddressBook.newBuilder().addPeople(person1).build();
+ System.out.println(addressBook1);
+ System.out.println("------------------");
+
+ // 链式构建
+ AddressBook addressBook2 = AddressBook
+ .newBuilder()
+ .addPeople(Person.newBuilder()
+ .setId(2)
+ .setName("www.wdbyte.com")
+ .setEmail("yyy@126.com")
+ .addPhones(PhoneNumber.newBuilder()
+ .setNumber("18388888888")
+ .setType(PhoneType.HOME)
+ )
+ )
+ .build();
+ System.out.println(addressBook2);
+ }
+}
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest2.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest2.java
new file mode 100644
index 0000000..0b3e236
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest2.java
@@ -0,0 +1,35 @@
+package com.wdbyte.tool.protos;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import com.wdbyte.tool.protos.Person.PhoneNumber;
+import com.wdbyte.tool.protos.Person.PhoneType;
+
+/**
+ *
+ * @author https://www.wdbyte.com
+ */
+public class ProtobufTest2 {
+
+ public static void main(String[] args) throws IOException {
+ PhoneNumber phoneNumber1 = PhoneNumber.newBuilder().setNumber("18388888888").setType(PhoneType.HOME).build();
+ Person person1 = Person.newBuilder().setId(1).setName("www.wdbyte.com").setEmail("xxx@wdbyte.com").addPhones(phoneNumber1).build();
+ AddressBook addressBook1 = AddressBook.newBuilder().addPeople(person1).build();
+
+ // 序列化成字节数组
+ byte[] byteArray = addressBook1.toByteArray();
+ // 反序列化 - 字节数组转对象
+ AddressBook addressBook2 = AddressBook.parseFrom(byteArray);
+ System.out.println("字节数组反序列化:");
+ System.out.println(addressBook2);
+
+ // 序列化到文件
+ addressBook1.writeTo(new FileOutputStream("AddressBook1.txt"));
+ // 读取文件反序列化
+ AddressBook addressBook3 = AddressBook.parseFrom(new FileInputStream("AddressBook1.txt"));
+ System.out.println("文件读取反序列化:");
+ System.out.println(addressBook3);
+ }
+}
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest3.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest3.java
new file mode 100644
index 0000000..6f3857c
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest3.java
@@ -0,0 +1,65 @@
+package com.wdbyte.tool.protos;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.alibaba.fastjson.JSON;
+
+import com.wdbyte.tool.protos.AddressBook.Builder;
+import com.wdbyte.tool.protos.AddressBookJava.PersonJava;
+import com.wdbyte.tool.protos.AddressBookJava.PhoneNumberJava;
+import com.wdbyte.tool.protos.AddressBookJava.PhoneTypeJava;
+import com.wdbyte.tool.protos.Person.PhoneNumber;
+import com.wdbyte.tool.protos.Person.PhoneType;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+public class ProtobufTest3 {
+
+ public static void main(String[] args) throws IOException {
+ AddressBookJava addressBookJava = createAddressBookJava(1000);
+ String jsonString = JSON.toJSONString(addressBookJava);
+ System.out.println("json string size:" + jsonString.length());
+
+ AddressBook addressBook = createAddressBook(1000);
+ byte[] addressBookByteArray = addressBook.toByteArray();
+ System.out.println("protobuf byte array size:" + addressBookByteArray.length);
+ }
+
+ public static AddressBook createAddressBook(int personCount) {
+ Builder builder = AddressBook.newBuilder();
+ for (int i = 0; i < personCount; i++) {
+ builder.addPeople(Person.newBuilder()
+ .setId(i)
+ .setName("www.wdbyte.com")
+ .setEmail("xxx@126.com")
+ .addPhones(PhoneNumber.newBuilder()
+ .setNumber("18333333333")
+ .setType(PhoneType.HOME)
+ )
+ );
+ }
+ return builder.build();
+ }
+
+ public static AddressBookJava createAddressBookJava(int personCount) {
+ AddressBookJava addressBookJava = new AddressBookJava();
+ addressBookJava.setPersonJavaList(new ArrayList<>());
+ for (int i = 0; i < personCount; i++) {
+ PersonJava personJava = new PersonJava();
+ personJava.setId(i);
+ personJava.setName("www.wdbyte.com");
+ personJava.setEmail("xxx@126.com");
+
+ PhoneNumberJava numberJava = new PhoneNumberJava();
+ numberJava.setNumber("18333333333");
+ numberJava.setPhoneTypeJava(PhoneTypeJava.HOME);
+
+ personJava.setPhones(numberJava);
+ addressBookJava.getPersonJavaList().add(personJava);
+ }
+ return addressBookJava;
+ }
+}
+
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest4.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest4.java
new file mode 100644
index 0000000..1437b42
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/ProtobufTest4.java
@@ -0,0 +1,97 @@
+package com.wdbyte.tool.protos;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+import com.alibaba.fastjson.JSON;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.wdbyte.tool.protos.AddressBook.Builder;
+import com.wdbyte.tool.protos.AddressBookJava.PersonJava;
+import com.wdbyte.tool.protos.AddressBookJava.PhoneNumberJava;
+import com.wdbyte.tool.protos.AddressBookJava.PhoneTypeJava;
+import com.wdbyte.tool.protos.Person.PhoneNumber;
+import com.wdbyte.tool.protos.Person.PhoneType;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * @author https://www.wdbyte.com
+ */
+@State(Scope.Thread)
+@Fork(2)
+@Warmup(iterations = 3, time = 3)
+@Measurement(iterations = 5, time = 3)
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+public class ProtobufTest4 {
+
+ private AddressBookJava addressBookJava;
+ private AddressBook addressBook;
+
+ @Setup
+ public void init() {
+ addressBookJava = createAddressBookJava(1000);
+ addressBook = createAddressBook(1000);
+ }
+
+ @Benchmark
+ public AddressBookJava testJSON() {
+ // 转 JSON
+ String jsonString = JSON.toJSONString(addressBookJava);
+ // JSON 转对象
+ return JSON.parseObject(jsonString, AddressBookJava.class);
+ }
+
+ @Benchmark
+ public AddressBook testProtobuf() throws InvalidProtocolBufferException {
+ // 转 JSON
+ byte[] addressBookByteArray = addressBook.toByteArray();
+ // JSON 转对象
+ return AddressBook.parseFrom(addressBookByteArray);
+ }
+
+ public static AddressBook createAddressBook(int personCount) {
+ Builder builder = AddressBook.newBuilder();
+ for (int i = 0; i < personCount; i++) {
+ builder.addPeople(Person.newBuilder()
+ .setId(i)
+ .setName("www.wdbyte.com")
+ .setEmail("xxx@126.com")
+ .addPhones(PhoneNumber.newBuilder()
+ .setNumber("18333333333")
+ .setType(PhoneType.HOME)
+ )
+ );
+ }
+ return builder.build();
+ }
+
+ public static AddressBookJava createAddressBookJava(int personCount) {
+ AddressBookJava addressBookJava = new AddressBookJava();
+ addressBookJava.setPersonJavaList(new ArrayList<>());
+ for (int i = 0; i < personCount; i++) {
+ PersonJava personJava = new PersonJava();
+ personJava.setId(i);
+ personJava.setName("www.wdbyte.com");
+ personJava.setEmail("xxx@126.com");
+
+ PhoneNumberJava numberJava = new PhoneNumberJava();
+ numberJava.setNumber("18333333333");
+ numberJava.setPhoneTypeJava(PhoneTypeJava.HOME);
+
+ personJava.setPhones(numberJava);
+ addressBookJava.getPersonJavaList().add(personJava);
+ }
+ return addressBookJava;
+ }
+}
+
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/StudentOuterClass.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/StudentOuterClass.java
new file mode 100644
index 0000000..c8c29e2
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/StudentOuterClass.java
@@ -0,0 +1,770 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: resources/student.proto
+
+package com.wdbyte.tool.protos;
+
+public final class StudentOuterClass {
+ private StudentOuterClass() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registerAllExtensions(
+ (com.google.protobuf.ExtensionRegistryLite) registry);
+ }
+ public interface StudentOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:com.wdbyte.protobuf.Student)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * optional string id = 1;
+ * @return Whether the id field is set.
+ */
+ boolean hasId();
+ /**
+ * optional string id = 1;
+ * @return The id.
+ */
+ java.lang.String getId();
+ /**
+ * optional string id = 1;
+ * @return The bytes for id.
+ */
+ com.google.protobuf.ByteString
+ getIdBytes();
+
+ /**
+ * optional string name = 2;
+ * @return Whether the name field is set.
+ */
+ boolean hasName();
+ /**
+ * optional string name = 2;
+ * @return The name.
+ */
+ java.lang.String getName();
+ /**
+ * optional string name = 2;
+ * @return The bytes for name.
+ */
+ com.google.protobuf.ByteString
+ getNameBytes();
+ }
+ /**
+ * Protobuf type {@code com.wdbyte.protobuf.Student}
+ */
+ public static final class Student extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:com.wdbyte.protobuf.Student)
+ StudentOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use Student.newBuilder() to construct.
+ private Student(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private Student() {
+ id_ = "";
+ name_ = "";
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new Student();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.StudentOuterClass.internal_static_com_wdbyte_protobuf_Student_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.StudentOuterClass.internal_static_com_wdbyte_protobuf_Student_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.StudentOuterClass.Student.class, com.wdbyte.tool.protos.StudentOuterClass.Student.Builder.class);
+ }
+
+ private int bitField0_;
+ public static final int ID_FIELD_NUMBER = 1;
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object id_ = "";
+ /**
+ * optional string id = 1;
+ * @return Whether the id field is set.
+ */
+ @java.lang.Override
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ * optional string id = 1;
+ * @return The id.
+ */
+ @java.lang.Override
+ public java.lang.String getId() {
+ java.lang.Object ref = id_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ id_ = s;
+ return s;
+ }
+ }
+ /**
+ * optional string id = 1;
+ * @return The bytes for id.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString
+ getIdBytes() {
+ java.lang.Object ref = id_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ id_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int NAME_FIELD_NUMBER = 2;
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object name_ = "";
+ /**
+ * optional string name = 2;
+ * @return Whether the name field is set.
+ */
+ @java.lang.Override
+ public boolean hasName() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ * optional string name = 2;
+ * @return The name.
+ */
+ @java.lang.Override
+ public java.lang.String getName() {
+ java.lang.Object ref = name_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ name_ = s;
+ return s;
+ }
+ }
+ /**
+ * optional string name = 2;
+ * @return The bytes for name.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString
+ getNameBytes() {
+ java.lang.Object ref = name_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ name_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ if (((bitField0_ & 0x00000001) != 0)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 1, id_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) != 0)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) != 0)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, name_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.wdbyte.tool.protos.StudentOuterClass.Student)) {
+ return super.equals(obj);
+ }
+ com.wdbyte.tool.protos.StudentOuterClass.Student other = (com.wdbyte.tool.protos.StudentOuterClass.Student) obj;
+
+ if (hasId() != other.hasId()) return false;
+ if (hasId()) {
+ if (!getId()
+ .equals(other.getId())) return false;
+ }
+ if (hasName() != other.hasName()) return false;
+ if (hasName()) {
+ if (!getName()
+ .equals(other.getName())) return false;
+ }
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (hasId()) {
+ hash = (37 * hash) + ID_FIELD_NUMBER;
+ hash = (53 * hash) + getId().hashCode();
+ }
+ if (hasName()) {
+ hash = (37 * hash) + NAME_FIELD_NUMBER;
+ hash = (53 * hash) + getName().hashCode();
+ }
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(com.wdbyte.tool.protos.StudentOuterClass.Student prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code com.wdbyte.protobuf.Student}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:com.wdbyte.protobuf.Student)
+ com.wdbyte.tool.protos.StudentOuterClass.StudentOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.wdbyte.tool.protos.StudentOuterClass.internal_static_com_wdbyte_protobuf_Student_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.wdbyte.tool.protos.StudentOuterClass.internal_static_com_wdbyte_protobuf_Student_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.wdbyte.tool.protos.StudentOuterClass.Student.class, com.wdbyte.tool.protos.StudentOuterClass.Student.Builder.class);
+ }
+
+ // Construct using com.wdbyte.tool.protos.StudentOuterClass.Student.newBuilder()
+ private Builder() {
+
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ bitField0_ = 0;
+ id_ = "";
+ name_ = "";
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return com.wdbyte.tool.protos.StudentOuterClass.internal_static_com_wdbyte_protobuf_Student_descriptor;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.StudentOuterClass.Student getDefaultInstanceForType() {
+ return com.wdbyte.tool.protos.StudentOuterClass.Student.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.StudentOuterClass.Student build() {
+ com.wdbyte.tool.protos.StudentOuterClass.Student result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.StudentOuterClass.Student buildPartial() {
+ com.wdbyte.tool.protos.StudentOuterClass.Student result = new com.wdbyte.tool.protos.StudentOuterClass.Student(this);
+ if (bitField0_ != 0) { buildPartial0(result); }
+ onBuilt();
+ return result;
+ }
+
+ private void buildPartial0(com.wdbyte.tool.protos.StudentOuterClass.Student result) {
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) != 0)) {
+ result.id_ = id_;
+ to_bitField0_ |= 0x00000001;
+ }
+ if (((from_bitField0_ & 0x00000002) != 0)) {
+ result.name_ = name_;
+ to_bitField0_ |= 0x00000002;
+ }
+ result.bitField0_ |= to_bitField0_;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.wdbyte.tool.protos.StudentOuterClass.Student) {
+ return mergeFrom((com.wdbyte.tool.protos.StudentOuterClass.Student)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.wdbyte.tool.protos.StudentOuterClass.Student other) {
+ if (other == com.wdbyte.tool.protos.StudentOuterClass.Student.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ id_ = other.id_;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ }
+ if (other.hasName()) {
+ name_ = other.name_;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10: {
+ id_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000001;
+ break;
+ } // case 10
+ case 18: {
+ name_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000002;
+ break;
+ } // case 18
+ default: {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+ private int bitField0_;
+
+ private java.lang.Object id_ = "";
+ /**
+ * optional string id = 1;
+ * @return Whether the id field is set.
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ * optional string id = 1;
+ * @return The id.
+ */
+ public java.lang.String getId() {
+ java.lang.Object ref = id_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ id_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string id = 1;
+ * @return The bytes for id.
+ */
+ public com.google.protobuf.ByteString
+ getIdBytes() {
+ java.lang.Object ref = id_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ id_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string id = 1;
+ * @param value The id to set.
+ * @return This builder for chaining.
+ */
+ public Builder setId(
+ java.lang.String value) {
+ if (value == null) { throw new NullPointerException(); }
+ id_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string id = 1;
+ * @return This builder for chaining.
+ */
+ public Builder clearId() {
+ id_ = getDefaultInstance().getId();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string id = 1;
+ * @param value The bytes for id to set.
+ * @return This builder for chaining.
+ */
+ public Builder setIdBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) { throw new NullPointerException(); }
+ checkByteStringIsUtf8(value);
+ id_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+
+ private java.lang.Object name_ = "";
+ /**
+ * optional string name = 2;
+ * @return Whether the name field is set.
+ */
+ public boolean hasName() {
+ return ((bitField0_ & 0x00000002) != 0);
+ }
+ /**
+ * optional string name = 2;
+ * @return The name.
+ */
+ public java.lang.String getName() {
+ java.lang.Object ref = name_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ name_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string name = 2;
+ * @return The bytes for name.
+ */
+ public com.google.protobuf.ByteString
+ getNameBytes() {
+ java.lang.Object ref = name_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ name_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string name = 2;
+ * @param value The name to set.
+ * @return This builder for chaining.
+ */
+ public Builder setName(
+ java.lang.String value) {
+ if (value == null) { throw new NullPointerException(); }
+ name_ = value;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string name = 2;
+ * @return This builder for chaining.
+ */
+ public Builder clearName() {
+ name_ = getDefaultInstance().getName();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string name = 2;
+ * @param value The bytes for name to set.
+ * @return This builder for chaining.
+ */
+ public Builder setNameBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) { throw new NullPointerException(); }
+ checkByteStringIsUtf8(value);
+ name_ = value;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return this;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:com.wdbyte.protobuf.Student)
+ }
+
+ // @@protoc_insertion_point(class_scope:com.wdbyte.protobuf.Student)
+ private static final com.wdbyte.tool.protos.StudentOuterClass.Student DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new com.wdbyte.tool.protos.StudentOuterClass.Student();
+ }
+
+ public static com.wdbyte.tool.protos.StudentOuterClass.Student getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public Student parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.wdbyte.tool.protos.StudentOuterClass.Student getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_com_wdbyte_protobuf_Student_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_com_wdbyte_protobuf_Student_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\027resources/student.proto\022\023com.wdbyte.pr" +
+ "otobuf\"=\n\007Student\022\017\n\002id\030\001 \001(\tH\000\210\001\001\022\021\n\004na" +
+ "me\030\002 \001(\tH\001\210\001\001B\005\n\003_idB\007\n\005_nameB\032\n\026com.wdb" +
+ "yte.tool.protosP\000b\006proto3"
+ };
+ descriptor = com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ });
+ internal_static_com_wdbyte_protobuf_Student_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_com_wdbyte_protobuf_Student_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_com_wdbyte_protobuf_Student_descriptor,
+ new java.lang.String[] { "Id", "Name", "Id", "Name", });
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/StudentTest.java b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/StudentTest.java
new file mode 100644
index 0000000..041a689
--- /dev/null
+++ b/tool-java-protobuf/src/main/java/com/wdbyte/tool/protos/StudentTest.java
@@ -0,0 +1,17 @@
+package com.wdbyte.tool.protos;
+
+import java.util.Arrays;
+
+import com.wdbyte.tool.protos.StudentOuterClass.Student;
+
+/**
+ * @author https://www.wdbyte.com
+ * @date 2023/05/10
+ */
+public class StudentTest {
+
+ public static void main(String[] args) {
+ Student student = Student.newBuilder().setId("1").setName("AB").build();
+ System.out.println(Arrays.toString(student.toByteArray()));
+ }
+}
diff --git a/tool-java-protobuf/src/main/resources/addressbook.proto b/tool-java-protobuf/src/main/resources/addressbook.proto
new file mode 100644
index 0000000..cbe93a9
--- /dev/null
+++ b/tool-java-protobuf/src/main/resources/addressbook.proto
@@ -0,0 +1,37 @@
+syntax = "proto3";
+// 指定 protobuf 包名,防止有相同类名的 message 定义
+package com.wdbyte.protobuf;
+// 是否生成多个文件
+option java_multiple_files = true;
+// 生成的文件存放在哪个包下
+option java_package = "com.wdbyte.tool.protos";
+// 生成的类名,如果没有指定,会根据文件名自动转驼峰来命名
+option java_outer_classname = "AddressBookProtos";
+// 可选消息字段类型:bool int32 float double string
+// 或者自定义消息类型,如下面的 PhoneNumber
+// 修饰符:optional: 可选字段,
+// 修饰符:repeated:可重复,如数组。
+// 修饰符:required:必要字段,必须给值,否则会报错 RuntimeException,但是在 protobuf 版本 3 中被移除。
+// 慎用 required,因为一旦被标记 requieds,以后将不能更改,否则可能会出问题。
+message Person {
+ optional int32 id = 1;
+ optional string name = 2;
+ optional string email = 3;
+
+ enum PhoneType {
+ MOBILE = 0;
+ HOME = 1;
+ WORK = 2;
+ }
+
+ message PhoneNumber {
+ optional string number = 1;
+ optional PhoneType type = 2;
+ }
+
+ repeated PhoneNumber phones = 4;
+}
+
+message AddressBook {
+ repeated Person people = 1;
+}
\ No newline at end of file
diff --git a/tool-java-protobuf/src/main/resources/student.proto b/tool-java-protobuf/src/main/resources/student.proto
new file mode 100644
index 0000000..d656f75
--- /dev/null
+++ b/tool-java-protobuf/src/main/resources/student.proto
@@ -0,0 +1,14 @@
+syntax = "proto3";
+// 指定 protobuf 包名,防止有相同类名的 message 定义
+package com.wdbyte.protobuf;
+// 是否生成多个文件
+option java_multiple_files = false;
+// 生成的文件存放在哪个包下
+option java_package = "com.wdbyte.tool.protos";
+// 生成的类名,如果没有指定,会根据文件名自动转驼峰来命名
+//option java_outer_classname = "Student";
+
+message Student{
+ optional string id = 1;
+ optional string name = 2;
+}
\ No newline at end of file
diff --git a/core-java-rate-limiter/README.md b/tool-java-rate-limiter/README.md
similarity index 100%
rename from core-java-rate-limiter/README.md
rename to tool-java-rate-limiter/README.md
diff --git a/core-java-rate-limiter/pom.xml b/tool-java-rate-limiter/pom.xml
similarity index 92%
rename from core-java-rate-limiter/pom.xml
rename to tool-java-rate-limiter/pom.xml
index 9679d8d..9b92fde 100644
--- a/core-java-rate-limiter/pom.xml
+++ b/tool-java-rate-limiter/pom.xml
@@ -10,7 +10,7 @@
4.0.0
com.wdbyte.rate.limiter
- core-java-rate-limiter
+ tool-java-rate-limiter
17
diff --git a/core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterGuava.java b/tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterGuava.java
similarity index 100%
rename from core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterGuava.java
rename to tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterGuava.java
diff --git a/core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSildingLog.java b/tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSildingLog.java
similarity index 100%
rename from core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSildingLog.java
rename to tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSildingLog.java
diff --git a/core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow.java b/tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow.java
similarity index 100%
rename from core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow.java
rename to tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow.java
diff --git a/core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow0.java b/tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow0.java
similarity index 100%
rename from core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow0.java
rename to tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSimpleWindow0.java
diff --git a/core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSlidingWindow.java b/tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSlidingWindow.java
similarity index 100%
rename from core-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSlidingWindow.java
rename to tool-java-rate-limiter/src/main/java/com/wdbyte/rate/limiter/RateLimiterSlidingWindow.java
diff --git a/core-java-rate-limiter/src/main/resources/limiter.lua b/tool-java-rate-limiter/src/main/resources/limiter.lua
similarity index 100%
rename from core-java-rate-limiter/src/main/resources/limiter.lua
rename to tool-java-rate-limiter/src/main/resources/limiter.lua
diff --git a/core-java-rate-limiter/src/main/resources/limiter2.lua b/tool-java-rate-limiter/src/main/resources/limiter2.lua
similarity index 100%
rename from core-java-rate-limiter/src/main/resources/limiter2.lua
rename to tool-java-rate-limiter/src/main/resources/limiter2.lua
diff --git a/core-java-rate-limiter/src/test/java/RedisLuaLimiterByIncr.java b/tool-java-rate-limiter/src/test/java/RedisLuaLimiterByIncr.java
similarity index 100%
rename from core-java-rate-limiter/src/test/java/RedisLuaLimiterByIncr.java
rename to tool-java-rate-limiter/src/test/java/RedisLuaLimiterByIncr.java
diff --git a/core-java-rate-limiter/src/test/java/RedisLuaLimiterByZset.java b/tool-java-rate-limiter/src/test/java/RedisLuaLimiterByZset.java
similarity index 100%
rename from core-java-rate-limiter/src/test/java/RedisLuaLimiterByZset.java
rename to tool-java-rate-limiter/src/test/java/RedisLuaLimiterByZset.java