Browse Source

0526 动态代理和线程池

Qing 1 year ago
parent
commit
31d40526c8
59 changed files with 1112 additions and 3 deletions
  1. 9 2
      12306-demo/my-ticket-service/pom.xml
  2. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/ServiceApplication.java
  3. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/constant/Index12306Constant.java
  4. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/constant/RedisKeyConstant.java
  5. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/controller/MyController.java
  6. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/controller/TicketController.java
  7. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/Builder.java
  8. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/Main.java
  9. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/MyBuilder.java
  10. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/Product.java
  11. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/CEO.java
  12. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Handler.java
  13. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Leader.java
  14. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Main.java
  15. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Manager.java
  16. 40 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/CglibProxyDemo.java
  17. 55 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/JdkProxyDemo.java
  18. 42 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/TestMethodInvoke.java
  19. 75 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/$Proxy0.java
  20. 221 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/$Proxy0Dump.java
  21. 64 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/MyJdkProxyDemo.java
  22. 43 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/TestDump.java
  23. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/Main.java
  24. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/MyStrategyA.java
  25. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/MyStrategyB.java
  26. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/Strategy.java
  27. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/dto/SeatClassDTO.java
  28. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/dto/TicketListDTO.java
  29. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/dto/req/TicketPageQueryReqDTO.java
  30. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/dto/resp/TicketPageQueryRespDTO.java
  31. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/TicketDO.java
  32. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainStationPriceDO.java
  33. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/entity/User.java
  34. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/filter/CustomFilter.java
  35. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/filter/CustomFilter2.java
  36. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/filter/config/FilterConfig.java
  37. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/interceptor/CustomInterceptor.java
  38. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/interceptor/config/InterceptorConfig.java
  39. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TicketMapper.java
  40. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/service/TicketService.java
  41. 9 0
      12306-demo/my-ticket-service/src/main/java/com/sf/service/impl/TicketServiceImpl.java
  42. 14 0
      12306-demo/my-ticket-service/src/main/java/com/sf/threadpool/MyRejectedPolicy.java
  43. 47 0
      12306-demo/my-ticket-service/src/main/java/com/sf/threadpool/PolicyTest.java
  44. 135 0
      12306-demo/my-ticket-service/src/main/java/com/sf/util/SnowflakeIdWorker.java
  45. 0 0
      12306-demo/my-ticket-service/src/main/java/com/sf/util/TimeStringComparator.java
  46. 0 0
      12306-demo/my-ticket-service/src/main/resources/application.yml
  47. 0 0
      12306-demo/my-ticket-service/src/test/java/com/sf/ApplicationTests.java
  48. 0 0
      12306-demo/my-ticket-service/src/test/java/com/sf/UserTest.java
  49. 86 0
      12306-demo/my-user-service/pom.xml
  50. 14 0
      12306-demo/my-user-service/src/main/java/com/sf/UserApplication.java
  51. 22 0
      12306-demo/my-user-service/src/main/java/com/sf/controller/UserController.java
  52. 112 0
      12306-demo/my-user-service/src/main/java/com/sf/entity/User.java
  53. 7 0
      12306-demo/my-user-service/src/main/java/com/sf/mapper/UserMapper.java
  54. 7 0
      12306-demo/my-user-service/src/main/java/com/sf/service/IUserService.java
  55. 11 0
      12306-demo/my-user-service/src/main/java/com/sf/service/impl/UserServiceImpl.java
  56. 15 0
      12306-demo/my-user-service/src/main/resources/application.yml
  57. 44 0
      12306-demo/my-user-service/src/main/resources/shardingsphere-config.yml
  58. 38 0
      12306-demo/my-user-service/src/test/java/com/sf/AppTest.java
  59. 2 1
      12306-demo/pom.xml

+ 9 - 2
12306-demo/my-service/pom.xml → 12306-demo/my-ticket-service/pom.xml

@@ -7,10 +7,10 @@
         <version>0.0.1-SNAPSHOT</version>
     </parent>
 
-    <artifactId>my-service</artifactId>
+    <artifactId>my-ticket-service</artifactId>
     <packaging>jar</packaging>
 
-    <name>my-service</name>
+    <name>my-ticket-service</name>
     <url>http://maven.apache.org</url>
 
     <properties>
@@ -83,5 +83,12 @@
             <artifactId>index12306-log-spring-boot-starter</artifactId>
             <version>${index12306.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+            <version>3.3.0</version>
+        </dependency>
+
     </dependencies>
 </project>

+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/ServiceApplication.java → 12306-demo/my-ticket-service/src/main/java/com/sf/ServiceApplication.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/constant/Index12306Constant.java → 12306-demo/my-ticket-service/src/main/java/com/sf/constant/Index12306Constant.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/constant/RedisKeyConstant.java → 12306-demo/my-ticket-service/src/main/java/com/sf/constant/RedisKeyConstant.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/controller/MyController.java → 12306-demo/my-ticket-service/src/main/java/com/sf/controller/MyController.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/controller/TicketController.java → 12306-demo/my-ticket-service/src/main/java/com/sf/controller/TicketController.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/builder/Builder.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/Builder.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/builder/Main.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/Main.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/builder/MyBuilder.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/MyBuilder.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/builder/Product.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/builder/Product.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/chain/CEO.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/CEO.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/chain/Handler.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Handler.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/chain/Leader.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Leader.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/chain/Main.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Main.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/chain/Manager.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/chain/Manager.java


+ 40 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/CglibProxyDemo.java

@@ -0,0 +1,40 @@
+package com.sf.design.proxy;
+
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+// cglib动态代理
+// 添加jvm参数 --add-opens java.base/java.lang=ALL-UNNAMED
+public class CglibProxyDemo {
+
+    // 目标类
+    static class MyLife {
+        public void learn() {
+            System.out.println("learn");
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        // 目标对象
+        MyLife myLife = new MyLife();
+        // 接收代理对象
+        // cglib的动态代理是基于 继承目标类  extends MyLife
+        MyLife object = (MyLife)Enhancer.create(MyLife.class, new MethodInterceptor() {
+            @Override
+            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
+                System.out.println("before");
+                Object result = method.invoke(myLife, objects);
+                System.out.println("after");
+                return result;
+            }
+        });
+        object.learn();
+
+        System.out.println(object.getClass());
+        System.in.read();
+    }
+}

+ 55 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/JdkProxyDemo.java

@@ -0,0 +1,55 @@
+package com.sf.design.proxy;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+// JDK动态代理
+public class JdkProxyDemo {
+
+    interface Life{
+        void learn();
+    }
+
+    // 被代理类 目标类
+    static class MyLife implements Life{
+
+        @Override
+        public void learn() {
+            System.out.println("learn");
+        }
+    }
+
+    public static void main(String[] args) {
+        // 目标对象
+        MyLife myLife = new MyLife();
+        // 获取类加载器
+        ClassLoader classLoader = JdkProxyDemo.class.getClassLoader();
+        // 来自反射包下的 Proxy类可以创建代理对象
+        // 三个参数  类加载器、由接口类组成的数组、InvocationHandler接口的实现逻辑
+        Life proxyInstance = (Life)Proxy.newProxyInstance(classLoader, new Class[]{Life.class}, new InvocationHandler() {
+            @Override
+            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                // 实现增强的逻辑
+                System.out.println("before");
+                // 通过反射调用目标对象的方法
+//                myLife.learn();
+                Object result = method.invoke(myLife, args);  // 调用方法的对象  方法的入参
+                System.out.println("after");
+                return result;
+            }
+        });
+        // 通过代理对象调用方法
+        proxyInstance.learn();
+
+        System.out.println(proxyInstance.getClass());
+        // 不直接执行结束
+        try {
+            System.in.read();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        // 使用工具查看动态生成的结果  arthas
+    }
+}

+ 42 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/TestMethodInvoke.java

@@ -0,0 +1,42 @@
+package com.sf.design.proxy;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+// 测试反射优化
+// 运行时请添加 --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED
+public class TestMethodInvoke {
+
+    // 前16次 使用java本地api NativeMethodAccessorImpl  性能较差
+    // 第17次 使用动态代理类 GeneratedMethodAccessor2 将反射调用变成正常调用  性能提升
+    public static void main(String[] args) throws Exception {
+        Method foo = TestMethodInvoke.class.getMethod("foo", int.class);
+        // 调用十七次反射
+        for (int i = 1; i <= 17; i++) {
+            show(i, foo);
+            // 调用静态方法 不需要传对象
+            foo.invoke(null, i);
+        }
+        // 阻塞
+        System.in.read();
+    }
+
+    // 方法反射调用时, 底层 MethodAccessor 的实现类
+    private static void show(int i, Method foo) throws Exception {
+        Method getMethodAccessor = Method.class.getDeclaredMethod("getMethodAccessor");
+        getMethodAccessor.setAccessible(true);
+        Object invoke = getMethodAccessor.invoke(foo);
+        if (invoke == null) {
+            System.out.println(i + ":" + null);
+            return;
+        }
+        Field delegate = Class.forName("jdk.internal.reflect.DelegatingMethodAccessorImpl").getDeclaredField("delegate");
+        delegate.setAccessible(true);
+        System.out.println(i + ":" + delegate.get(invoke));
+    }
+
+    public static void foo(int i) {
+        System.out.println(i + ":" + "foo");
+    }
+
+}

+ 75 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/$Proxy0.java

@@ -0,0 +1,75 @@
+package com.sf.design.proxy.self;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+// 代理对象
+// 实现Life接口
+public class $Proxy0 extends Proxy implements MyJdkProxyDemo.Life {
+
+//    private MyJdkProxyDemo.InvocationHandler h;
+//
+//    public $Proxy0(MyJdkProxyDemo.InvocationHandler h) {
+//        this.h = h;
+//    }
+
+//    private InvocationHandler h;
+
+    public $Proxy0(InvocationHandler h) {
+//        this.h = h;
+        super(h);
+    }
+
+//    private MyJdkProxyDemo.Life target;
+//
+//    public $Proxy0(MyJdkProxyDemo.Life target) {
+//        this.target = target;
+//    }
+    // 代理逻辑目前写死了
+//    @Override
+//    public void learn() {
+//        System.out.println("before");
+//        target.learn();
+//        System.out.println("after");
+//    }
+
+    static Method learn;
+    static Method sleep;
+    static {
+        try {
+            learn = MyJdkProxyDemo.Life.class.getDeclaredMethod("learn");
+            sleep = MyJdkProxyDemo.Life.class.getDeclaredMethod("sleep");
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void learn() {
+        try {
+//            Method learn = MyJdkProxyDemo.Life.class.getDeclaredMethod("learn");
+            // 需要方法本身和入参
+            h.invoke(this, learn, new Object[0]);
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // 代理只在方法前后做增强 不影响调用逻辑和返回结果
+    @Override
+    public String sleep() {
+        try {
+//            Method sleep = MyJdkProxyDemo.Life.class.getDeclaredMethod("sleep");
+            // 需要方法本身和入参
+            Object result = h.invoke(this, sleep, new Object[0]);
+            return (String) result;
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 221 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/$Proxy0Dump.java

@@ -0,0 +1,221 @@
+package com.sf.design.proxy.self;
+
+
+import org.springframework.asm.*;
+
+public class $Proxy0Dump implements Opcodes {
+
+    public static byte[] dump() throws Exception {
+
+        ClassWriter classWriter = new ClassWriter(0);
+        FieldVisitor fieldVisitor;
+        RecordComponentVisitor recordComponentVisitor;
+        MethodVisitor methodVisitor;
+        AnnotationVisitor annotationVisitor0;
+
+        classWriter.visit(V17, ACC_PUBLIC | ACC_SUPER, "com/sf/design/proxy/self/$Proxy0", null, "java/lang/reflect/Proxy", new String[]{"com/sf/design/proxy/self/MyJdkProxyDemo$Life"});
+
+        classWriter.visitSource("$Proxy0.java", null);
+
+        classWriter.visitInnerClass("com/sf/design/proxy/self/MyJdkProxyDemo$Life", "com/sf/design/proxy/self/MyJdkProxyDemo", "Life", ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
+
+        {
+            fieldVisitor = classWriter.visitField(ACC_STATIC, "learn", "Ljava/lang/reflect/Method;", null, null);
+            fieldVisitor.visitEnd();
+        }
+        {
+            fieldVisitor = classWriter.visitField(ACC_STATIC, "sleep", "Ljava/lang/reflect/Method;", null, null);
+            fieldVisitor.visitEnd();
+        }
+        {
+            methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/reflect/InvocationHandler;)V", null, null);
+            methodVisitor.visitParameter("h", 0);
+            methodVisitor.visitCode();
+            Label label0 = new Label();
+            methodVisitor.visitLabel(label0);
+            methodVisitor.visitLineNumber(21, label0);
+            methodVisitor.visitVarInsn(ALOAD, 0);
+            methodVisitor.visitVarInsn(ALOAD, 1);
+            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/Proxy", "<init>", "(Ljava/lang/reflect/InvocationHandler;)V", false);
+            Label label1 = new Label();
+            methodVisitor.visitLabel(label1);
+            methodVisitor.visitLineNumber(22, label1);
+            methodVisitor.visitInsn(RETURN);
+            Label label2 = new Label();
+            methodVisitor.visitLabel(label2);
+            methodVisitor.visitLocalVariable("this", "Lcom/sf/design/proxy/self/$Proxy0;", null, label0, label2, 0);
+            methodVisitor.visitLocalVariable("h", "Ljava/lang/reflect/InvocationHandler;", null, label0, label2, 1);
+            methodVisitor.visitMaxs(2, 2);
+            methodVisitor.visitEnd();
+        }
+        {
+            methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "learn", "()V", null, null);
+            methodVisitor.visitCode();
+            Label label0 = new Label();
+            Label label1 = new Label();
+            Label label2 = new Label();
+            methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/NoSuchMethodException");
+            Label label3 = new Label();
+            methodVisitor.visitTryCatchBlock(label0, label1, label3, "java/lang/Throwable");
+            methodVisitor.visitLabel(label0);
+            methodVisitor.visitLineNumber(53, label0);
+            methodVisitor.visitVarInsn(ALOAD, 0);
+            methodVisitor.visitFieldInsn(GETFIELD, "com/sf/design/proxy/self/$Proxy0", "h", "Ljava/lang/reflect/InvocationHandler;");
+            methodVisitor.visitVarInsn(ALOAD, 0);
+            methodVisitor.visitFieldInsn(GETSTATIC, "com/sf/design/proxy/self/$Proxy0", "learn", "Ljava/lang/reflect/Method;");
+            methodVisitor.visitInsn(ICONST_0);
+            methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/Object");
+            methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/lang/reflect/InvocationHandler", "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true);
+            methodVisitor.visitInsn(POP);
+            methodVisitor.visitLabel(label1);
+            methodVisitor.visitLineNumber(58, label1);
+            Label label4 = new Label();
+            methodVisitor.visitJumpInsn(GOTO, label4);
+            methodVisitor.visitLabel(label2);
+            methodVisitor.visitLineNumber(54, label2);
+            methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/NoSuchMethodException"});
+            methodVisitor.visitVarInsn(ASTORE, 1);
+            Label label5 = new Label();
+            methodVisitor.visitLabel(label5);
+            methodVisitor.visitLineNumber(55, label5);
+            methodVisitor.visitTypeInsn(NEW, "java/lang/RuntimeException");
+            methodVisitor.visitInsn(DUP);
+            methodVisitor.visitVarInsn(ALOAD, 1);
+            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V", false);
+            methodVisitor.visitInsn(ATHROW);
+            methodVisitor.visitLabel(label3);
+            methodVisitor.visitLineNumber(56, label3);
+            methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Throwable"});
+            methodVisitor.visitVarInsn(ASTORE, 1);
+            Label label6 = new Label();
+            methodVisitor.visitLabel(label6);
+            methodVisitor.visitLineNumber(57, label6);
+            methodVisitor.visitTypeInsn(NEW, "java/lang/RuntimeException");
+            methodVisitor.visitInsn(DUP);
+            methodVisitor.visitVarInsn(ALOAD, 1);
+            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V", false);
+            methodVisitor.visitInsn(ATHROW);
+            methodVisitor.visitLabel(label4);
+            methodVisitor.visitLineNumber(59, label4);
+            methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+            methodVisitor.visitInsn(RETURN);
+            Label label7 = new Label();
+            methodVisitor.visitLabel(label7);
+            methodVisitor.visitLocalVariable("e", "Ljava/lang/NoSuchMethodException;", null, label5, label3, 1);
+            methodVisitor.visitLocalVariable("e", "Ljava/lang/Throwable;", null, label6, label4, 1);
+            methodVisitor.visitLocalVariable("this", "Lcom/sf/design/proxy/self/$Proxy0;", null, label0, label7, 0);
+            methodVisitor.visitMaxs(4, 2);
+            methodVisitor.visitEnd();
+        }
+        {
+            methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "sleep", "()Ljava/lang/String;", null, null);
+            methodVisitor.visitCode();
+            Label label0 = new Label();
+            Label label1 = new Label();
+            Label label2 = new Label();
+            methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/NoSuchMethodException");
+            Label label3 = new Label();
+            methodVisitor.visitTryCatchBlock(label0, label1, label3, "java/lang/Throwable");
+            methodVisitor.visitLabel(label0);
+            methodVisitor.visitLineNumber(67, label0);
+            methodVisitor.visitVarInsn(ALOAD, 0);
+            methodVisitor.visitFieldInsn(GETFIELD, "com/sf/design/proxy/self/$Proxy0", "h", "Ljava/lang/reflect/InvocationHandler;");
+            methodVisitor.visitVarInsn(ALOAD, 0);
+            methodVisitor.visitFieldInsn(GETSTATIC, "com/sf/design/proxy/self/$Proxy0", "sleep", "Ljava/lang/reflect/Method;");
+            methodVisitor.visitInsn(ICONST_0);
+            methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/Object");
+            methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/lang/reflect/InvocationHandler", "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true);
+            methodVisitor.visitVarInsn(ASTORE, 1);
+            Label label4 = new Label();
+            methodVisitor.visitLabel(label4);
+            methodVisitor.visitLineNumber(68, label4);
+            methodVisitor.visitVarInsn(ALOAD, 1);
+            methodVisitor.visitTypeInsn(CHECKCAST, "java/lang/String");
+            methodVisitor.visitLabel(label1);
+            methodVisitor.visitInsn(ARETURN);
+            methodVisitor.visitLabel(label2);
+            methodVisitor.visitLineNumber(69, label2);
+            methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/NoSuchMethodException"});
+            methodVisitor.visitVarInsn(ASTORE, 1);
+            Label label5 = new Label();
+            methodVisitor.visitLabel(label5);
+            methodVisitor.visitLineNumber(70, label5);
+            methodVisitor.visitTypeInsn(NEW, "java/lang/RuntimeException");
+            methodVisitor.visitInsn(DUP);
+            methodVisitor.visitVarInsn(ALOAD, 1);
+            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V", false);
+            methodVisitor.visitInsn(ATHROW);
+            methodVisitor.visitLabel(label3);
+            methodVisitor.visitLineNumber(71, label3);
+            methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Throwable"});
+            methodVisitor.visitVarInsn(ASTORE, 1);
+            Label label6 = new Label();
+            methodVisitor.visitLabel(label6);
+            methodVisitor.visitLineNumber(72, label6);
+            methodVisitor.visitTypeInsn(NEW, "java/lang/RuntimeException");
+            methodVisitor.visitInsn(DUP);
+            methodVisitor.visitVarInsn(ALOAD, 1);
+            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V", false);
+            methodVisitor.visitInsn(ATHROW);
+            Label label7 = new Label();
+            methodVisitor.visitLabel(label7);
+            methodVisitor.visitLocalVariable("result", "Ljava/lang/Object;", null, label4, label2, 1);
+            methodVisitor.visitLocalVariable("e", "Ljava/lang/NoSuchMethodException;", null, label5, label3, 1);
+            methodVisitor.visitLocalVariable("e", "Ljava/lang/Throwable;", null, label6, label7, 1);
+            methodVisitor.visitLocalVariable("this", "Lcom/sf/design/proxy/self/$Proxy0;", null, label0, label7, 0);
+            methodVisitor.visitMaxs(4, 2);
+            methodVisitor.visitEnd();
+        }
+        {
+            methodVisitor = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
+            methodVisitor.visitCode();
+            Label label0 = new Label();
+            Label label1 = new Label();
+            Label label2 = new Label();
+            methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/NoSuchMethodException");
+            methodVisitor.visitLabel(label0);
+            methodVisitor.visitLineNumber(41, label0);
+            methodVisitor.visitLdcInsn(Type.getType("Lcom/sf/design/proxy/self/MyJdkProxyDemo$Life;"));
+            methodVisitor.visitLdcInsn("learn");
+            methodVisitor.visitInsn(ICONST_0);
+            methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/Class");
+            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getDeclaredMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false);
+            methodVisitor.visitFieldInsn(PUTSTATIC, "com/sf/design/proxy/self/$Proxy0", "learn", "Ljava/lang/reflect/Method;");
+            Label label3 = new Label();
+            methodVisitor.visitLabel(label3);
+            methodVisitor.visitLineNumber(42, label3);
+            methodVisitor.visitLdcInsn(Type.getType("Lcom/sf/design/proxy/self/MyJdkProxyDemo$Life;"));
+            methodVisitor.visitLdcInsn("sleep");
+            methodVisitor.visitInsn(ICONST_0);
+            methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/Class");
+            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getDeclaredMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false);
+            methodVisitor.visitFieldInsn(PUTSTATIC, "com/sf/design/proxy/self/$Proxy0", "sleep", "Ljava/lang/reflect/Method;");
+            methodVisitor.visitLabel(label1);
+            methodVisitor.visitLineNumber(45, label1);
+            Label label4 = new Label();
+            methodVisitor.visitJumpInsn(GOTO, label4);
+            methodVisitor.visitLabel(label2);
+            methodVisitor.visitLineNumber(43, label2);
+            methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/NoSuchMethodException"});
+            methodVisitor.visitVarInsn(ASTORE, 0);
+            Label label5 = new Label();
+            methodVisitor.visitLabel(label5);
+            methodVisitor.visitLineNumber(44, label5);
+            methodVisitor.visitTypeInsn(NEW, "java/lang/RuntimeException");
+            methodVisitor.visitInsn(DUP);
+            methodVisitor.visitVarInsn(ALOAD, 0);
+            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V", false);
+            methodVisitor.visitInsn(ATHROW);
+            methodVisitor.visitLabel(label4);
+            methodVisitor.visitLineNumber(46, label4);
+            methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+            methodVisitor.visitInsn(RETURN);
+            methodVisitor.visitLocalVariable("e", "Ljava/lang/NoSuchMethodException;", null, label5, label4, 0);
+            methodVisitor.visitMaxs(3, 1);
+            methodVisitor.visitEnd();
+        }
+        classWriter.visitEnd();
+
+        return classWriter.toByteArray();
+    }
+}

+ 64 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/MyJdkProxyDemo.java

@@ -0,0 +1,64 @@
+package com.sf.design.proxy.self;
+
+import com.sf.design.proxy.JdkProxyDemo;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+// 手写JDK动态代理
+public class MyJdkProxyDemo {
+
+    interface Life{
+        void learn();
+
+        String sleep();
+    }
+
+    // 被代理类 目标类
+    static class MyLife implements Life {
+
+        @Override
+        public void learn() {
+            System.out.println("learn");
+        }
+
+        @Override
+        public String sleep() {
+            System.out.println("sleep");
+            return "MyLife sleep";
+        }
+    }
+
+    // 触发要代理的方法的处理器
+//    interface InvocationHandler{
+//        // 增加入参  方法本身和参数
+//        Object invoke(Object proxy,Method method, Object[] args);
+//    }
+
+    public static void main(String[] args) {
+        // 目标对象
+        MyLife myLife = new MyLife();
+//        new $Proxy0(myLife).learn();
+
+        // 实际需要的 代理的处理逻辑
+        $Proxy0 proxy = new $Proxy0((proxy1, method, args1) -> {
+            System.out.println("before");
+            // 动态的方法调用
+            try {
+                Object result = method.invoke(myLife, args1);
+                System.out.println("after");
+                return result;
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
+            } catch (InvocationTargetException e) {
+                throw new RuntimeException(e);
+            }
+        });
+        proxy.learn();
+        System.out.println("======");
+        String sleepRes = proxy.sleep();
+        System.out.println(sleepRes);
+    }
+
+}

+ 43 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/design/proxy/self/TestDump.java

@@ -0,0 +1,43 @@
+package com.sf.design.proxy.self;
+
+import java.io.FileOutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class TestDump {
+
+    // 整个过程是 生成字节码 -》 类加载器加载字节码 -》 获取类构造器 -》 构造代理对象 -》 通过代理对象调用
+    public static void main(String[] args) throws Exception {
+        byte[] dump = $Proxy0Dump.dump();
+        // 写到文件里
+//        FileOutputStream fos = new FileOutputStream("$Proxy0.class");
+//        fos.write(dump);
+//        fos.close();
+
+        // 加载字节码
+        // 声明类加载器
+        ClassLoader classLoader = new ClassLoader(){
+            @Override
+            protected Class<?> findClass(String name) throws ClassNotFoundException {
+                // 将字节码数据加载进来
+                return super.defineClass(name, dump, 0, dump.length);
+            }
+        };
+
+        // 类加载器加载类名
+        Class<?> loadClass = classLoader.loadClass("com.sf.design.proxy.self.$Proxy0");
+        // 找到有InvocationHandler的构造器
+        Constructor<?> constructor = loadClass.getConstructor(InvocationHandler.class);
+        // 动态创建代理对象
+        MyJdkProxyDemo.Life object = (MyJdkProxyDemo.Life)constructor.newInstance(new InvocationHandler() {
+            @Override
+            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                System.out.println("before");
+                return null;
+            }
+        });
+        // 通过代理对象 调用方法
+        object.learn();
+    }
+}

+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/strategy/Main.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/Main.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/strategy/MyStrategyA.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/MyStrategyA.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/strategy/MyStrategyB.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/MyStrategyB.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/design/strategy/Strategy.java → 12306-demo/my-ticket-service/src/main/java/com/sf/design/strategy/Strategy.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/dto/SeatClassDTO.java → 12306-demo/my-ticket-service/src/main/java/com/sf/dto/SeatClassDTO.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/dto/TicketListDTO.java → 12306-demo/my-ticket-service/src/main/java/com/sf/dto/TicketListDTO.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/dto/req/TicketPageQueryReqDTO.java → 12306-demo/my-ticket-service/src/main/java/com/sf/dto/req/TicketPageQueryReqDTO.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/dto/resp/TicketPageQueryRespDTO.java → 12306-demo/my-ticket-service/src/main/java/com/sf/dto/resp/TicketPageQueryRespDTO.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/entity/TicketDO.java → 12306-demo/my-ticket-service/src/main/java/com/sf/entity/TicketDO.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/entity/TrainStationPriceDO.java → 12306-demo/my-ticket-service/src/main/java/com/sf/entity/TrainStationPriceDO.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/entity/User.java → 12306-demo/my-ticket-service/src/main/java/com/sf/entity/User.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/filter/CustomFilter.java → 12306-demo/my-ticket-service/src/main/java/com/sf/filter/CustomFilter.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/filter/CustomFilter2.java → 12306-demo/my-ticket-service/src/main/java/com/sf/filter/CustomFilter2.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/filter/config/FilterConfig.java → 12306-demo/my-ticket-service/src/main/java/com/sf/filter/config/FilterConfig.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/interceptor/CustomInterceptor.java → 12306-demo/my-ticket-service/src/main/java/com/sf/interceptor/CustomInterceptor.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/interceptor/config/InterceptorConfig.java → 12306-demo/my-ticket-service/src/main/java/com/sf/interceptor/config/InterceptorConfig.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/mapper/TicketMapper.java → 12306-demo/my-ticket-service/src/main/java/com/sf/mapper/TicketMapper.java


+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/service/TicketService.java → 12306-demo/my-ticket-service/src/main/java/com/sf/service/TicketService.java


+ 9 - 0
12306-demo/my-service/src/main/java/com/sf/service/impl/TicketServiceImpl.java → 12306-demo/my-ticket-service/src/main/java/com/sf/service/impl/TicketServiceImpl.java

@@ -56,6 +56,15 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, TicketDO> imple
         // 遍历其中每个元素 转化为多个TicketListDTO对象组成的list
         List<TicketListDTO> seatResults = regionTrainStationAllMap.values().stream().map(
                 each -> JSON.parseObject(each.toString(), TicketListDTO.class)).toList();
+
+        //使用普通的方式来处理的逻辑
+//        List<TicketListDTO> newSeatResults = new ArrayList<>();
+//        Collection<Object> values = regionTrainStationAllMap.values();
+//        values.forEach((Object each) -> {
+//            TicketListDTO ticketListDTO = JSON.parseObject(each.toString(), TicketListDTO.class);
+//            newSeatResults.add(ticketListDTO);
+//        });
+
         // 按照出发时间排序
         seatResults = seatResults.stream().sorted(new TimeStringComparator()).toList();
         for (TicketListDTO each : seatResults) {

+ 14 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/threadpool/MyRejectedPolicy.java

@@ -0,0 +1,14 @@
+package com.sf.threadpool;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+// 自定义拒绝策略
+public class MyRejectedPolicy implements RejectedExecutionHandler {
+
+    @Override
+    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
+        System.out.println("anything");
+        throw  new RuntimeException();
+    }
+}

+ 47 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/threadpool/PolicyTest.java

@@ -0,0 +1,47 @@
+package com.sf.threadpool;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class PolicyTest {
+
+    public static void main(String[] args) {
+        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
+                1, 3, 1024, TimeUnit.SECONDS,
+                new LinkedBlockingDeque<>(1), new MyRejectedPolicy());
+
+        threadPoolExecutor.setRejectedExecutionHandler(new MyRejectedPolicy());
+
+        for (int i = 0; i < 5; i++) {
+            threadPoolExecutor.execute(() -> {
+                try {
+                    Thread.sleep(100000000L);
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+            });
+        }
+
+//        for (int i = 0; i < 5; i++) {
+//            threadPoolExecutor.execute(new Runnable() {
+//                @Override
+//                public void run() {
+//                    try {
+//                        Thread.sleep(100000000L);
+//                    } catch (InterruptedException e) {
+//                        throw new RuntimeException(e);
+//                    }
+//                }
+//            });
+//
+//            threadPoolExecutor.submit(new Callable<String>() {
+//                @Override
+//                public String call() throws Exception {
+//                    return "";
+//                }
+//            });
+//        }
+    }
+}

+ 135 - 0
12306-demo/my-ticket-service/src/main/java/com/sf/util/SnowflakeIdWorker.java

@@ -0,0 +1,135 @@
+package com.sf.util;
+
+public class SnowflakeIdWorker {
+    /**
+     * 开始时间截 (2015-01-01)
+     */
+    private final long twepoch = 1420041600000L;
+    /**
+     * 机器id所占的位数
+     */
+    private final long workerIdBits = 5L;
+    /**
+     * 数据标识id所占的位数
+     */
+    private final long datacenterIdBits = 5L;
+    /**
+     * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
+     */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+    /**
+     * 支持的最大数据标识id,结果是31
+     */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+    /**
+     * 序列在id中占的位数
+     */
+    private final long sequenceBits = 12L;
+    /**
+     * 机器ID向左移12位
+     */
+    private final long workerIdShift = sequenceBits;
+    /**
+     * 数据标识id向左移17位(12+5)
+     */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+    /**
+     * 时间截向左移22位(5+5+12)
+     */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+    /**
+     * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
+     */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+    /**
+     * 工作机器ID(0~31)
+     */
+    private long workerId;
+    /**
+     * 数据中心ID(0~31)
+     */
+    private long datacenterId;
+    /**
+     * 毫秒内序列(0~4095)
+     */
+    private long sequence = 0L;
+    /**
+     * 上次生成ID的时间截
+     */
+    private long lastTimestamp = -1L;
+    /**
+     * 构造函数
+     * @param workerId     工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public SnowflakeIdWorker(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+        // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+        // 如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            // 毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        // 时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+        // 上次生成ID的时间截
+        lastTimestamp = timestamp;
+        // 移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+    /**
+     * 返回以毫秒为单位的当前时间
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    public static void main(String[] args) throws InterruptedException {
+        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
+        for (int i = 0; i < 10; i++) {
+            long id = idWorker.nextId();
+            Thread.sleep(1);
+            System.out.println(id);
+        }
+    }
+}

+ 0 - 0
12306-demo/my-service/src/main/java/com/sf/util/TimeStringComparator.java → 12306-demo/my-ticket-service/src/main/java/com/sf/util/TimeStringComparator.java


+ 0 - 0
12306-demo/my-service/src/main/resources/application.yml → 12306-demo/my-ticket-service/src/main/resources/application.yml


+ 0 - 0
12306-demo/my-service/src/test/java/com/sf/ApplicationTests.java → 12306-demo/my-ticket-service/src/test/java/com/sf/ApplicationTests.java


+ 0 - 0
12306-demo/my-service/src/test/java/com/sf/UserTest.java → 12306-demo/my-ticket-service/src/test/java/com/sf/UserTest.java


+ 86 - 0
12306-demo/my-user-service/pom.xml

@@ -0,0 +1,86 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.sf</groupId>
+        <artifactId>demo-12306</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>my-user-service</artifactId>
+    <packaging>jar</packaging>
+
+    <name>my-user-service</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <java.version>17</java.version>
+        <mybatis-plus.version>3.5.3</mybatis-plus.version>
+        <springdoc.version>2.0.2</springdoc.version>
+        <shardingsphere.version>5.3.2</shardingsphere.version>
+        <lombok.version>1.18.32</lombok.version>
+    </properties>
+
+    <dependencies>
+        <!-- springboot 的web依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- mybatis plus 的依赖-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatis-plus.version}</version>
+        </dependency>
+
+        <!-- mysql驱动 的依赖-->
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!-- 整合jdbc -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+
+        <!-- lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+        </dependency>
+
+        <!-- 分库分表中间件 -->
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-jdbc-core</artifactId>
+            <version>${shardingsphere.version}</version>
+        </dependency>
+
+        <!-- swagger -->
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
+            <version>${springdoc.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+            <version>${springdoc.version}</version>
+        </dependency>
+
+        <!-- 测试 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

+ 14 - 0
12306-demo/my-user-service/src/main/java/com/sf/UserApplication.java

@@ -0,0 +1,14 @@
+package com.sf;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@MapperScan("com.sf.mapper")
+public class UserApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(UserApplication.class, args);
+    }
+}

+ 22 - 0
12306-demo/my-user-service/src/main/java/com/sf/controller/UserController.java

@@ -0,0 +1,22 @@
+package com.sf.controller;
+
+import com.sf.entity.User;
+import com.sf.service.IUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class UserController {
+
+    @Autowired
+    private IUserService userService;
+
+    // http://localhost:9001/save
+    @GetMapping("/save")
+    public String save() {
+        User user = User.builder().username("test").password("123").realName("testtest").build();
+        userService.save(user);
+        return "success";
+    }
+}

+ 112 - 0
12306-demo/my-user-service/src/main/java/com/sf/entity/User.java

@@ -0,0 +1,112 @@
+package com.sf.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@TableName("t_user")
+public class User {
+
+    /**
+     * id
+     */
+    private Long id;
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 真实姓名
+     */
+    private String realName;
+
+    /**
+     * 国家/地区
+     */
+    private String region;
+
+    /**
+     * 证件类型
+     */
+    private Integer idType;
+
+    /**
+     * 证件号
+     */
+    private String idCard;
+
+    /**
+     * 手机号
+     */
+    private String phone;
+
+    /**
+     * 固定电话
+     */
+    private String telephone;
+
+    /**
+     * 邮箱
+     */
+    private String mail;
+
+    /**
+     * 旅客类型
+     */
+    private Integer userType;
+
+    /**
+     * 审核状态
+     */
+    private Integer verifyStatus;
+
+    /**
+     * 邮编
+     */
+    private String postCode;
+
+    /**
+     * 地址
+     */
+    private String address;
+
+    /**
+     * 注销时间戳
+     */
+    private Long deletionTime;
+
+    /**
+     * 创建时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+
+    /**
+     * 修改时间
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+
+    /**
+     * 删除标志
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Integer delFlag;
+}

+ 7 - 0
12306-demo/my-user-service/src/main/java/com/sf/mapper/UserMapper.java

@@ -0,0 +1,7 @@
+package com.sf.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sf.entity.User;
+
+public interface UserMapper extends BaseMapper<User> {
+}

+ 7 - 0
12306-demo/my-user-service/src/main/java/com/sf/service/IUserService.java

@@ -0,0 +1,7 @@
+package com.sf.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.sf.entity.User;
+
+public interface IUserService extends IService<User> {
+}

+ 11 - 0
12306-demo/my-user-service/src/main/java/com/sf/service/impl/UserServiceImpl.java

@@ -0,0 +1,11 @@
+package com.sf.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sf.entity.User;
+import com.sf.mapper.UserMapper;
+import com.sf.service.IUserService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
+}

+ 15 - 0
12306-demo/my-user-service/src/main/resources/application.yml

@@ -0,0 +1,15 @@
+
+spring:
+  application:
+    name: my-user-service
+  datasource:
+    # 修改驱动
+#    driver-class-name: com.mysql.cj.jdbc.Driver
+    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
+#    username: root
+#    password: root123456
+#    url: jdbc:mysql://127.0.0.1:3306/railway_ticket?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8
+    url: jdbc:shardingsphere:classpath:shardingsphere-config.yml
+
+server:
+  port: 9001

+ 44 - 0
12306-demo/my-user-service/src/main/resources/shardingsphere-config.yml

@@ -0,0 +1,44 @@
+# 数据源集合
+dataSources:
+  # 逻辑数据源名称
+  ds_0:
+    # 数据源类型
+    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
+    # 数据库驱动
+    driverClassName: com.mysql.cj.jdbc.Driver
+    # 数据库连接
+    jdbcUrl: jdbc:mysql://127.0.0.1:3306/railway?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
+    # 用户名,如果本地数据库与这个不一致,需要修改
+    username: root
+    # 密码,如果本地数据库与这个不一致,需要修改
+    password: root123456
+
+# ShardingSphere 规则配置,包含:数据分片、数据加密、读写分离等
+rules:
+  - !SHARDING
+    # 需要数据分片的表集合
+    tables:
+      # 逻辑表名
+      t_user:
+        # 真实存在数据库的物理表集合
+        actualDataNodes: ds_0.t_user_${0..1}
+        # 分表策略
+        tableStrategy:
+          # 单分片键分表
+          standard:
+            # 自定义分片字段
+            shardingColumn: id
+            # 自定义分片算法名称,对应 {rules[0].shardingAlgorithms.user_table_hash_mod}
+            shardingAlgorithmName: user_table_hash_mod
+    # 数据分片算法定义集合
+    shardingAlgorithms:
+      # 自定义分片算法名称
+      user_table_hash_mod:
+        # 分片方式,HASH_MODE,按照 HASH 的方式对分片键进行操作,获取真实的物理表索引
+        type: HASH_MOD
+        props:
+          # 物理表分片数量
+          sharding-count: 2
+props:
+  # 是否打印逻辑SQL和真实SQL,开发测试环境建议开放,生产环境建议关闭
+  sql-show: true

+ 38 - 0
12306-demo/my-user-service/src/test/java/com/sf/AppTest.java

@@ -0,0 +1,38 @@
+package com.sf;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}

+ 2 - 1
12306-demo/pom.xml

@@ -16,7 +16,8 @@
 
     <modules>
         <module>my-spring-boot-starter</module>
-        <module>my-service</module>
+        <module>my-ticket-service</module>
+        <module>my-user-service</module>
     </modules>
     <packaging>pom</packaging>