├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── JUC └── src │ └── cn │ └── chendapeng │ └── juc │ ├── NiubilityContainer.java │ ├── TestCountDownLatch.java │ ├── TestCyclicBarrier.java │ └── TestSemaphore.java ├── ObjectSizeAgent ├── META-INF │ └── MANIFEST.MF └── src │ └── cn │ └── chendapeng │ └── agent │ └── ObjectSizeAgent.java ├── README.md ├── design-patterns ├── design-patterns.iml ├── pom.xml └── src │ └── main │ ├── java │ └── cn │ │ └── chendapeng │ │ └── dp │ │ ├── abstractfactory │ │ ├── BaseFactory.java │ │ ├── Client.java │ │ ├── FaceMask.java │ │ ├── Food.java │ │ ├── HumanFactory.java │ │ ├── Junk.java │ │ ├── ProtectiveEquip.java │ │ ├── Rags.java │ │ ├── Rice.java │ │ └── UsaFactory.java │ │ ├── chainofresposibility │ │ ├── servlet │ │ │ └── Client.java │ │ ├── v1 │ │ │ └── Client.java │ │ ├── v2 │ │ │ └── Client.java │ │ └── v3 │ │ │ └── Client.java │ │ ├── facade │ │ ├── CheckDept.java │ │ ├── Client.java │ │ ├── IssueDept.java │ │ ├── NetApp.java │ │ └── StuffDept.java │ │ ├── factorymethod │ │ ├── Client.java │ │ ├── FaceMask.java │ │ ├── FaceMaskFactory.java │ │ ├── HandMask.java │ │ ├── ProtectiveEquip.java │ │ └── SimpleProtectiveEquipFactory.java │ │ ├── observer │ │ ├── MyFrame.java │ │ ├── v1 │ │ │ └── Client.java │ │ ├── v2 │ │ │ └── Client.java │ │ └── v3 │ │ │ └── Client.java │ │ ├── proxy │ │ ├── cglib │ │ │ └── Main.java │ │ ├── dynamicproxy │ │ │ ├── Painter.java │ │ │ ├── Pony.java │ │ │ ├── Teacher.java │ │ │ └── TimeProxyHandler.java │ │ ├── springaop │ │ │ ├── LogProxy.java │ │ │ ├── Pony.java │ │ │ └── Teacher.java │ │ └── staticproxy │ │ │ ├── LogProxy.java │ │ │ ├── Painter.java │ │ │ ├── Pony.java │ │ │ ├── Puppy.java │ │ │ ├── Teacher.java │ │ │ ├── TimeProxy.java │ │ │ └── TimeProxyHandler.java │ │ └── singleton │ │ ├── Main.java │ │ ├── Singleton_1.java │ │ ├── Singleton_2.java │ │ ├── Singleton_3.java │ │ ├── Singleton_4.java │ │ ├── Singleton_5.java │ │ ├── Singleton_6.java │ │ ├── Singleton_7.java │ │ └── Singleton_8.java │ └── resources │ ├── app.xml │ └── app_aop.xml ├── fastdfs ├── pom.xml └── src │ └── main │ ├── java │ └── cn │ │ └── chendapeng │ │ └── fastdfs │ │ └── utils │ │ └── FastDfsClient.java │ └── resources │ └── fdfs_client.conf ├── shardingsphere ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── cn │ │ │ └── chendapeng │ │ │ └── shardingsphere │ │ │ ├── ShardingsphereApplication.java │ │ │ ├── bean │ │ │ └── Laogong.java │ │ │ └── mapper │ │ │ └── LaogongMapper.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── xblzer │ └── shardingsphere │ └── ShardingsphereApplicationTests.java ├── tryout ├── pom.xml └── src │ └── main │ └── java │ └── cn │ └── chendapeng │ └── tryout │ ├── CreateObjectTest.java │ ├── OOMTest.java │ ├── ObjectSizeTest.java │ └── bean │ └── User.java └── zookeeper ├── .gitignore ├── pom.xml └── src ├── main └── java │ └── cn │ └── chendapeng │ └── zookeeper │ └── config │ ├── DefaultWatcher.java │ ├── MyConfig.java │ └── WatchAndCallback.java └── test └── java └── cn └── chendapeng └── zookeeper └── ZooKeeperConfigTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenDapengJava/JavaJourney/5116a7506bb433ca43551a057c3163b73038a328/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /JUC/src/cn/chendapeng/juc/NiubilityContainer.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.juc; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 行百里者 8 | * @date 2022-08-05 10:29 9 | */ 10 | public class NiubilityContainer { 11 | private List list = new ArrayList<>(); 12 | 13 | /** 14 | * add方法,借用list的add方法相容器添加元素 15 | * 16 | * @param t 待添加的元素 17 | */ 18 | public void add(T t) { 19 | list.add(t); 20 | } 21 | 22 | /** 23 | * 借助list的size方法返回当前容器的元素个数 24 | * 25 | * @return int 容器元素个数 26 | */ 27 | public int size() { 28 | return list.size(); 29 | } 30 | 31 | public static void main(String[] args) { 32 | NiubilityContainer c = new NiubilityContainer(); 33 | //定义一个需要上锁的对象,线程持有该对象的锁才能执行 34 | final Object lock = new Object(); 35 | 36 | //启动一个监控线程 37 | new Thread(() -> { 38 | System.out.println("监控线程启动..."); 39 | synchronized (lock) { 40 | //只要元素个数不为5,就调用wait方法让出CPU 41 | if (c.size() != 5) { 42 | try { 43 | lock.wait(); 44 | } catch (InterruptedException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | //通知添加元素的线程继续执行 49 | lock.notify(); 50 | } 51 | System.out.println("容器元素个数为5,监控线程退出!"); 52 | }, "MonitorThread").start(); 53 | 54 | //启动一个添加元素的线程 55 | new Thread(() -> { 56 | System.out.println("添加元素线程启动..."); 57 | synchronized (lock) { 58 | for (int i = 0; i < 10; i++) { 59 | c.add(i); 60 | System.out.println("添加元素线程 add " + i); 61 | 62 | if (c.size() == 5) { 63 | //先唤醒当前线程 64 | lock.notify(); 65 | try { 66 | //释放锁,使得监控线程得以执行 67 | lock.wait(); 68 | } catch (InterruptedException e) { 69 | e.printStackTrace(); 70 | } 71 | } 72 | } 73 | } 74 | }, "AddThread").start(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /JUC/src/cn/chendapeng/juc/TestCountDownLatch.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.juc; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.concurrent.CountDownLatch; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * @author 行百里者 10 | * @date 2022-08-05 10:33 11 | */ 12 | public class TestCountDownLatch { 13 | 14 | static CountDownLatch latch = new CountDownLatch(1); 15 | static List lists = new LinkedList(); 16 | 17 | 18 | static void add(Object o) { 19 | lists.add(o); 20 | } 21 | 22 | static int size() { 23 | return lists.size(); 24 | } 25 | 26 | static class ReactThread extends Thread { 27 | @Override 28 | public void run() { 29 | try { 30 | latch.await(); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | System.out.println("============== 元素个数已到达5,监控退出!============="); 35 | } 36 | } 37 | 38 | static class AddThread extends Thread { 39 | @Override 40 | public void run() { 41 | for (int i = 1; i < 11; i++) { 42 | add(new Object()); 43 | System.out.println("添加元素线程 add 第" + i + "个元素"); 44 | 45 | if (size() == 5) { 46 | latch.countDown(); 47 | } 48 | 49 | //(监控线程已经准备打印退出了,添加元素的线程还在继续添加) 50 | //加个睡眠时间,方便观察,因为打印的动作也需要耗时 51 | try { 52 | TimeUnit.MILLISECONDS.sleep(100); 53 | } catch (InterruptedException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | } 58 | } 59 | 60 | public static void main(String[] args) { 61 | new ReactThread().start(); 62 | new AddThread().start(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /JUC/src/cn/chendapeng/juc/TestCyclicBarrier.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.juc; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.concurrent.BrokenBarrierException; 6 | import java.util.concurrent.CyclicBarrier; 7 | 8 | /** 9 | * @author 行百里者 10 | * @date 2022-08-05 10:30 11 | */ 12 | public class TestCyclicBarrier { 13 | 14 | static CyclicBarrier barrier; 15 | static List lists = new LinkedList(); 16 | 17 | 18 | static void add(Object o) { 19 | lists.add(o); 20 | } 21 | 22 | static int size() { 23 | return lists.size(); 24 | } 25 | 26 | static class ReactThread implements Runnable { 27 | @Override 28 | public void run() { 29 | System.out.println("============== 元素个数已到达5,监控退出!============="); 30 | } 31 | } 32 | 33 | static class AddThread extends Thread { 34 | @Override 35 | public void run() { 36 | for (int i = 1; i < 11; i++) { 37 | add(new Object()); 38 | System.out.println("添加元素线程 add 第" + i + "个元素"); 39 | 40 | if (size() == 5) { 41 | try { 42 | barrier.await(); 43 | } catch (InterruptedException | BrokenBarrierException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | 51 | public static void main(String[] args) { 52 | barrier = new CyclicBarrier(1, new ReactThread()); 53 | new AddThread().start(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /JUC/src/cn/chendapeng/juc/TestSemaphore.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.juc; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.concurrent.Semaphore; 6 | 7 | /** 8 | * @author 行百里者 9 | * @date 2022-08-05 11:13 10 | */ 11 | public class TestSemaphore { 12 | static List lists = new LinkedList(); 13 | 14 | static void add(Object o) { 15 | lists.add(o); 16 | } 17 | 18 | static int size() { 19 | return lists.size(); 20 | } 21 | 22 | static Thread t1 = null, t2 = null; 23 | 24 | public static void main(String[] args) { 25 | //定义一个只能有1个线程能获得许可的信号量 26 | Semaphore semaphore = new Semaphore(1); 27 | 28 | t1 = new Thread(() -> { 29 | try { 30 | //尝试获得许可 31 | semaphore.acquire(); 32 | //添加5个元素之后,释放锁 33 | for (int i = 0; i < 5; i++) { 34 | add(new Object()); 35 | System.out.println("线程t1 已经 add " + size() + " 个元素"); 36 | } 37 | //释放锁,等待t2打印退出 38 | semaphore.release(); 39 | 40 | //需要让t2执行 41 | t2.start(); 42 | t2.join(); 43 | 44 | //t2退出后,继续获得许可,添加元素 45 | semaphore.acquire(); 46 | for (int i = 0; i < 5; i++) { 47 | add(new Object()); 48 | System.out.println("线程t1 已经 add " + size() + " 个元素"); 49 | } 50 | } catch (InterruptedException e) { 51 | e.printStackTrace(); 52 | } 53 | }); 54 | 55 | t2 = new Thread(() -> { 56 | try { 57 | //首先获得许可 58 | semaphore.acquire(); 59 | //打印 退出 60 | System.out.println("------- 线程t2已知容器中有5个元素了,t2退出。-------"); 61 | //释放锁,等t1接着添加剩余的元素 62 | semaphore.release(); 63 | } catch (InterruptedException e) { 64 | e.printStackTrace(); 65 | } 66 | }); 67 | 68 | t1.start(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ObjectSizeAgent/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Premain-Class: cn.chendapeng.agent.ObjectSizeAgent 3 | -------------------------------------------------------------------------------- /ObjectSizeAgent/src/cn/chendapeng/agent/ObjectSizeAgent.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.agent; 2 | 3 | import java.lang.instrument.Instrumentation; 4 | 5 | /** 6 | * 探测对象占用字节数的Agent 7 | * 8 | * @author 行百里者 9 | * @since 2020/11/03 11:10 10 | **/ 11 | public class ObjectSizeAgent { 12 | //Java内部字节码处理调试用的是Instrumentation 13 | //所以在使用代理装到我们jvm的时候可以截获这个Instrumentation 14 | private static Instrumentation inst; 15 | 16 | /** 17 | * 必须要有premain函数 18 | * 参数固定 19 | * 第二个参数就是Instrumentation,这个是虚拟机调用的,会自动帮我们初始化Instrumentation 20 | * 在这里通过给自己定义的成员变量赋值,赋完值就能拿到Instrumentation 21 | * 22 | * @param agentArgs 23 | * @param _inst 24 | */ 25 | public static void premain(String agentArgs, Instrumentation _inst) { 26 | inst = _inst; 27 | } 28 | 29 | /** 30 | * 在premain里拿到Instrumentation后,可以调用getObjectSize获取对象大小 31 | * 32 | * @param o 待测定的对象 33 | * @return 对象大小 34 | */ 35 | public static long sizeOf(Object o) { 36 | return inst.getObjectSize(o); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaJourney 2 | 积小流以成江海,积跬步以至千里。 3 | 4 | 本开源项目主攻Java相关技术栈,把平时积累的点点滴滴汇聚到这里来,既是总结也是分享。 5 | 6 | **文章都是原创,手敲不易,您的一个star,是我永远的动力!** 7 | 8 | 文章首发公众号`行百里er`,欢迎关注。 9 | 10 | ![扫码关注,给个鼓励吧](https://gitee.com/xblzer/picture/raw/master/2020-10-29/1603936988710-%E4%BA%8C%E7%BB%B4%E7%A0%81.jpg) 11 | 12 | 13 | 14 | ### 不断更新的目录 15 | 16 | - 架构师必备 17 | 18 | [Java后端?面试官真问了Linux命令!](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001980&idx=1&sn=1c0550210a0db5baad62f51e2252c987&chksm=69813f845ef6b692170640cff5e97a6bd94a9b2b42fbac093c6de86a4994eb1c9996a10e739c#rd) 19 | 20 | [手摸手助你从零开始搭建etcd集群](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100002150&idx=1&sn=98a36e80c931c3de4d63e7ae535bdb15&chksm=69813e5e5ef6b7482e160226c641bab1716d14823fafc0d0fabc5aeca01abc2676fcc9c24d64#rd) 21 | 22 | [用etcd实现比Redis更骚的分布式锁](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100002197&idx=1&sn=18eccce8af40256e0c6bd2d9544d9380&chksm=69813ead5ef6b7bb6dd6f866eeb9b7725b6d53ac45a339be41e4a675b67243b3ebd1c6477511#rd) 23 | 24 | [MySQL高可用之主从复制原理及实现](https://t.1yb.co/9IE4) 25 | 26 | [基于Sharding-JDBC的MySQL读写分离](https://t.1yb.co/9IEE) 27 | 28 | [还在手动维护API文档吗?是时候用用丝袜哥(swagger)了!](https://t.1yb.co/qv06) 29 | 30 | [接口管理 | 除了swagger,还有Yapi这种接口管理的利器!](https://t.1yb.co/srgM) 31 | 32 | [分布式配置中心之Apollo实战](https://t.1yb.co/trqy) 33 | 34 | - GC系列 35 | 36 | [【GC系列】JVM垃圾定位及垃圾回收算法浅析](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100002408&idx=1&sn=8385f11f1160c6a141302dfe33b9658e&chksm=69813d505ef6b4464f1a727fa1b1c7599e24c81b5c44027edc1901d03b04b36b0e2a84fb9a87#rd) 37 | 38 | [【GC系列】JVM堆内存分代模型及常见的垃圾回收器](https://t.1yb.co/82C5) 39 | 40 | [【GC系列】JVM的常用GC参数及GC日志解析](https://t.1yb.co/82Cs) 41 | 42 | - Java基础 43 | 44 | [Object o = new Object()在内存中占多少字节?](https://t.1yb.co/quYj) 45 | 46 | [Java8新特性Stream还有这种操作?](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001184&idx=1&sn=1e5895d286ad138c37e23a206d83cecb&chksm=698132985ef6bb8e06ba1890e3688361179a449577bf0547a19e9f340b779410346c5bd6d08d#rd) 47 | 48 | [终于看懂别人的代码了!总结Java 8之Lambda表达式的写法套路](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001223&idx=1&sn=23e835628012fb5b66117f04412ea41a&chksm=698132ff5ef6bbe97750283664efe0145b90dac97fb8008b5c7e8be5775bdad23e8ea430fad5#rd) 49 | 50 | [【优雅的避坑】避免HashMap扩容的正确姿势](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001845&idx=1&sn=c8fb86be33337836737da95f5813a990&chksm=69813f0d5ef6b61baf45d6eb655b365666e42ca575436451c667f2846673c2f39b1b36b11369#rd) 51 | 52 | [【优雅的避坑】不安全!别再共享SimpleDateFormat变量了](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100002282&idx=1&sn=d2cff4595250f17a000f94b316483596&chksm=69813ed25ef6b7c423e8b7ecf492d7909b927ef7084c5213be07a56daf2c799c87f5cb2aa8ea#rd) 53 | 54 | [【优雅的避坑】你的钱算错了!为什么0.1+0.2不等于0.3了!?](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001820&idx=1&sn=4ace09b751a1e6a32aeefcb7f012b012&chksm=69813f245ef6b632c19823791c03c6da50939784f0b84db2711b3117c80fffcb673d6aa0a901#rd) 55 | 56 | [【优雅的避坑】不要轻易使用==比较两个Integer的值](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001801&idx=1&sn=5c2cf1bb2d20df863abd2d1caa9e0d27&chksm=69813f315ef6b627bb727428b155f8fd0ddb2ac934b240e9a484c53362103d26eae698be4dcb#rd) 57 | 58 | [【优雅的避坑】从验证码生成代码的优化到JVM栈和堆](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001773&idx=1&sn=cf33661c355fca06abb7a8deb733812f&chksm=698130d55ef6b9c3f2b4cd5298e4f991375459faeb839a8d3f2bdea5e6bcab2bb30e049a2bb2#rd) 59 | 60 | [Java最强大的技术之一:反射](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001735&idx=1&sn=f9bb8087f110229b7787cc0d29096441&chksm=698130ff5ef6b9e9435d09f16eb4716bf17d2ade0207e3fcedbba47d16fbd8ef00f491ffd2e5#rd) 61 | 62 | - 数据结构与算法 63 | 64 | [数据结构(一)- 链表](https://t.1yb.co/srio) 65 | 66 | [数据结构(二)| 队列与栈](https://t.1yb.co/sywf) 67 | 68 | [数据结构与算法(三)| 用数组实现队列和栈](https://t.1yb.co/trpZ) 69 | 70 | [数据结构与算法(四)| 队列、栈与Java集合](https://t.1yb.co/trqh) 71 | 72 | [数据结构与算法(五)| 递归行为及其时间复杂度分析](https://t.1yb.co/tNaW) 73 | 74 | - 设计模式 75 | 76 | [浅析单例模式的8种写法](https://mp.weixin.qq.com/s/2VjQLRj4X_Pz8OzcwdJRfQ) 77 | 78 | [【设计模式】Prototype原型模式](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001712&idx=1&sn=a76195af0d82fc4890c27add5bbf9cd9&chksm=698130885ef6b99e9468dc29969d72c3c7a2467b28a15a931ddce6902d492c899c99eabe57d4#rd) 79 | 80 | [【设计模式】详解访问者(Visitor)模式](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001883&idx=1&sn=ebe60ee186c7acbe1f9dd2f48a81251a&chksm=69813f635ef6b675045159e72e487b9999ee9414fe7d3fd2fdab3452b54a7c8ce4de90281478#rd) 81 | 82 | [这就是模板方法?TemplateMethod,一个你一直都在用的设计模式!](https://t.1yb.co/59xn) 83 | 84 | [1分钟帮你整明白什么是Builder建造者模式](https://t.1yb.co/59xu) 85 | 86 | [Observer 观察者模式浅析](https://t.1yb.co/59xJ) 87 | 88 | [责任链模式-号称倒数第二难的设计模式终于搞明白了](https://t.1yb.co/59xZ) 89 | 90 | [慎用多层继承,不妨试试装饰器模式](https://t.1yb.co/59y7) 91 | 92 | [代理模式那些事儿:静态代理,动态代理,JDK的动态代理,cglib,Spring AOP](https://t.1yb.co/59yi) 93 | 94 | [几需体验三欢钟,里造会干我一样理解Facade和Mediator模式](https://t.1yb.co/59yr) 95 | 96 | [工厂系列-FactoryMethod,AbstractFactory,Spring IOC](https://t.1yb.co/59yA) 97 | 98 | [策略模式之“这不就是if-else吗”](https://t.1yb.co/59z3) 99 | 100 | 101 | - 多线程 102 | 103 | [我用线程池ThreadPoolExecutor处理任务和Redis做缓存查询,效率提升了5倍!](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001317&idx=1&sn=42294b2068661ba4b4d214f6aafbdfb7&chksm=6981311d5ef6b80bf436ae595fb87b5ddea30e14bf6d1b4e1ab405b9594013a7816320f81692#rd) 104 | 105 | [从一道面试题进入Java并发新机制---J.U.C](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001154&idx=1&sn=080e5601e1a068a7367adb872bf209a7&chksm=698132ba5ef6bbacaf04724036e2000f8b8a88aa28dfc5bd6d298c5678dac00c0905b7aa2076#rd) 106 | 107 | - Elastic Stack 108 | 109 | [Elasticsearch初体验-创建Index,Document以及常见的ES查询](https://t.1yb.co/quKh) 110 | 111 | [ES Java API之增删改查](https://t.1yb.co/quKP) 112 | 113 | [Elasticsearch部署的这些问题,你遇到过吗?](https://t.1yb.co/quLd) 114 | 115 | [整活 | 海量日志收集利器之ELK!SpringBoot + ELK走起!](https://t.1yb.co/quLu) 116 | 117 | - Redis 118 | 119 | [Redis各种模式部署及工作原理-单节点、主从复制、redis-sentinel(哨兵)以及redis-cluster(集群)](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100002259&idx=1&sn=5f72b51448d4c49d3fcb519eab05b0bf&chksm=69813eeb5ef6b7fde4785957d0252984187e0b489cbc9d345facf4c8766567824a6c7d44f0d2#rd) 120 | 121 | [基于Redis分布式锁的实现](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100002320&idx=1&sn=eaaf6ad7c8b1450c0dc61ec8c808c4df&chksm=69813d285ef6b43ee18680f88984d228919391a90ff1535f8e75ccd957769edcbedbbb434207#rd) 122 | 123 | - Zookeeper 124 | 125 | [分布式高可用的ZooKeeper集群搭建与基本操作](https://t.1yb.co/59Ac) 126 | 127 | [ZooKeeper原理-paxos算法,ZAB协议](https://t.1yb.co/59Af) 128 | 129 | [用ZooKeeper实现分布式配置中心](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001512&idx=1&sn=7f3d5efdcaaf4b5d3aa3867b79f686de&chksm=698131d05ef6b8c605d3fe8237bc94c0db18b51eac0f5d4076726677d065333a37460aa1d7ef#rd) 130 | 131 | [用ZooKeeper实现分布式锁](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100001545&idx=1&sn=a11239e814e9f0054b2d3f284e269ba8&chksm=698130315ef6b927582a25a7507cd8d9eda61cca3ff9db5288ac1de094b6555886b0c6d1a13a#rd) 132 | 133 | - Kafka 134 | 135 | [从分布式AKF原则的角度看Kafka的架构设计](https://t.1yb.co/quH2) 136 | 137 | [探究Kafka高性能之道](https://t.1yb.co/quHc) 138 | 139 | [整活了!结合API操作Kafka集群,理解producer、consumer、topic、partition](https://t.1yb.co/quHt) 140 | 141 | 142 | 143 | - MySQL 144 | 145 | [【MySQL 8】MySQL 5.7即将停止维护,是时候看看MySQL 8了!](https://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=2247487414&idx=1&sn=b79c3e0e9870fb3e996bc38f6b425325&chksm=e981388edef6b1985c377cc7b96901ee37e9ddf32a812a50ccb32855f1bbc1176f3a1a629669#rd) 146 | 147 | [【MySQL 8入门之安装篇】CentOS 7系统下安装MySQL 8](https://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=2247487321&idx=1&sn=a485103b2799fccc585b5a23d28a95cf&chksm=e9813861def6b1770f6285fdf677cd43bbd254036f2ceb55116c32e3280f5c889a520d62094e#rd) 148 | 149 | [中班小朋友都会的 CentOS 7 下安装MySQL 5.7!](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000167&idx=1&sn=3b392431f89212ea96a16d5a93389242&chksm=6981369f5ef6bf89736ded3fd834dc22fba1c2cc54d4e2f6048fb3930e055270a740306efb31#rd) 150 | 151 | [捅破窗户纸-入门MySQL调优之性能监控](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000185&idx=1&sn=4e962f5b9dc34dad1079e3656d302c56&chksm=698136815ef6bf97c1776062926a110d80a1e719e55ac2e299394deebb559fe1472e5b69b4ae#rd) 152 | 153 | [结合案例说明MySQL的数据类型如何优化](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000228&idx=1&sn=88e329f7b330d921898d5d09641e77fb&chksm=698136dc5ef6bfca7889ca21c849f82b453f46cb48b595ede43c13282d5af1d68cf1e3f4fa20#rd) 154 | 155 | [将优化考虑在最前面-MySQL数据库设计优化:范式与反范式,主键,字符集,存储引擎](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000237&idx=1&sn=35041479d440d7d8f448bea63b61867a&chksm=698136d55ef6bfc35b31b9d003b9731a1aa67bb80d0c3ae9de05f5cd3cf19df8f4d024892730#rd) 156 | 157 | [MySQL优化必备之执行计划explain,索引基本知识,索引数据结构推演](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000253&idx=1&sn=e55ed089d68c0a6b6f9e6f9e12b2902c&chksm=698136c55ef6bfd3be8508fafae9f84ccc29e127b7eff76b190d985fd82892dd0f6ab857f594#rd) 158 | 159 | [MySQL通过索引优化-这里可能有你不知道的索引优化细节(一)](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000626&idx=1&sn=ee7686427c41127c4a6916e2edb81cd8&chksm=6981344a5ef6bd5c9a2979a010ccd24c0409c845564bba83ffa470bac79089c67abe8bf53335#rd) 160 | 161 | [MySQL通过索引优化-这里可能有你不知道的索引优化细节(二)](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000751&idx=1&sn=be0391a436f34a6fd53183f2c7b3b93e&chksm=698134d75ef6bdc1f9eef4ebdac9af5f2369803acb45f58ca526f46c8da530a3cf136d25e7af#rd) 162 | 163 | [MySQL调优之查询优化](http://mp.weixin.qq.com/s?__biz=MzI1MDU1MjkxOQ==&mid=100000870&idx=1&sn=5883625d302ce218ba3eac4be957df46&chksm=6981335e5ef6ba487826d094fbf0fdd44561c7fab32f1f9f40167d662359ca660d700dd63115#rd) 164 | 165 | - 不断更新中 166 | 167 | -------------------------------------------------------------------------------- /design-patterns/design-patterns.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /design-patterns/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xblzer 8 | design-patterns 9 | 1.0 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | org.mybatis 19 | mybatis 20 | 3.5.3 21 | 22 | 23 | 24 | org.aspectj 25 | aspectjweaver 26 | 1.9.5 27 | 28 | 29 | 30 | org.springframework 31 | spring-core 32 | 5.2.6.RELEASE 33 | 34 | 35 | 36 | org.springframework 37 | spring-context 38 | 5.2.6.RELEASE 39 | 40 | 41 | org.springframework 42 | spring-aop 43 | 5.2.6.RELEASE 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/BaseFactory.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public abstract class BaseFactory { 7 | 8 | abstract Food createFood(); 9 | 10 | abstract ProtectiveEquip createProtectiveEquip(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.support.ClassPathXmlApplicationContext; 6 | 7 | /** 8 | * @author 行百里者 9 | */ 10 | public class Client { 11 | 12 | public static void main(String[] args) { 13 | // BaseFactory factory = new HumanFactory(); 14 | // //BaseFactory factory = new UsaFactory(); 15 | // 16 | // Food food = factory.createFood(); 17 | // food.printName(); 18 | // ProtectiveEquip protectiveEquip = factory.createProtectiveEquip(); 19 | // protectiveEquip.protect(); 20 | 21 | ApplicationContext ctx = new ClassPathXmlApplicationContext("app.xml"); 22 | Rice rice = (Rice) ctx.getBean("rice"); 23 | rice.printName(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/FaceMask.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * 口罩 类 5 | * 6 | * @author 行百里者 7 | */ 8 | public class FaceMask extends ProtectiveEquip { 9 | 10 | @Override 11 | public void protect() { 12 | System.out.println("face masks don't let the virus enter"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/Food.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * 食物 5 | * 6 | * @author 行百里者 7 | */ 8 | public abstract class Food { 9 | public abstract void printName(); 10 | } 11 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/HumanFactory.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class HumanFactory extends BaseFactory { 7 | @Override 8 | Food createFood() { 9 | return new Rice(); 10 | } 11 | 12 | @Override 13 | ProtectiveEquip createProtectiveEquip() { 14 | return new FaceMask(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/Junk.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class Junk extends Food { 7 | @Override 8 | public void printName() { 9 | System.out.println("French fries is junk food!"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/ProtectiveEquip.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * 防护用品 5 | * 6 | * @author 行百里者 7 | */ 8 | public abstract class ProtectiveEquip { 9 | 10 | public abstract void protect(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/Rags.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * “漂亮国”的防护口罩 5 | * 6 | * @author 行百里者 7 | */ 8 | public class Rags extends ProtectiveEquip { 9 | @Override 10 | public void protect() { 11 | //处理其他业务逻辑。。日志等 12 | System.out.println("漂亮国的防护口罩,不知道能不能防护!"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/Rice.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class Rice extends Food { 7 | @Override 8 | public void printName() { 9 | System.out.println("rice,en... delicious!!!"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/abstractfactory/UsaFactory.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.abstractfactory; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class UsaFactory extends BaseFactory { 7 | @Override 8 | Food createFood() { 9 | return new Junk(); 10 | } 11 | 12 | @Override 13 | ProtectiveEquip createProtectiveEquip() { 14 | return new Rags(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/chainofresposibility/servlet/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.chainofresposibility.servlet; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 行百里者 8 | */ 9 | public class Client { 10 | public static void main(String[] args) { 11 | Request request = new Request(); 12 | request.reqMsg = "检查发动机,变速箱,车身有没有问题"; 13 | Response response = new Response(); 14 | response.respMsg = "-------response:"; 15 | 16 | FilterChain chain = new FilterChain(); 17 | chain.add(new EngineFilter()).add(new GearboxFilter()).add(new CarbodyFilter()); 18 | chain.doFilter(request, response); 19 | 20 | System.out.println(response.respMsg); 21 | } 22 | } 23 | 24 | class Request { 25 | String reqMsg; 26 | } 27 | 28 | class Response { 29 | String respMsg; 30 | } 31 | 32 | interface Filter { 33 | void doFilter(Request request, Response response, FilterChain chain); 34 | } 35 | 36 | class EngineFilter implements Filter { 37 | @Override 38 | public void doFilter(Request request, Response response, FilterChain chain) { 39 | //先处理request请求 40 | if (request.reqMsg.contains("发动机")) { 41 | System.out.println("------EngineFilter 检查了发动机------"); 42 | } 43 | //通过链条传递处理下一个request 44 | chain.doFilter(request, response); 45 | //处理response 46 | response.respMsg += "---执行了EngineFilter过滤器---"; 47 | } 48 | } 49 | 50 | class GearboxFilter implements Filter { 51 | @Override 52 | public void doFilter(Request request, Response response, FilterChain chain) { 53 | if (request.reqMsg.contains("变速箱")) { 54 | System.out.println("------GearboxFilter 检查了变速箱------"); 55 | } 56 | //通过链条传递处理下一个request 57 | chain.doFilter(request, response); 58 | //处理response 59 | response.respMsg += "---执行了GearboxFilter过滤器---"; 60 | } 61 | } 62 | 63 | class CarbodyFilter implements Filter { 64 | @Override 65 | public void doFilter(Request request, Response response, FilterChain chain) { 66 | if (request.reqMsg.contains("车身")) { 67 | System.out.println("------CarbodyFilter 检查了车身------"); 68 | } 69 | //通过链条传递处理下一个request 70 | chain.doFilter(request, response); 71 | //处理response 72 | response.respMsg += "---执行了CarbodyFilter过滤器---"; 73 | } 74 | } 75 | 76 | class FilterChain { 77 | List filters = new ArrayList<>(); 78 | int filterIndex = 0; 79 | 80 | public FilterChain add(Filter filter) { 81 | filters.add(filter); 82 | return this; 83 | } 84 | 85 | public void doFilter(Request request, Response response) { 86 | //如果request链条执行完了,就不往下传递了 87 | if (filterIndex == filters.size()) { 88 | return; 89 | } 90 | Filter f = filters.get(filterIndex); 91 | filterIndex++; 92 | f.doFilter(request, response, this); 93 | } 94 | } 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/chainofresposibility/v1/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.chainofresposibility.v1; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class Client { 7 | public static void main(String[] args) { 8 | Client client = new Client(); 9 | 10 | Request req = new Request(); 11 | req.setReqMsg("检查发动机,变速箱,车身有没有问题"); 12 | if (req.getReqMsg().contains("车身")) { 13 | client.doCheckCarbody(); 14 | } 15 | if (req.getReqMsg().contains("发动机")) { 16 | client.doCheckEngine(); 17 | } 18 | if (req.getReqMsg().contains("变速箱")) { 19 | client.doCheckGearbox(); 20 | } 21 | if (req.getReqMsg().contains("xxx")) { 22 | // do something 23 | } 24 | } 25 | 26 | public void doCheckEngine() { 27 | System.out.println("------检查了发动机------"); 28 | } 29 | 30 | public void doCheckCarbody() { 31 | System.out.println("------检查了车身-------"); 32 | } 33 | 34 | public void doCheckGearbox() { 35 | System.out.println("------检查了变速箱-----"); 36 | } 37 | } 38 | 39 | class Request { 40 | private String reqMsg; 41 | 42 | public String getReqMsg() { 43 | return reqMsg; 44 | } 45 | 46 | public void setReqMsg(String reqMsg) { 47 | this.reqMsg = reqMsg; 48 | } 49 | } 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/chainofresposibility/v2/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.chainofresposibility.v2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 行百里者 8 | */ 9 | public class Client { 10 | public static void main(String[] args) { 11 | Request req = new Request(); 12 | req.setReqMsg("检查发动机,变速箱,车身有没有问题"); 13 | 14 | List filters = new ArrayList<>(); 15 | filters.add(new CarbodyFilter()); 16 | filters.add(new GearboxFilter()); 17 | filters.add(new EngineFilter()); 18 | 19 | for (Filter f : filters) { 20 | f.doFilter(req); 21 | } 22 | } 23 | } 24 | 25 | class Request { 26 | private String reqMsg; 27 | 28 | public String getReqMsg() { 29 | return reqMsg; 30 | } 31 | 32 | public void setReqMsg(String reqMsg) { 33 | this.reqMsg = reqMsg; 34 | } 35 | } 36 | 37 | interface Filter { 38 | boolean doFilter(Request request); 39 | } 40 | 41 | class EngineFilter implements Filter { 42 | @Override 43 | public boolean doFilter(Request request) { 44 | if (request.getReqMsg().contains("发动机")) { 45 | System.out.println("------检查了发动机------"); 46 | } 47 | return true; 48 | } 49 | } 50 | 51 | class GearboxFilter implements Filter { 52 | @Override 53 | public boolean doFilter(Request request) { 54 | if (request.getReqMsg().contains("变速箱")) { 55 | System.out.println("------检查了变速箱------"); 56 | } 57 | return true; 58 | } 59 | } 60 | 61 | class CarbodyFilter implements Filter { 62 | @Override 63 | public boolean doFilter(Request request) { 64 | if (request.getReqMsg().contains("车身")) { 65 | System.out.println("------检查了车身------"); 66 | } 67 | return true; 68 | } 69 | } 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/chainofresposibility/v3/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.chainofresposibility.v3; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 行百里者 8 | */ 9 | public class Client { 10 | public static void main(String[] args) { 11 | Request req = new Request(); 12 | req.setReqMsg("检查发动机,变速箱,车身有没有问题"); 13 | 14 | FilterChain chain = new FilterChain(); 15 | chain.add(new EngineFilter()) 16 | .add(new GearboxFilter()) 17 | .add(new CarbodyFilter()) 18 | .doFilter(req); 19 | // chain.add(new EngineFilter()); 20 | // chain.add(new GearboxFilter()); 21 | // chain.add(new CarbodyFilter()); 22 | // chain.doFilter(req); 23 | } 24 | } 25 | 26 | class Request { 27 | private String reqMsg; 28 | 29 | public String getReqMsg() { 30 | return reqMsg; 31 | } 32 | 33 | public void setReqMsg(String reqMsg) { 34 | this.reqMsg = reqMsg; 35 | } 36 | } 37 | 38 | interface Filter { 39 | boolean doFilter(Request request); 40 | } 41 | 42 | class EngineFilter implements Filter { 43 | @Override 44 | public boolean doFilter(Request request) { 45 | if (request.getReqMsg().contains("发动机")) { 46 | System.out.println("------检查了发动机------"); 47 | } 48 | return true; 49 | } 50 | } 51 | 52 | class GearboxFilter implements Filter { 53 | @Override 54 | public boolean doFilter(Request request) { 55 | if (request.getReqMsg().contains("变速箱")) { 56 | System.out.println("------检查了变速箱------"); 57 | } 58 | return true; 59 | } 60 | } 61 | 62 | class CarbodyFilter implements Filter { 63 | @Override 64 | public boolean doFilter(Request request) { 65 | if (request.getReqMsg().contains("车身")) { 66 | System.out.println("------检查了车身------"); 67 | } 68 | return true; 69 | } 70 | } 71 | 72 | class FilterChain implements Filter { 73 | List filters = new ArrayList<>(); 74 | 75 | //比较骚的写法,这样可以链式调用 76 | public FilterChain add(Filter filter) { 77 | filters.add(filter); 78 | return this; 79 | } 80 | //一般写法 81 | // public void add(Filter filter) { 82 | // filters.add(filter); 83 | // } 84 | 85 | @Override 86 | public boolean doFilter(Request request) { 87 | for (Filter f : filters) { 88 | //任何一环检查出了问题,均不往下检查 89 | if (!f.doFilter(request)) { 90 | return false; 91 | } 92 | } 93 | return true; 94 | } 95 | } 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/facade/CheckDept.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.facade; 2 | 3 | /** 4 | * 检查核验部门,核验通过才给盖章 5 | * 6 | * @author 行百里者 7 | */ 8 | public class CheckDept { 9 | public void checkStuff() { 10 | //处理业务逻辑 11 | System.out.println("核查材料的准确性,核查通过才给盖章"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/facade/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.facade; 2 | 3 | /** 4 | * @author chappell 5 | */ 6 | public class Client { 7 | public static void main(String[] args) { 8 | // //一定要按照这个顺序去办证,否则拿不到证 9 | // StuffDept sd = new StuffDept(); 10 | // sd.makeStuff(); 11 | // CheckDept cd = new CheckDept(); 12 | // cd.checkStuff(); 13 | // IssueDept id = new IssueDept(); 14 | // id.issueCert(); 15 | NetApp facade = new NetApp(); 16 | facade.doItJustOnce(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/facade/IssueDept.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.facade; 2 | 3 | /** 4 | * 发证部门 5 | * 6 | * @author 行百里者 7 | */ 8 | public class IssueDept { 9 | public void issueCert() { 10 | //处理业务逻辑 11 | System.out.println("发证部门检验材料是否盖章,然后制证发证"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/facade/NetApp.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.facade; 2 | 3 | /** 4 | * “中国式办证”所需的“门面”部门,负责统一处理各部门的事情, 5 | * Client只需要调“门面”的doItJustOnce方法即可 6 | * 7 | * @author 行百里者 8 | */ 9 | public class NetApp { 10 | private StuffDept stuffDept = new StuffDept(); 11 | private CheckDept checkDept = new CheckDept(); 12 | private IssueDept issueDept = new IssueDept(); 13 | 14 | public void doItJustOnce() { 15 | stuffDept.makeStuff(); 16 | checkDept.checkStuff(); 17 | issueDept.issueCert(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/facade/StuffDept.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.facade; 2 | 3 | /** 4 | * 材料部门,给办证者提供必要的材料 5 | * 6 | * @author 行百里者 7 | */ 8 | public class StuffDept { 9 | public void makeStuff() { 10 | //处理业务逻辑 11 | System.out.println("制作相关材料,并发给Client填写"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/factorymethod/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.factorymethod; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class Client { 7 | 8 | public static void main(String[] args) { 9 | // FaceMask fm = new FaceMask(); 10 | // fm.protect(); 11 | FaceMaskFactory factory = new FaceMaskFactory(); 12 | factory.create().protect(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/factorymethod/FaceMask.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.factorymethod; 2 | 3 | /** 4 | * 口罩 类 5 | * 6 | * @author 行百里者 7 | */ 8 | public class FaceMask extends ProtectiveEquip { 9 | 10 | @Override 11 | public void protect() { 12 | System.out.println("face masks don't let the virus enter"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/factorymethod/FaceMaskFactory.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.factorymethod; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class FaceMaskFactory { 7 | 8 | FaceMask create() { 9 | System.out.println("业务逻辑..."); 10 | return new FaceMask(); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/factorymethod/HandMask.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.factorymethod; 2 | 3 | /** 4 | * 口罩 类 5 | * 6 | * @author 行百里者 7 | */ 8 | public class HandMask { 9 | 10 | public void protect() { 11 | System.out.println("hand masks don't let the virus enter"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/factorymethod/ProtectiveEquip.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.factorymethod; 2 | 3 | /** 4 | * 防护用品 5 | * 6 | * @author 行百里者 7 | */ 8 | public abstract class ProtectiveEquip { 9 | 10 | public abstract void protect(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/factorymethod/SimpleProtectiveEquipFactory.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.factorymethod; 2 | 3 | /** 4 | * 简单工厂 生产防护用品 5 | * 简单工厂的可扩展性不好,比如需要造新的防护用品的时候,需要加方法 6 | * 7 | * @author 行百里者 8 | */ 9 | public class SimpleProtectiveEquipFactory { 10 | 11 | FaceMask createFaceMask() { 12 | return new FaceMask(); 13 | } 14 | 15 | HandMask createHandMask() { 16 | return new HandMask(); 17 | } 18 | 19 | //如果还需要生产其他防护用品,就接着写createXXX方法 20 | } 21 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/observer/MyFrame.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.observer; 2 | 3 | import java.awt.*; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.awt.event.WindowAdapter; 7 | import java.awt.event.WindowEvent; 8 | 9 | /** 10 | * @author 行百里者 11 | */ 12 | public class MyFrame extends Frame { 13 | public void launch() { 14 | Button b = new Button("press me"); 15 | b.addActionListener(new MyActionListener()); 16 | b.addActionListener(new MyActionListener2()); 17 | this.add(b); 18 | this.pack(); 19 | 20 | this.addWindowListener(new WindowAdapter() { 21 | @Override 22 | public void windowClosing(WindowEvent e) { 23 | System.exit(0); 24 | } 25 | 26 | }); 27 | this.setLocation(400, 400); 28 | this.setVisible(true); 29 | } 30 | 31 | public static void main(String[] args) { 32 | new MyFrame().launch(); 33 | } 34 | 35 | //Observer 36 | private class MyActionListener implements ActionListener { 37 | 38 | @Override 39 | public void actionPerformed(ActionEvent e) { 40 | ((Button) e.getSource()).setLabel("press me again!"); 41 | System.out.println("button pressed!"); 42 | } 43 | 44 | } 45 | 46 | private class MyActionListener2 implements ActionListener { 47 | 48 | @Override 49 | public void actionPerformed(ActionEvent e) { 50 | System.out.println("button pressed 2!"); 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/observer/v1/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.observer.v1; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class Client { 7 | public static void main(String[] args) { 8 | Korea k = new Korea(); 9 | k.fire(); 10 | } 11 | } 12 | 13 | class Korea { 14 | 15 | China china = new China(); 16 | Usa usa = new Usa(); 17 | 18 | public void fire() { 19 | System.out.println("朝鲜:发射核弹!"); 20 | china.warn(); 21 | usa.threaten(); 22 | } 23 | } 24 | 25 | class China { 26 | public void warn() { 27 | System.out.println("中国:不要在我家门口玩火,否则后果自负!"); 28 | } 29 | } 30 | 31 | class Usa { 32 | public void threaten() { 33 | System.out.println("美国:韩国小老弟来我们军事演练走一波!"); 34 | } 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/observer/v2/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.observer.v2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 行百里者 8 | */ 9 | public class Client { 10 | public static void main(String[] args) { 11 | Korea k = new Korea(); 12 | k.fire(); 13 | } 14 | } 15 | 16 | class Korea { 17 | 18 | private List observers = new ArrayList<>(); 19 | 20 | { 21 | observers.add(new China()); 22 | observers.add(new Usa()); 23 | } 24 | 25 | public void fire() { 26 | System.out.println("朝鲜:我要发射了!Boom!!!"); 27 | observers.forEach(observer -> observer.onFire()); 28 | } 29 | } 30 | 31 | interface Observer { 32 | void onFire(); 33 | } 34 | 35 | class China implements Observer { 36 | public void warn() { 37 | System.out.println("中国:不要在我家门口玩火,否则后果自负!"); 38 | } 39 | 40 | @Override 41 | public void onFire() { 42 | warn(); 43 | } 44 | } 45 | 46 | class Usa implements Observer { 47 | public void threaten() { 48 | System.out.println("美国:韩国小老弟来我们军事演练走一波!"); 49 | } 50 | 51 | @Override 52 | public void onFire() { 53 | threaten(); 54 | } 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/observer/v3/Client.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.observer.v3; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 行百里者 8 | */ 9 | public class Client { 10 | public static void main(String[] args) { 11 | Korea k = new Korea(); 12 | k.fire(); 13 | } 14 | } 15 | 16 | class Korea { 17 | 18 | private List observers = new ArrayList<>(); 19 | 20 | { 21 | observers.add(new China()); 22 | observers.add(new Usa()); 23 | } 24 | 25 | public void fire() { 26 | System.out.println("朝鲜:我要发射了!Boom!!!"); 27 | //事件发生了 28 | FireEvent fireEvent = new FireEvent(System.currentTimeMillis(), "夏威夷", this); 29 | observers.forEach(observer -> observer.onFire(fireEvent)); 30 | } 31 | } 32 | 33 | /** 34 | * 抽象出事件类 35 | * 36 | * @param 37 | */ 38 | abstract class Event { 39 | abstract T getSource(); 40 | } 41 | 42 | /** 43 | * 发射核弹事件,事件源是Korea 44 | */ 45 | class FireEvent extends Event { 46 | 47 | //事件发生时间 48 | long timestamp; 49 | //事件发生地点 50 | String location; 51 | //事件源 52 | private Korea korea; 53 | 54 | public FireEvent(long timestamp, String location, Korea korea) { 55 | this.timestamp = timestamp; 56 | this.location = location; 57 | this.korea = korea; 58 | } 59 | 60 | @Override 61 | public Korea getSource() { 62 | return korea; 63 | } 64 | } 65 | 66 | /** 67 | * 观察者 68 | */ 69 | interface Observer { 70 | //观察者根据事件作出响应 71 | void onFire(FireEvent fireEvent); 72 | } 73 | 74 | class China implements Observer { 75 | public void warn() { 76 | System.out.println("中国:不要在我家门口玩火,否则后果自负!"); 77 | } 78 | 79 | @Override 80 | public void onFire(FireEvent fireEvent) { 81 | if (fireEvent.location.contains("鸭绿江")) { 82 | warn(); 83 | } 84 | } 85 | } 86 | 87 | class Usa implements Observer { 88 | public void threaten() { 89 | System.out.println("美国:韩国小老弟来我们军事演练走一波!"); 90 | } 91 | 92 | @Override 93 | public void onFire(FireEvent fireEvent) { 94 | if (fireEvent.location.contains("夏威夷")) { 95 | threaten(); 96 | } 97 | } 98 | } 99 | 100 | 101 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/cglib/Main.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.cglib; 2 | 3 | import org.springframework.cglib.proxy.Enhancer; 4 | import org.springframework.cglib.proxy.MethodInterceptor; 5 | import org.springframework.cglib.proxy.MethodProxy; 6 | 7 | import java.lang.reflect.Method; 8 | import java.util.Random; 9 | 10 | /** 11 | * cglib-code generate library 12 | * cglib实现动态代理不需要实现接口 13 | * 底层用的也是asm 14 | * 15 | * @author 行百里者 16 | */ 17 | public class Main { 18 | public static void main(String[] args) { 19 | Enhancer enhancer = new Enhancer(); 20 | enhancer.setSuperclass(Pony.class); 21 | enhancer.setCallback(new TimeMethodInterceptor()); 22 | Pony pony = (Pony) enhancer.create(); 23 | pony.paint(); 24 | } 25 | } 26 | 27 | class TimeMethodInterceptor implements MethodInterceptor { 28 | @Override 29 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 30 | System.out.println(o.getClass().getSuperclass().getName()); 31 | System.out.println("before..."); 32 | Object result = methodProxy.invokeSuper(o, objects); 33 | System.out.println("after"); 34 | return result; 35 | } 36 | } 37 | 38 | class Pony { 39 | public void paint() { 40 | System.out.println("小马画月牙"); 41 | //随机睡10s以内,假装这是处理业务逻辑 42 | try { 43 | Thread.sleep(new Random().nextInt(10000)); 44 | } catch (InterruptedException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/dynamicproxy/Painter.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.dynamicproxy; 2 | 3 | /** 4 | * 小画家 接口 5 | * 6 | * @author 行百里者 7 | */ 8 | public interface Painter { 9 | void paint(); 10 | } 11 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/dynamicproxy/Pony.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.dynamicproxy; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author 行百里者 7 | */ 8 | public class Pony implements Painter { 9 | @Override 10 | public void paint() { 11 | System.out.println("小马画月牙"); 12 | //随机睡10s以内,假装这是处理业务逻辑 13 | try { 14 | Thread.sleep(new Random().nextInt(10000)); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/dynamicproxy/Teacher.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.dynamicproxy; 2 | 3 | import java.lang.reflect.Proxy; 4 | 5 | /** 6 | * 使用jdk的动态代理 7 | * 8 | * @author 行百里者 9 | */ 10 | public class Teacher { 11 | public static void main(String[] args) { 12 | Pony pony = new Pony(); 13 | //将proxy内部调用invoke方法 生成的中间类 保存下来 14 | System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); 15 | Painter painter = (Painter) Proxy.newProxyInstance( 16 | Pony.class.getClassLoader(), 17 | new Class[]{Painter.class}, 18 | new TimeProxyHandler(pony)); 19 | painter.paint(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/dynamicproxy/TimeProxyHandler.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.dynamicproxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * @author 行百里者 8 | */ 9 | public class TimeProxyHandler implements InvocationHandler { 10 | 11 | private Pony pony; 12 | 13 | public TimeProxyHandler(Pony pony) { 14 | this.pony = pony; 15 | } 16 | 17 | @Override 18 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 19 | long start = System.currentTimeMillis(); 20 | Object o = method.invoke(pony, args); 21 | long end = System.currentTimeMillis(); 22 | System.out.println("执行耗时:" + (end - start) + "毫秒"); 23 | return o; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/springaop/LogProxy.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.springaop; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class LogProxy { 7 | public void before() { 8 | System.out.println("日志:开始作画"); 9 | } 10 | 11 | public void after() { 12 | System.out.println("日志:画完了"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/springaop/Pony.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.springaop; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author 行百里者 7 | */ 8 | public class Pony { 9 | public void paint() { 10 | System.out.println("小马画月牙"); 11 | //随机睡10s以内,假装这是处理业务逻辑 12 | try { 13 | Thread.sleep(new Random().nextInt(10000)); 14 | } catch (InterruptedException e) { 15 | e.printStackTrace(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/springaop/Teacher.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.springaop; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | 6 | /** 7 | * Spring AOP 8 | * 9 | * @author 行百里者 10 | */ 11 | public class Teacher { 12 | public static void main(String[] args) { 13 | ApplicationContext ctx = new ClassPathXmlApplicationContext("app_aop.xml"); 14 | Pony pony = (Pony) ctx.getBean("pony"); 15 | pony.paint(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/staticproxy/LogProxy.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.staticproxy; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class LogProxy implements Painter { 7 | 8 | private Painter painter; 9 | 10 | public LogProxy(Painter painter) { 11 | this.painter = painter; 12 | } 13 | 14 | @Override 15 | public void paint() { 16 | System.out.println("日志:开始作画"); 17 | painter.paint(); 18 | System.out.println("日志:画完了"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/staticproxy/Painter.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.staticproxy; 2 | 3 | /** 4 | * 小画家 接口 5 | * 6 | * @author 行百里者 7 | * @since 2020.5.22 8 | */ 9 | public interface Painter { 10 | void paint(); 11 | } 12 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/staticproxy/Pony.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.staticproxy; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author 行百里者 7 | * @since 2020.5.22 8 | */ 9 | public class Pony implements Painter { 10 | @Override 11 | public void paint() { 12 | System.out.println("小马画月牙"); 13 | //随机睡10s以内,假装这是处理业务逻辑 14 | try { 15 | Thread.sleep(new Random().nextInt(10000)); 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/staticproxy/Puppy.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.staticproxy; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author 行百里者 7 | * @since 2020.5.22 8 | */ 9 | public class Puppy implements Painter { 10 | @Override 11 | public void paint() { 12 | System.out.println("小狗画梅花"); 13 | //随机睡10s以内,假装这是处理业务逻辑 14 | try { 15 | Thread.sleep(new Random().nextInt(10000)); 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/staticproxy/Teacher.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.staticproxy; 2 | 3 | /** 4 | * @author 行百里者 5 | * @since 2020.5.22 6 | */ 7 | public class Teacher { 8 | public static void main(String[] args) { 9 | 10 | //new TimeProxy(new Puppy()).paint(); 11 | new TimeProxy(new LogProxy(new Puppy())).paint(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/staticproxy/TimeProxy.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.staticproxy; 2 | 3 | /** 4 | * @author 行百里者 5 | */ 6 | public class TimeProxy implements Painter { 7 | 8 | private Painter painter; 9 | 10 | public TimeProxy(Painter painter) { 11 | this.painter = painter; 12 | } 13 | 14 | @Override 15 | public void paint() { 16 | long start = System.currentTimeMillis(); 17 | //调用小马画画 18 | painter.paint(); 19 | long end = System.currentTimeMillis(); 20 | System.out.println("paint 画画耗时:" + (end - start) + "毫秒"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/proxy/staticproxy/TimeProxyHandler.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.proxy.staticproxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * @author 行百里者 8 | * @since 2020.05.22 9 | */ 10 | public class TimeProxyHandler implements InvocationHandler { 11 | private Pony pony; 12 | 13 | public TimeProxyHandler(Pony pony) { 14 | this.pony = pony; 15 | } 16 | 17 | @Override 18 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 19 | long start = System.currentTimeMillis(); 20 | Object o = method.invoke(pony, args); 21 | long end = System.currentTimeMillis(); 22 | System.out.println("执行耗时:" + (end - start) + "毫秒"); 23 | return o; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Main.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * for test 5 | * 6 | * @author 行百里者 7 | */ 8 | public class Main { 9 | public static void main(String[] args) { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_1.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * 类加载的时候就实例化一个实例,JVM保证线程安全 5 | * 也称饿汉式 6 | * 该方式简单实用 7 | * 8 | * @author 行百里者 9 | */ 10 | public class Singleton_1 { 11 | private static final Singleton_1 INSTANCE = new Singleton_1(); 12 | 13 | /** 14 | * 私有的构造方法,其他地方不能new 15 | */ 16 | private Singleton_1() { 17 | } 18 | 19 | public static Singleton_1 getInstance() { 20 | return INSTANCE; 21 | } 22 | 23 | /** 24 | * for test 25 | */ 26 | public static void main(String[] args) { 27 | Singleton_1 instance1 = Singleton_1.getInstance(); 28 | Singleton_1 instance2 = Singleton_1.getInstance(); 29 | System.out.println(instance1 == instance2); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_2.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * 和Singleton_1是同一个意思 5 | * 只是将new的动作放在了代码块里 6 | * 类加载到内存的时候只加载一个实例 7 | * 8 | * @author 行百里者 9 | */ 10 | public class Singleton_2 { 11 | private static final Singleton_2 INSTANCE; 12 | 13 | static { 14 | INSTANCE = new Singleton_2(); 15 | } 16 | 17 | /** 18 | * 私有的构造方法,其他地方不能new 19 | */ 20 | private Singleton_2() { 21 | } 22 | 23 | public static Singleton_2 getInstance() { 24 | return INSTANCE; 25 | } 26 | 27 | /** 28 | * for test 29 | */ 30 | public static void main(String[] args) { 31 | Singleton_2 instance1 = Singleton_2.getInstance(); 32 | Singleton_2 instance2 = Singleton_2.getInstance(); 33 | System.out.println(instance1 == instance2); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_3.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * lazy loading 懒汉式 5 | * 这种写法虽然达到了用的时候才初始化的目的,但是存在多线程获取实例时相互影响的问题 6 | * 7 | * @author 行百里者 8 | */ 9 | public class Singleton_3 { 10 | private static Singleton_3 INSTANCE; 11 | 12 | /** 13 | * 私有的构造方法,其他地方不能new 14 | */ 15 | private Singleton_3() { 16 | } 17 | 18 | public static Singleton_3 getInstance() { 19 | if (INSTANCE == null) { 20 | // 测试,sleep一下,增加被其他线程打断的机会 21 | try { 22 | Thread.sleep(1); 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } 26 | INSTANCE = new Singleton_3(); 27 | } 28 | return INSTANCE; 29 | } 30 | 31 | /** 32 | * for test 33 | */ 34 | public static void main(String[] args) { 35 | //同一个类的不同对象的hashcode不同 36 | //跑100个线程,看看有没有不同的实例 37 | for (int i = 0; i < 100; i++) { 38 | new Thread(() -> System.out.println(Singleton_3.getInstance().hashCode())).start(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_4.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * lazy loading 懒汉式 5 | * 这种写法虽然达到了用的时候才初始化的目的,但是存在多线程获取实例时相互影响的问题 6 | * 可以用synchronized加锁,但是效率会降低 7 | * 8 | * @author 行百里者 9 | */ 10 | public class Singleton_4 { 11 | private static Singleton_4 INSTANCE; 12 | 13 | /** 14 | * 私有的构造方法,其他地方不能new 15 | */ 16 | private Singleton_4() { 17 | } 18 | 19 | /** 20 | * 既然lazy loading的写法有线程安全问题,那就加把锁 21 | */ 22 | public static synchronized Singleton_4 getInstance() { 23 | if (INSTANCE == null) { 24 | // 测试,sleep一下,增加被其他线程打断的机会 25 | try { 26 | Thread.sleep(1); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | INSTANCE = new Singleton_4(); 31 | } 32 | return INSTANCE; 33 | } 34 | 35 | /** 36 | * for test 37 | */ 38 | public static void main(String[] args) { 39 | //同一个类的不同对象的hashcode不同 40 | //跑100个线程,看看有没有不同的实例 41 | for (int i = 0; i < 100; i++) { 42 | new Thread(() -> System.out.println(Singleton_4.getInstance().hashCode())).start(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_5.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * lazy loading 懒汉式 5 | * 这种写法虽然达到了用的时候才初始化的目的,但是存在多线程获取实例时相互影响的问题 6 | * 可以用synchronized加锁,但是效率会降低 7 | * 在加锁的基础上再优化一下,减少加锁代码块的数量 8 | * 9 | * @author 行百里者 10 | */ 11 | public class Singleton_5 { 12 | private static Singleton_5 INSTANCE; 13 | 14 | /** 15 | * 私有的构造方法,其他地方不能new 16 | */ 17 | private Singleton_5() { 18 | } 19 | 20 | public static Singleton_5 getInstance() { 21 | if (INSTANCE == null) { 22 | //不在方法上加锁而在new的时候才加锁,减少锁的代码,然而这种方式并不行 23 | synchronized (Singleton_5.class) { 24 | // 测试,sleep一下,增加被其他线程打断的机会 25 | try { 26 | Thread.sleep(1); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | INSTANCE = new Singleton_5(); 31 | } 32 | } 33 | return INSTANCE; 34 | } 35 | 36 | /** 37 | * for test 38 | */ 39 | public static void main(String[] args) { 40 | //同一个类的不同对象的hashcode不同 41 | //跑100个线程,看看有没有不同的实例 42 | for (int i = 0; i < 100; i++) { 43 | new Thread(() -> System.out.println(Singleton_5.getInstance().hashCode())).start(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_6.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * lazy loading 懒汉式 5 | * 这种写法虽然达到了用的时候才初始化的目的,但是存在多线程获取实例时相互影响的问题 6 | * 可以用synchronized加锁,但是效率会降低 7 | * 在加锁的基础上再优化一下,减少加锁代码块的数量---事实证明不可行 8 | * 那就双重检查DCL 9 | * 10 | * @author 行百里者 11 | */ 12 | public class Singleton_6 { 13 | private static volatile Singleton_6 INSTANCE; 14 | 15 | /** 16 | * 私有的构造方法,其他地方不能new 17 | */ 18 | private Singleton_6() { 19 | } 20 | 21 | public static Singleton_6 getInstance() { 22 | if (INSTANCE == null) { //第一重检查 23 | synchronized (Singleton_6.class) { 24 | if (INSTANCE == null) { //第二重检查 25 | // 测试,sleep一下,增加被其他线程打断的机会 26 | try { 27 | Thread.sleep(1); 28 | } catch (InterruptedException e) { 29 | e.printStackTrace(); 30 | } 31 | INSTANCE = new Singleton_6(); 32 | } 33 | } 34 | } 35 | return INSTANCE; 36 | } 37 | 38 | /** 39 | * for test 40 | */ 41 | public static void main(String[] args) { 42 | //同一个类的不同对象的hashcode不同 43 | //跑100个线程,看看有没有不同的实例 44 | for (int i = 0; i < 100; i++) { 45 | new Thread(() -> System.out.println(Singleton_6.getInstance().hashCode())).start(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_7.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * 静态内部类方式 5 | * JVM保证单例 6 | * 加载外部类时不会加载内部类---也可实现懒加载 7 | * 8 | * @author 行百里者 9 | */ 10 | public class Singleton_7 { 11 | 12 | /** 13 | * 私有的构造方法,其他地方不能new 14 | */ 15 | private Singleton_7() { 16 | } 17 | 18 | /** 19 | * 定义一个静态内部类 20 | */ 21 | private static class SingletonHolder { 22 | private static final Singleton_7 INSTANCE = new Singleton_7(); 23 | } 24 | 25 | public static Singleton_7 getInstance() { 26 | return SingletonHolder.INSTANCE; 27 | } 28 | 29 | /** 30 | * for test 31 | */ 32 | public static void main(String[] args) { 33 | //同一个类的不同对象的hashcode不同 34 | //跑100个线程,看看有没有不同的实例 35 | for (int i = 0; i < 100; i++) { 36 | new Thread(() -> System.out.println(Singleton_7.getInstance().hashCode())).start(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /design-patterns/src/main/java/cn/chendapeng/dp/singleton/Singleton_8.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.dp.singleton; 2 | 3 | /** 4 | * 枚举单例 5 | * 不仅可以解决线程同步,还可以防止反序列化 6 | * 7 | * @author travler100 8 | */ 9 | public enum Singleton_8 { 10 | INSTANCE; 11 | 12 | /** 13 | * for test 14 | */ 15 | public static void main(String[] args) { 16 | //同一个类的不同对象的hashcode不同 17 | //跑100个线程,看看有没有不同的实例 18 | for (int i = 0; i < 100; i++) { 19 | new Thread(() -> System.out.println(Singleton_8.INSTANCE.hashCode())).start(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /design-patterns/src/main/resources/app.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /design-patterns/src/main/resources/app_aop.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /fastdfs/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xblzer 8 | fastdfs 9 | 1.0 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | cn.bestwu 19 | fastdfs-client-java 20 | 1.27 21 | 22 | 23 | org.apache.commons 24 | commons-lang3 25 | 3.4 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /fastdfs/src/main/java/cn/chendapeng/fastdfs/utils/FastDfsClient.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.fastdfs.utils; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.csource.common.NameValuePair; 5 | import org.csource.fastdfs.*; 6 | 7 | import java.io.*; 8 | 9 | /** 10 | * 分布式文件系统FastDFS 操作客户端 11 | * 12 | * @author 行百里er 13 | * @date 2022-06-25 18:08 14 | */ 15 | public class FastDfsClient { 16 | 17 | private static final String FASTDFS_CONFIG_FILE_NAME = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "fdfs_client.conf"; 18 | 19 | private static StorageClient storageClient = null; 20 | 21 | static { 22 | try { 23 | ClientGlobal.init(FASTDFS_CONFIG_FILE_NAME); 24 | // 追踪服务 25 | TrackerClient trackerClient = new TrackerClient(ClientGlobal.getG_tracker_group()); 26 | TrackerServer trackerServer = trackerClient.getConnection(); 27 | // 存储服务。追踪器充当客户端和存储服务的媒介,将存储服务的信息获取到 28 | StorageServer storageServer = trackerClient.getStoreStorage(trackerServer); 29 | storageClient = new StorageClient(trackerServer, storageServer); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | /** 36 | * 上传文件 37 | * 38 | * @param file 文件 39 | * @param fileName 文件名 40 | * @return 返回一个数组,第一个元素是组名称,第二个元素时图片名称 41 | */ 42 | public static String[] uploadFile(File file, String fileName) { 43 | FileInputStream fis = null; 44 | try { 45 | fis = new FileInputStream(file); 46 | int len = fis.available(); 47 | byte[] fileBuff = new byte[len]; 48 | fis.read(fileBuff); 49 | 50 | return storageClient.upload_file(fileBuff, getFileExt(fileName), null); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | return null; 54 | } finally { 55 | if (fis != null) { 56 | try { 57 | fis.close(); 58 | } catch (IOException e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | } 63 | } 64 | 65 | /** 66 | * 根据组名和远程文件名来删除一个文件 67 | * 68 | * @param groupName 例如 "group1" 如果不指定该值,默认为group1 69 | * @param remoteFileName 例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg" 70 | * @return 0为成功,非0为失败,具体为错误代码 71 | */ 72 | public static int deleteFile(String groupName, String remoteFileName) { 73 | try { 74 | return storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName); 75 | } catch (Exception ex) { 76 | return 0; 77 | } 78 | } 79 | 80 | /** 81 | * 修改一个已经存在的文件 82 | * 83 | * @param oldGroupName 旧的组名 84 | * @param oldFileName 旧的文件名 85 | * @param file 新文件 86 | * @param fileName 新文件名 87 | * @return 返回空则为失败 88 | */ 89 | public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) { 90 | String[] fileIds; 91 | try { 92 | // 先上传 93 | fileIds = uploadFile(file, fileName); 94 | if (fileIds == null) { 95 | return null; 96 | } 97 | // 再删除 98 | int delResult = deleteFile(oldGroupName, oldFileName); 99 | if (delResult != 0) { 100 | return null; 101 | } 102 | } catch (Exception ex) { 103 | return null; 104 | } 105 | return fileIds; 106 | } 107 | 108 | /** 109 | * 文件下载 110 | * 111 | * @param groupName 组名 112 | * @param remoteFileName 文件名 113 | * @return 返回一个流 114 | */ 115 | public static InputStream downloadFile(String groupName, String remoteFileName) { 116 | try { 117 | byte[] bytes = storageClient.download_file(groupName, remoteFileName); 118 | return new ByteArrayInputStream(bytes); 119 | } catch (Exception ex) { 120 | return null; 121 | } 122 | } 123 | 124 | 125 | public static NameValuePair[] getMetaData(String groupName, String remoteFileName) { 126 | try { 127 | return storageClient.get_metadata(groupName, remoteFileName); 128 | } catch (Exception ex) { 129 | ex.printStackTrace(); 130 | return null; 131 | } 132 | } 133 | 134 | /** 135 | * 获取文件后缀名(不带点). 136 | * 137 | * @return 如:"jpg" or "". 138 | */ 139 | private static String getFileExt(String fileName) { 140 | if (StringUtils.isBlank(fileName) || !fileName.contains(".")) { 141 | return ""; 142 | } else { 143 | return fileName.substring(fileName.lastIndexOf(".") + 1); 144 | } 145 | } 146 | 147 | public static void main(String[] args) { 148 | // 上传 149 | // File file = new File("D:/apptest/test.jpg"); 150 | // String fileName = "test.jpg"; 151 | // String[] uploadResult = uploadFile(file, fileName); 152 | // System.out.println(Arrays.toString(uploadResult)); 153 | 154 | // 下载 155 | try { 156 | // 上传时有个返回结果包含group和文件磁盘及文件名信息 157 | InputStream is = downloadFile("group1", "M00/00/00/wKjycGK25DSAM3pvAAGQJOaIBGg984.jpg"); 158 | OutputStream os = new FileOutputStream("D:/fastdfs.png"); 159 | int index; 160 | while ((index = is.read()) != -1) { 161 | os.write(index); 162 | } 163 | os.flush(); 164 | os.close(); 165 | is.close(); 166 | } catch (IOException e) { 167 | e.printStackTrace(); 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /fastdfs/src/main/resources/fdfs_client.conf: -------------------------------------------------------------------------------- 1 | connect_timeout = 10 2 | network_timeout = 30 3 | charset = UTF-8 4 | http.tracker_http_port = 8080 5 | tracker_server = 192.168.242.112:22122 6 | -------------------------------------------------------------------------------- /shardingsphere/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | mvnw 22 | mvnw.cmd 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | -------------------------------------------------------------------------------- /shardingsphere/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | cn.chendapeng 6 | shardingsphere 7 | 0.0.1-SNAPSHOT 8 | shardingsphere 9 | Demo project for Spring Boot 10 | 11 | 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | 2.3.7.RELEASE 16 | 17 | 18 | 19 | 20 | org.apache.shardingsphere 21 | sharding-jdbc-spring-boot-starter 22 | 4.1.1 23 | 24 | 25 | com.alibaba 26 | druid 27 | 1.2.3 28 | 29 | 30 | org.mybatis.spring.boot 31 | mybatis-spring-boot-starter 32 | 2.1.4 33 | 34 | 35 | 36 | mysql 37 | mysql-connector-java 38 | runtime 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-test 43 | test 44 | 45 | 46 | org.junit.vintage 47 | junit-vintage-engine 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-dependencies 58 | ${spring-boot.version} 59 | pom 60 | import 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-compiler-plugin 70 | 3.8.1 71 | 72 | 1.8 73 | 1.8 74 | UTF-8 75 | 76 | 77 | 78 | org.springframework.boot 79 | spring-boot-maven-plugin 80 | 2.3.7.RELEASE 81 | 82 | cn.chendapeng.shardingsphere.ShardingsphereApplication 83 | 84 | 85 | 86 | repackage 87 | 88 | repackage 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /shardingsphere/src/main/java/cn/chendapeng/shardingsphere/ShardingsphereApplication.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.shardingsphere; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ShardingsphereApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(ShardingsphereApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /shardingsphere/src/main/java/cn/chendapeng/shardingsphere/bean/Laogong.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.shardingsphere.bean; 2 | 3 | /** 4 | * @author 行百里者 5 | * @since 2020/11/19 21:04 6 | **/ 7 | public class Laogong { 8 | 9 | private Integer id; 10 | private String name; 11 | private Integer age; 12 | 13 | public Integer getId() { 14 | return id; 15 | } 16 | 17 | public void setId(Integer id) { 18 | this.id = id; 19 | } 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | public void setName(String name) { 26 | this.name = name; 27 | } 28 | 29 | public Integer getAge() { 30 | return age; 31 | } 32 | 33 | public void setAge(Integer age) { 34 | this.age = age; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "Laogong{" + 40 | "id=" + id + 41 | ", name='" + name + '\'' + 42 | ", age=" + age + 43 | '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /shardingsphere/src/main/java/cn/chendapeng/shardingsphere/mapper/LaogongMapper.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.shardingsphere.mapper; 2 | 3 | import cn.chendapeng.shardingsphere.bean.Laogong; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Select; 7 | import org.springframework.stereotype.Repository; 8 | 9 | /** 10 | * @author 行百里者 11 | * @since 2020/11/19 21:05 12 | **/ 13 | @Repository 14 | @Mapper 15 | public interface LaogongMapper { 16 | 17 | @Insert("insert into laogong(id, name, age) values(#{id}, #{name}, #{age})") 18 | void addLaogong(Laogong laogong); 19 | 20 | @Select("select * from laogong where id=#{id}") 21 | Laogong queryLaogong(Integer id); 22 | } 23 | -------------------------------------------------------------------------------- /shardingsphere/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenDapengJava/JavaJourney/5116a7506bb433ca43551a057c3163b73038a328/shardingsphere/src/main/resources/application.yml -------------------------------------------------------------------------------- /shardingsphere/src/test/java/com/xblzer/shardingsphere/ShardingsphereApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xblzer.shardingsphere; 2 | 3 | import cn.chendapeng.shardingsphere.bean.Laogong; 4 | import cn.chendapeng.shardingsphere.mapper.LaogongMapper; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import java.util.Random; 10 | 11 | @SpringBootTest 12 | class ShardingsphereApplicationTests { 13 | 14 | @Autowired 15 | private LaogongMapper laogongMapper; 16 | 17 | @Test 18 | public void testMSInsert() { 19 | for (int i = 1; i <= 5; i++) { 20 | Laogong laogong = new Laogong(); 21 | laogong.setId(i); 22 | laogong.setName("xblzer" + i); 23 | laogong.setAge(new Random().nextInt(30)); 24 | laogongMapper.addLaogong(laogong); 25 | } 26 | } 27 | 28 | @Test 29 | public void testMSQuery() { 30 | for (int i = 0; i < 10; i++) { 31 | Laogong laogong = laogongMapper.queryLaogong(1); 32 | System.out.println(laogong); 33 | } 34 | } 35 | 36 | @Test 37 | public void test() { 38 | System.out.println(new Random().nextInt(20)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /tryout/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xblzer 8 | tryout 9 | 1.0 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | com.xblzer.tryout.agent 19 | ObjectSizeAgent 20 | 1.0 21 | 22 | 23 | com.google.guava 24 | guava 25 | 29.0-jre 26 | 27 | 28 | org.projectlombok 29 | lombok 30 | 1.18.12 31 | provided 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /tryout/src/main/java/cn/chendapeng/tryout/CreateObjectTest.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.tryout; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author 行百里者 7 | * @date 2022-08-03 10:48 8 | */ 9 | public class CreateObjectTest { 10 | public static void main(String[] args) throws ClassNotFoundException { 11 | //对象.getClass() 12 | // User user = new User(); 13 | // Class clazz = user.getClass(); 14 | // System.out.println(clazz.getPackage()); 15 | // System.out.println(clazz.getName()); 16 | // System.out.println(clazz.getCanonicalName()); 17 | // System.out.println(clazz.getSimpleName()); 18 | //类.class 19 | // Class clazz = User.class; 20 | //Class.forName 21 | Class clazz = Class.forName("cn.chendapeng.tryout.bean.User"); 22 | System.out.println("getConstructors:"); 23 | Arrays.stream(clazz.getConstructors()).iterator().forEachRemaining(System.out::println); 24 | System.out.println("getDeclaredFields:"); 25 | Arrays.stream(clazz.getDeclaredFields()).iterator().forEachRemaining(System.out::println); 26 | System.out.println("getDeclaredMethods:"); 27 | Arrays.stream(clazz.getDeclaredMethods()).iterator().forEachRemaining(System.out::println); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tryout/src/main/java/cn/chendapeng/tryout/OOMTest.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.tryout; 2 | 3 | //import com.google.common.util.concurrent.ThreadFactoryBuilder; 4 | //import lombok.Data; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.ArrayList; 8 | import java.util.Date; 9 | import java.util.List; 10 | import java.util.Random; 11 | import java.util.concurrent.ScheduledThreadPoolExecutor; 12 | import java.util.concurrent.ThreadPoolExecutor; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * 测试OOM 17 | * 18 | * @author 行百里者 19 | * @since 2020/11/01 14:39 20 | **/ 21 | public class OOMTest { 22 | //定时任务线程池 23 | private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(24, 24 | //new ThreadFactoryBuilder().setNameFormat("处理告警信息线程-%d").build(), 25 | new ThreadPoolExecutor.DiscardOldestPolicy()); 26 | 27 | public static void main(String[] args) throws InterruptedException { 28 | System.out.println("program starts"); 29 | executor.setMaximumPoolSize(50); 30 | //业务处理 31 | while (true) { 32 | //获取告警列表 33 | List list = getAlarmList(); 34 | list.forEach(alarmInfo -> { 35 | executor.scheduleWithFixedDelay(() -> { 36 | alarmInfo.alarmCheck(); 37 | }, 2, 3, TimeUnit.SECONDS); 38 | }); 39 | Thread.sleep(100); 40 | } 41 | } 42 | 43 | //模拟获取告警列表 44 | private static List getAlarmList() { 45 | List list = new ArrayList<>(); 46 | for (int i = 0; i < 200; i++) { 47 | AlarmInfo alarmInfo = new AlarmInfo(); 48 | alarmInfo.setId(i); 49 | alarmInfo.setAlarmType("type" + i); 50 | alarmInfo.setAlarmTime(new Date()); 51 | alarmInfo.setDuration(new BigDecimal(new Random().nextInt(10000))); 52 | list.add(alarmInfo); 53 | } 54 | return list; 55 | } 56 | 57 | //模拟告警数据 58 | // @Data 59 | public static class AlarmInfo { 60 | private Integer id; 61 | private String alarmType; 62 | private Date alarmTime; 63 | private BigDecimal duration; 64 | 65 | //处理业务逻辑 66 | public void alarmCheck() { 67 | //System.out.println("do something"); 68 | } 69 | 70 | public void setId(Integer id) { 71 | this.id = id; 72 | } 73 | 74 | public void setAlarmType(String alarmType) { 75 | this.alarmType = alarmType; 76 | } 77 | 78 | public void setAlarmTime(Date alarmTime) { 79 | this.alarmTime = alarmTime; 80 | } 81 | 82 | public void setDuration(BigDecimal duration) { 83 | this.duration = duration; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tryout/src/main/java/cn/chendapeng/tryout/ObjectSizeTest.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.tryout; 2 | 3 | 4 | import com.xblzer.tryout.agent.ObjectSizeAgent; 5 | 6 | /** 7 | * 测试Object占用字节大小 8 | * 运行时添加制作的agent,添加VM参数: -javaagent:D:\3rd_jar\ObjectSizeAgent.jar 9 | * 10 | * @author 行百里者 11 | * @since 2020/11/03 14:43 12 | **/ 13 | public class ObjectSizeTest { 14 | public static void main(String[] args) { 15 | // // 配置 XX:+UseCompressedClassPointer XX:+UseCompressedOops 16 | // 16字节 = markword 8 + classpointer 4 + padding 4 17 | System.out.println("new Object size:" + ObjectSizeAgent.sizeOf(new Object())); 18 | // 16字节 = markword 8 + classpointer 4 + 数组长度 4 + padding 0(前面已经是8的倍数了) 19 | System.out.println("new array size:" + ObjectSizeAgent.sizeOf(new int[]{})); 20 | // 34+padding=40 (最终必须满足8的倍数) 21 | System.out.println("new a common class size:" + ObjectSizeAgent.sizeOf(new P())); 22 | 23 | // 配置 XX:-UseCompressedClassPointer XX:+UseCompressedOops 24 | // 16字节 = markword 8 + classpointer 8 + padding 0 25 | // System.out.println("new Object size:" + ObjectSizeAgent.sizeOf(new Object())); 26 | // // 24字节 = markword 8 + classpointer 8 + 数组长度 4 + padding 4(补齐至8的倍数) 27 | // System.out.println("new array size:" + ObjectSizeAgent.sizeOf(new int[]{})); 28 | // // 40 (最终必须满足8的倍数) 29 | // System.out.println("new a common class size:" + ObjectSizeAgent.sizeOf(new P())); 30 | } 31 | 32 | private static class P { 33 | // markword 8 34 | // ClassPinter 4 (-UseCompressedClassPointer时 为8;+UseCompressedClassPointer时 为4) 35 | 36 | // 4 37 | int id; 38 | // Oops 4 39 | String name;// 这是一个引用 +UseCompressedOops时 为8 -UseCompressedOops时 为4 40 | // 1 41 | byte b1; 42 | // 1 43 | byte b2; 44 | //Oops 4 45 | Object o; 46 | // 8 47 | long i; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tryout/src/main/java/cn/chendapeng/tryout/bean/User.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.tryout.bean; 2 | 3 | /** 4 | * @author 行百里者 5 | * @date 2022-08-03 10:47 6 | */ 7 | public class User { 8 | private Integer id; 9 | private String userName; 10 | private String phoneNumber; 11 | 12 | public User() { 13 | } 14 | 15 | public User(Integer id, String userName, String phoneNumber) { 16 | this.id = id; 17 | this.userName = userName; 18 | this.phoneNumber = phoneNumber; 19 | } 20 | 21 | public void myDefine() { 22 | System.out.println("xxx"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /zookeeper/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /zookeeper/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | cn.chendapeng 6 | zookeeper 7 | 0.0.1-SNAPSHOT 8 | zookeeper 9 | Demo project for Spring Boot 10 | 11 | 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | 2.3.7.RELEASE 16 | 17 | 18 | 19 | 20 | 21 | org.projectlombok 22 | lombok 23 | 1.18.12 24 | provided 25 | 26 | 27 | 28 | org.apache.zookeeper 29 | zookeeper 30 | 3.7.1 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | org.junit.vintage 40 | junit-vintage-engine 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-dependencies 51 | ${spring-boot.version} 52 | pom 53 | import 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-compiler-plugin 63 | 3.8.1 64 | 65 | 1.8 66 | 1.8 67 | UTF-8 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-maven-plugin 73 | 2.3.7.RELEASE 74 | 75 | cn.chendapeng.zookeeper.ZookeeperApplication 76 | 77 | 78 | 79 | repackage 80 | 81 | repackage 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /zookeeper/src/main/java/cn/chendapeng/zookeeper/config/DefaultWatcher.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.zookeeper.config; 2 | 3 | import org.apache.zookeeper.WatchedEvent; 4 | import org.apache.zookeeper.Watcher; 5 | 6 | import java.util.concurrent.CountDownLatch; 7 | 8 | /** 9 | * 默认的ZK watcher 10 | * @author 行百里者 11 | * @since 2020/09/16 10:18 12 | **/ 13 | public class DefaultWatcher implements Watcher { 14 | 15 | private CountDownLatch latch; 16 | 17 | public DefaultWatcher() { 18 | } 19 | 20 | public DefaultWatcher(CountDownLatch latch) { 21 | this.latch = latch; 22 | } 23 | 24 | @Override 25 | public void process(WatchedEvent watchedEvent) { 26 | System.out.println("DefaultWatcher watchedEvent:" + watchedEvent); 27 | Event.KeeperState state = watchedEvent.getState(); 28 | switch (state) { 29 | case Disconnected: 30 | break; 31 | case SyncConnected: 32 | System.out.println("SyncConnected."); 33 | //连接成功后,执行countDown,此时便可以拿zk对象使用了 34 | latch.countDown(); 35 | break; 36 | case AuthFailed: 37 | break; 38 | case ConnectedReadOnly: 39 | break; 40 | case SaslAuthenticated: 41 | break; 42 | case Expired: 43 | break; 44 | case Closed: 45 | break; 46 | default: 47 | break; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /zookeeper/src/main/java/cn/chendapeng/zookeeper/config/MyConfig.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.zookeeper.config; 2 | 3 | /** 4 | * 自定义配置,根据实际业务自定义 5 | * @author 行百里者 6 | * @since 2020/09/16 10:28 7 | **/ 8 | public class MyConfig { 9 | 10 | private String userServiceConf; 11 | 12 | public String getuserServiceConf() { 13 | return userServiceConf; 14 | } 15 | 16 | public void setuserServiceConf(String userServiceConf) { 17 | this.userServiceConf = userServiceConf; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /zookeeper/src/main/java/cn/chendapeng/zookeeper/config/WatchAndCallback.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.zookeeper.config; 2 | 3 | import org.apache.zookeeper.AsyncCallback; 4 | import org.apache.zookeeper.WatchedEvent; 5 | import org.apache.zookeeper.Watcher; 6 | import org.apache.zookeeper.ZooKeeper; 7 | import org.apache.zookeeper.data.Stat; 8 | 9 | import java.util.concurrent.CountDownLatch; 10 | 11 | /** 12 | * 配置watch和callback 13 | * @author 行百里者 14 | * @since 2020/09/16 10:31 15 | **/ 16 | public class WatchAndCallback implements Watcher, AsyncCallback.StatCallback, AsyncCallback.DataCallback { 17 | 18 | private ZooKeeper zk; 19 | private MyConfig config; 20 | CountDownLatch latch = new CountDownLatch(1); 21 | 22 | public void await() { 23 | zk.exists("/userServiceConf", this, this, "exists watch"); 24 | try { 25 | latch.await(); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | 31 | 32 | /** 33 | * DataCallback 34 | * 此回调用于检索节点的数据和stat 35 | * @param rc 调用返回的code或结果 36 | * @param path 传递给异步调用的路径 37 | * @param ctx 传递给异步调用的上下文对象 38 | * @param data 节点的数据 39 | * @param stat 指定节点的Stat对象 40 | **/ 41 | @Override 42 | public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) { 43 | if (data != null) { 44 | String res = new String(data); 45 | config.setuserServiceConf(res); 46 | latch.countDown(); 47 | } 48 | } 49 | 50 | /** 51 | * StatCallback 52 | * 此回调用于检索节点的stat 53 | * @param rc 调用返回的code或结果 54 | * @param path 传递给异步调用的路径 55 | * @param ctx 传递给异步调用的上下文对象 56 | * @param stat 指定路径上节点的Stat对象 57 | **/ 58 | @Override 59 | public void processResult(int rc, String path, Object ctx, Stat stat) { 60 | if (stat != null) { 61 | zk.getData("/userServiceConf", this, this, "Msg:Stat is not null"); 62 | } 63 | } 64 | 65 | /** 66 | * Watcher接口的实现。 67 | * Watcher接口指定事件处理程序类必须实现的公共接口。 68 | * ZooKeeper客户机将从它连接到的ZooKeeper服务器获取各种事件。 69 | * 使用这种客户机的应用程序通过向客户机注册回调对象来处理这些事件。 70 | * 回调对象应该是实现监视器接口的类的实例。 71 | * @param watchedEvent WatchedEvent表示监视者能够响应的ZooKeeper上的更改。WatchedEvent包含发生了什么,ZooKeeper的当前状态,以及事件中涉及的znode的路径。 72 | **/ 73 | @Override 74 | public void process(WatchedEvent watchedEvent) { 75 | Event.EventType type = watchedEvent.getType(); 76 | switch (type) { 77 | case None: 78 | break; 79 | case NodeCreated: 80 | //当一个node被创建后,获取node 81 | //getData中又会触发StatCallback的回调processResult 82 | zk.getData("/userServiceConf", this, this, "Msg:NodeCreated"); 83 | break; 84 | case NodeDeleted: 85 | //节点被删除 86 | config.setuserServiceConf(""); 87 | //重新开启CountDownLatch 88 | latch = new CountDownLatch(1); 89 | break; 90 | case NodeDataChanged: 91 | //节点数据被改变了 92 | //会触发DataCallback的回调 93 | zk.getData("/userServiceConf", this, this, "Msg:NodeDataChanged"); 94 | break; 95 | case NodeChildrenChanged: 96 | break; 97 | case DataWatchRemoved: 98 | break; 99 | case ChildWatchRemoved: 100 | break; 101 | case PersistentWatchRemoved: 102 | break; 103 | default: 104 | break; 105 | } 106 | } 107 | 108 | public ZooKeeper getZk() { 109 | return zk; 110 | } 111 | 112 | public void setZk(ZooKeeper zk) { 113 | this.zk = zk; 114 | } 115 | 116 | public MyConfig getConfig() { 117 | return config; 118 | } 119 | 120 | public void setConfig(MyConfig config) { 121 | this.config = config; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /zookeeper/src/test/java/cn/chendapeng/zookeeper/ZooKeeperConfigTest.java: -------------------------------------------------------------------------------- 1 | package cn.chendapeng.zookeeper; 2 | 3 | import cn.chendapeng.zookeeper.config.DefaultWatcher; 4 | import cn.chendapeng.zookeeper.config.MyConfig; 5 | import cn.chendapeng.zookeeper.config.WatchAndCallback; 6 | import lombok.SneakyThrows; 7 | import org.apache.zookeeper.ZooKeeper; 8 | import org.junit.jupiter.api.AfterAll; 9 | import org.junit.jupiter.api.BeforeAll; 10 | import org.junit.jupiter.api.Test; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | 14 | import java.util.concurrent.CountDownLatch; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | public class ZooKeeperConfigTest { 18 | // @Value("zookeeper.conf-servers") 19 | // static String servers; 20 | static String servers = "192.168.242.11:2181,192.168.242.12:2181,192.168.242.13:2181,192.168.242.14:2181/conf"; 21 | 22 | static ZooKeeper zk; 23 | 24 | static CountDownLatch latch = new CountDownLatch(1); 25 | 26 | @SneakyThrows 27 | @BeforeAll 28 | public static void getZK() { 29 | System.out.println("servers:" + servers); 30 | //因为是异步的,所以要await,等到连接上zk集群之后再进行后续操作 31 | zk = new ZooKeeper(servers, 3000, new DefaultWatcher(latch)); 32 | latch.await(); 33 | } 34 | 35 | @SneakyThrows 36 | @AfterAll 37 | public static void close() { 38 | zk.close(); 39 | } 40 | 41 | @Test 42 | public void zkConfigTest() { 43 | WatchAndCallback watchAndCallback = new WatchAndCallback(); 44 | MyConfig config = new MyConfig(); 45 | watchAndCallback.setConfig(config); 46 | watchAndCallback.setZk(zk); 47 | 48 | //阻塞等待 49 | watchAndCallback.await(); 50 | 51 | //方便观测,写个死循环 52 | for(;;) { 53 | if (config.getuserServiceConf().equals("")) { 54 | System.out.println("node可能被删除了"); 55 | //此时应该阻塞住,等待着node重新创建 56 | watchAndCallback.await(); 57 | } else { 58 | System.out.println("userServiceConf:" + config.getuserServiceConf()); 59 | } 60 | try { 61 | Thread.sleep(2000); 62 | } catch (InterruptedException e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | } 67 | 68 | } 69 | --------------------------------------------------------------------------------