diff --git a/01jvm/JvmClassLoaderPrintPath.java b/01jvm/JvmClassLoaderPrintPath.java index 5ff32757..0ab31054 100644 --- a/01jvm/JvmClassLoaderPrintPath.java +++ b/01jvm/JvmClassLoaderPrintPath.java @@ -3,10 +3,26 @@ import java.net.URLClassLoader; import java.util.List; +/** + * @author Joly + * @Descriptopn 当出现jar包没有加载进去的时候,就可以这么输出类加载器加载的jar包来看看是不是路径给少了 + */ public class JvmClassLoaderPrintPath { public static void main(String[] args) { - + /** knowledge point: + * 1.启动类加载器会在JVM启动时就去加载jre的一些核心jar包和/jre/classes + * 2.启动类加载器是JVM底层运行的,使用C++写的。 + * 3.Launcher:是JVM启动后运行的第一个java类 + */ + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/lib/resources.jar + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/lib/rt.jar + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/lib/sunrsasign.jar + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/lib/jsse.jar + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/lib/jce.jar + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/lib/charsets.jar + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/lib/jfr.jar + // ===> file:/D:/ITTools/Java/jdk1.8.0_131/jre/classes // 启动类加载器 URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs(); System.out.println("启动类加载器"); @@ -15,10 +31,12 @@ public static void main(String[] args) { } // 扩展类加载器 - printClassloader("扩展类加载器",JvmClassLoaderPrintPath.class.getClassLoader().getParent()); - + printClassloader("扩展类加载器", JvmClassLoaderPrintPath.class.getClassLoader().getParent()); + /** knowledge point: + * 所以一个类被加载的时候,是先从应用类加载器开始找的 + */ // 应用类加载器 - printClassloader("应用类加载器",JvmClassLoaderPrintPath.class.getClassLoader()); + printClassloader("应用类加载器", JvmClassLoaderPrintPath.class.getClassLoader()); } @@ -33,8 +51,8 @@ private static void printClassloader(String name, ClassLoader classLoader) { } private static void printURLForClassloader(ClassLoader classLoader) { - Object ucp = insightField(classLoader,"ucp"); - Object path = insightField(ucp,"path"); + Object ucp = insightField(classLoader, "ucp"); + Object path = insightField(ucp, "path"); List paths = (List) path; for (Object p : paths) { System.out.println(" ===> " + p.toString()); @@ -51,8 +69,7 @@ private static Object insightField(Object obj, String fName) { } f.setAccessible(true); return f.get(obj); - } - catch (Exception ex) { + } catch (Exception ex) { ex.printStackTrace(); } return null; diff --git a/01jvm/clazz/ClazzA.java b/01jvm/clazz/ClazzA.java new file mode 100644 index 00000000..47f70962 --- /dev/null +++ b/01jvm/clazz/ClazzA.java @@ -0,0 +1,17 @@ +package clazz; + +/** + * @author Joly + */ +public class ClazzA { + static int a = 1; + int b = 11; + + static { + a = 2; + b = 22; + c = 222; + } + + static int c = 111; +} diff --git a/01jvm/clazz/InterfaceA.java b/01jvm/clazz/InterfaceA.java new file mode 100644 index 00000000..c8502fa7 --- /dev/null +++ b/01jvm/clazz/InterfaceA.java @@ -0,0 +1,8 @@ +package clazz; + +/** + * @author Joly + */ +public interface InterfaceA { + +} diff --git a/01jvm/clazz/Person.java b/01jvm/clazz/Person.java new file mode 100644 index 00000000..1d3736b2 --- /dev/null +++ b/01jvm/clazz/Person.java @@ -0,0 +1,29 @@ +package clazz; + +/** + * 配合TwoMethodClazz做练习 + * + * @author Joly + */ +public class Person { + int age; + String name; + final String GENDER = "女"; + final Long HEIGHT = 163L; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/01jvm/clazz/TwoMethodClazz.java b/01jvm/clazz/TwoMethodClazz.java new file mode 100644 index 00000000..ad5c61ba --- /dev/null +++ b/01jvm/clazz/TwoMethodClazz.java @@ -0,0 +1,36 @@ +package clazz; + +/** + * 生成字节码文件,研究该字节码文件如何对应JVM以及如何对应java + * + * @author Joly + */ +public class TwoMethodClazz { + + static { + System.out.println("静态代码块"); + } + + private static String s1 = "静态变量"; + + public static void main(String[] args) { + TwoMethodClazz tmc = new TwoMethodClazz(); + int c1 = tmc.one(); + System.out.println("finish"); + Person p = new Person(); + tmc.two(c1, p); + } + + public int one() { + int a = 1; + int b = 2; + int c = a + b; + return c; + } + + private void two(int aa, Person pp) { + System.out.println(aa + 1); + pp.setAge(26); + pp.setName("Joly"); + } +} diff --git a/01jvm/jvm/HelloClassLoader.java b/01jvm/jvm/HelloClassLoader.java index c465f987..b2130ba9 100644 --- a/01jvm/jvm/HelloClassLoader.java +++ b/01jvm/jvm/HelloClassLoader.java @@ -12,7 +12,12 @@ public static void main(String[] args) throws Exception { protected Class findClass(String name) throws ClassNotFoundException { String helloBase64 = "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAg8Y2xpbml0PgEAClNvdXJjZUZpbGUBAApIZWxsby5qYXZhDAAHAAgHABYMABcAGAEAGEhlbGxvIENsYXNzIEluaXRpYWxpemVkIQcAGQwAGgAbAQAJanZtL0hlbGxvAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAgABAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAMACAALAAgAAQAJAAAAJQACAAAAAAAJsgACEgO2AASxAAAAAQAKAAAACgACAAAABQAIAAYAAQAMAAAAAgAN"; byte[] bytes = decode(helloBase64); - return defineClass(name,bytes,0,bytes.length); + return defineClass(name, bytes, 0, bytes.length); + } + + @Override + protected Class loadClass(String name, boolean resolve) { + return null; } public byte[] decode(String base64) { diff --git a/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java b/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java index 81f31d2e..a623b425 100644 --- a/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java +++ b/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java @@ -16,13 +16,24 @@ import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; +/** + * 适配器 + * + * @author jrl + * @date 2021-9-23 + */ public class HttpHandler extends ChannelInboundHandlerAdapter { - + @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } + /** + * @param msg 所有请求的报文 + * @return + * @date 2021-9-23 + */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { try { @@ -30,13 +41,14 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { FullHttpRequest fullRequest = (FullHttpRequest) msg; String uri = fullRequest.uri(); //logger.info("接收到的请求url为{}", uri); + // 这里就相当于一个路由或者是spring mvc 里面的mapping if (uri.contains("/test")) { handlerTest(fullRequest, ctx, "hello,kimmking"); } else { handlerTest(fullRequest, ctx, "hello,others"); } - - } catch(Exception e) { + + } catch (Exception e) { e.printStackTrace(); } finally { ReferenceCountUtil.release(msg); @@ -44,6 +56,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { } private void handlerTest(FullHttpRequest fullRequest, ChannelHandlerContext ctx, String body) { + // 需要组装FullHTTPResponse这个对象 FullHttpResponse response = null; try { String value = body; // 对接上次作业的httpclient或者okhttp请求另一个url的响应数据 @@ -57,7 +70,7 @@ private void handlerTest(FullHttpRequest fullRequest, ChannelHandlerContext ctx, response.headers().setInt("Content-Length", response.content().readableBytes()); } catch (Exception e) { - System.out.println("处理出错:"+e.getMessage()); + System.out.println("处理出错:" + e.getMessage()); response = new DefaultFullHttpResponse(HTTP_1_1, NO_CONTENT); } finally { if (fullRequest != null) { diff --git a/02nio/nio01/src/main/java/java0/nio01/netty/HttpInitializer.java b/02nio/nio01/src/main/java/java0/nio01/netty/HttpInitializer.java index ff4ee0be..9c1a1630 100644 --- a/02nio/nio01/src/main/java/java0/nio01/netty/HttpInitializer.java +++ b/02nio/nio01/src/main/java/java0/nio01/netty/HttpInitializer.java @@ -6,14 +6,24 @@ import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; +/** + * 流水线 + * + * @author jrl + * @date 2021-9-23 + */ public class HttpInitializer extends ChannelInitializer { - - @Override - public void initChannel(SocketChannel ch) { - ChannelPipeline p = ch.pipeline(); - p.addLast(new HttpServerCodec()); - //p.addLast(new HttpServerExpectContinueHandler()); - p.addLast(new HttpObjectAggregator(1024 * 1024)); - p.addLast(new HttpHandler()); - } + + @Override + public void initChannel(SocketChannel ch) { + // 在这次IO中需要我们自己控制流水线部分 + ChannelPipeline p = ch.pipeline(); + // 添加了HTTPServer编码器 + p.addLast(new HttpServerCodec()); + //p.addLast(new HttpServerExpectContinueHandler()); + // 添加了聚合器 + p.addLast(new HttpObjectAggregator(1024 * 1024)); + // 添加了适配器 + p.addLast(new HttpHandler()); + } } diff --git a/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java b/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java index 487d7283..2f1b6795 100644 --- a/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java +++ b/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java @@ -11,6 +11,10 @@ import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +/** + * @author jrl + * @date 2021-9-23 + */ public class NettyHttpServer { public static void main(String[] args) throws InterruptedException { @@ -20,7 +24,9 @@ public static void main(String[] args) throws InterruptedException { EventLoopGroup workerGroup = new NioEventLoopGroup(16); try { + //作为NettyHttpServer启动的入口点 ServerBootstrap b = new ServerBootstrap(); + // 绑定各种channel的参数 b.option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_KEEPALIVE, true) @@ -30,11 +36,11 @@ public static void main(String[] args) throws InterruptedException { .childOption(EpollChannelOption.SO_REUSEPORT, true) .childOption(ChannelOption.SO_KEEPALIVE, true) .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); - + // 给启动器入口点绑定事件还有适配器 b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new HttpInitializer()); - + // 把启动器入口点绑定端口和channel,也就是把服务器给启动了 Channel ch = b.bind(port).sync().channel(); System.out.println("开启netty http服务器,监听地址和端口为 http://127.0.0.1:" + port + '/'); ch.closeFuture().sync(); diff --git a/02nio/nio02/README.md b/02nio/nio02/README.md index 82214410..4311e17d 100644 --- a/02nio/nio02/README.md +++ b/02nio/nio02/README.md @@ -1,6 +1,8 @@ # netty-gateway ``` - - +1.(必做)整合你上次作业的 httpclient/okhttp; +2.(选做)使用 netty 实现后端 http 访问(代替上一步骤) +3.(必做)实现过滤器。 +4.(选做)实现路由。 ``` \ No newline at end of file diff --git a/02nio/nio02/src/main/java/io/github/kimmking/gateway/NettyServerApplication.java b/02nio/nio02/src/main/java/io/github/kimmking/gateway/NettyServerApplication.java index e67b7961..13535b63 100644 --- a/02nio/nio02/src/main/java/io/github/kimmking/gateway/NettyServerApplication.java +++ b/02nio/nio02/src/main/java/io/github/kimmking/gateway/NettyServerApplication.java @@ -5,14 +5,21 @@ import java.util.Arrays; +/** + * knowledge point: + * 个人认为:用netty实现gateway需要实现的功能点是: + * 1.设置好gateway的端口和要代理的服务的端口 + * 2.把客户端的请求准确的传递到被代理的服务中 + * 3.做一些过滤器和路由的附加操作 + */ public class NettyServerApplication { - + public final static String GATEWAY_NAME = "NIOGateway"; public final static String GATEWAY_VERSION = "3.0.0"; - + public static void main(String[] args) { - String proxyPort = System.getProperty("proxyPort","8888"); + String proxyPort = System.getProperty("proxyPort", "8888"); // 这是之前的单个后端url的例子 // String proxyServer = System.getProperty("proxyServer","http://localhost:8088"); @@ -20,16 +27,18 @@ public static void main(String[] args) { // // http://localhost:8088/api/hello ==> backend service // java -Xmx512m gateway-server-0.0.1-SNAPSHOT.jar #作为后端服务 - + // knowledge use:网关就是用来代理业务服务的 // 这是多个后端url走随机路由的例子 - String proxyServers = System.getProperty("proxyServers","http://localhost:8801,http://localhost:8802"); + String proxyServers = System.getProperty("proxyServers", "http://localhost:8801,http://localhost:8802"); int port = Integer.parseInt(proxyPort); - System.out.println(GATEWAY_NAME + " " + GATEWAY_VERSION +" starting..."); + System.out.println(GATEWAY_NAME + " " + GATEWAY_VERSION + " starting..."); + // done HttpInboundServer是什么 ---> 是用来处理输出的模块 + // done 不应该是用netty写的什么server吗,那么这个httpInboundServer就是用netty框架写的nio的服务是吗 ---> 是的 HttpInboundServer server = new HttpInboundServer(port, Arrays.asList(proxyServers.split(","))); - System.out.println(GATEWAY_NAME + " " + GATEWAY_VERSION +" started at http://localhost:" + port + " for server:" + server.toString()); + System.out.println(GATEWAY_NAME + " " + GATEWAY_VERSION + " started at http://localhost:" + port + " for server:" + server.toString()); try { server.run(); - }catch (Exception ex){ + } catch (Exception ex) { ex.printStackTrace(); } } diff --git a/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundHandler.java b/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundHandler.java index 69b40fde..0d066844 100644 --- a/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundHandler.java +++ b/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundHandler.java @@ -12,18 +12,24 @@ import java.util.List; +/** + * 每个channel要怎么处理io事件,从io准备好数据以后,进行的处理,到业务处理的接口调用 + * + * @author jrl + * @date 2021-9-28 + */ public class HttpInboundHandler extends ChannelInboundHandlerAdapter { private static Logger logger = LoggerFactory.getLogger(HttpInboundHandler.class); private final List proxyServer; private HttpOutboundHandler handler; private HttpRequestFilter filter = new HeaderHttpRequestFilter(); - + public HttpInboundHandler(List proxyServer) { this.proxyServer = proxyServer; this.handler = new HttpOutboundHandler(this.proxyServer); } - + @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); @@ -39,10 +45,10 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { // if (uri.contains("/test")) { // handlerTest(fullRequest, ctx); // } - + // todo 这里把过滤器进行了执行是吗 handler.handle(fullRequest, ctx, filter); - - } catch(Exception e) { + + } catch (Exception e) { e.printStackTrace(); } finally { ReferenceCountUtil.release(msg); diff --git a/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundInitializer.java b/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundInitializer.java index 1d651fb1..8619c664 100644 --- a/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundInitializer.java +++ b/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundInitializer.java @@ -11,23 +11,30 @@ import java.util.List; +/** + * @author jrl + * @date 2021-9-28 + */ public class HttpInboundInitializer extends ChannelInitializer { - - private List proxyServer; - - public HttpInboundInitializer(List proxyServer) { - this.proxyServer = proxyServer; - } - - @Override - public void initChannel(SocketChannel ch) { - ChannelPipeline p = ch.pipeline(); + + private List proxyServer; + + public HttpInboundInitializer(List proxyServer) { + this.proxyServer = proxyServer; + } + + @Override + public void initChannel(SocketChannel ch) { + ChannelPipeline p = ch.pipeline(); // if (sslCtx != null) { // p.addLast(sslCtx.newHandler(ch.alloc())); // } - p.addLast(new HttpServerCodec()); - //p.addLast(new HttpServerExpectContinueHandler()); - p.addLast(new HttpObjectAggregator(1024 * 1024)); - p.addLast(new HttpInboundHandler(this.proxyServer)); - } + // 添加了HTTPServer编码器 + p.addLast(new HttpServerCodec()); + //p.addLast(new HttpServerExpectContinueHandler()); + // 添加了聚合器 + p.addLast(new HttpObjectAggregator(1024 * 1024)); + // 添加了适配器 + p.addLast(new HttpInboundHandler(this.proxyServer)); + } } diff --git a/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundServer.java b/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundServer.java index 97d54ccd..b2934024 100644 --- a/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundServer.java +++ b/02nio/nio02/src/main/java/io/github/kimmking/gateway/inbound/HttpInboundServer.java @@ -16,41 +16,77 @@ import java.util.List; +/** + * HttpInboundServer 其实就是gateway对io请求进来的处理 + * 1.就是用Netty实现的 + * 2.reactor主从模型 + * 3.作用:维护io连接,将io事件处理好后交给业务程序 + * + * @author jrl + * @date 2021-9-28 + */ @Data public class HttpInboundServer { - + /** + * 端口号(自己的端口号,请求直接设置成发给这个端口撒) + * + * @author jrl + * @date 2021-9-28 + */ private int port; - + /** + * 代理的服务器(比如业务服务器) + * + * @author jrl + * @date 2021-9-28 + */ private List proxyServers; public HttpInboundServer(int port, List proxyServers) { - this.port=port; + this.port = port; this.proxyServers = proxyServers; } + /** + * 这是整个服务真正核心被执行的方法 + * Netty实现了Reactor的主从模型 + * + * @param + * @return + * @date 2021-9-28 + */ public void run() throws Exception { + /** knowledge point: mainReactor 负责对io的连接维护 */ EventLoopGroup bossGroup = new NioEventLoopGroup(1); + /** knowledge point: subReactor 负责对事件的分发*/ EventLoopGroup workerGroup = new NioEventLoopGroup(16); try { + // knowledge use: netty写的server的启动入口点 ServerBootstrap b = new ServerBootstrap(); + // knowledge use:用于设置正在建立连接的网络连接数最大可以是多少 b.option(ChannelOption.SO_BACKLOG, 128) + /* knowledge use: TCP发送网络包的时候的优化策略:TCP会把同一个程序的数据合在一起来统一发送. + * 设置TCP_NODELAY就能屏蔽Nagle算法. + */ .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_KEEPALIVE, true) .childOption(ChannelOption.SO_REUSEADDR, true) + // knowledge use:接受数据和发送数据的缓冲区,这样就可以不满就发送出去,就快一点 .childOption(ChannelOption.SO_RCVBUF, 32 * 1024) .childOption(ChannelOption.SO_SNDBUF, 32 * 1024) .childOption(EpollChannelOption.SO_REUSEPORT, true) .childOption(ChannelOption.SO_KEEPALIVE, true) .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); - + // 绑定EventLoopGroup 和 Handler b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.DEBUG)) .childHandler(new HttpInboundInitializer(this.proxyServers)); - + // 启动服务器(绑定端口) Channel ch = b.bind(port).sync().channel(); System.out.println("开启netty http服务器,监听地址和端口为 http://127.0.0.1:" + port + '/'); + /** todo doubt: 这在干嘛*/ ch.closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); diff --git a/02nio/nio02/src/main/java/io/github/kimmking/gateway/outbound/httpclient4/HttpOutboundHandler.java b/02nio/nio02/src/main/java/io/github/kimmking/gateway/outbound/httpclient4/HttpOutboundHandler.java index c20c9be5..15e4eab0 100644 --- a/02nio/nio02/src/main/java/io/github/kimmking/gateway/outbound/httpclient4/HttpOutboundHandler.java +++ b/02nio/nio02/src/main/java/io/github/kimmking/gateway/outbound/httpclient4/HttpOutboundHandler.java @@ -32,8 +32,11 @@ import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; +/** + * done doubt: outbound负责的是 从网关到客户端,还是从网关到业务服务 ---> outbound负责的是 由应用程序主动请求而触发的事件 + */ public class HttpOutboundHandler { - + private CloseableHttpAsyncClient httpclient; private ExecutorService proxyService; private List backendUrls; @@ -42,43 +45,54 @@ public class HttpOutboundHandler { HttpEndpointRouter router = new RandomHttpEndpointRouter(); public HttpOutboundHandler(List backends) { - + // backend 后端 this.backendUrls = backends.stream().map(this::formatUrl).collect(Collectors.toList()); int cores = Runtime.getRuntime().availableProcessors(); long keepAliveTime = 1000; int queueSize = 2048; RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();//.DiscardPolicy(); + // 创建了线程池 proxyService = new ThreadPoolExecutor(cores, cores, keepAliveTime, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(queueSize), new NamedThreadFactory("proxyService"), handler); - + IOReactorConfig ioConfig = IOReactorConfig.custom() .setConnectTimeout(1000) .setSoTimeout(1000) .setIoThreadCount(cores) .setRcvBufSize(32 * 1024) .build(); - + /** todo doubt: 这是啥*/ httpclient = HttpAsyncClients.custom().setMaxConnTotal(40) .setMaxConnPerRoute(8) .setDefaultIOReactorConfig(ioConfig) - .setKeepAliveStrategy((response,context) -> 6000) + .setKeepAliveStrategy((response, context) -> 6000) .build(); httpclient.start(); } private String formatUrl(String backend) { - return backend.endsWith("/")?backend.substring(0,backend.length()-1):backend; + return backend.endsWith("/") ? backend.substring(0, backend.length() - 1) : backend; } - + + // todo 为什么要用final修饰 public void handle(final FullHttpRequest fullRequest, final ChannelHandlerContext ctx, HttpRequestFilter filter) { + // 随机获取一个路由(业务处理程序) String backendUrl = router.route(this.backendUrls); final String url = backendUrl + fullRequest.uri(); + // 在这里执行了过滤器 filter.filter(fullRequest, ctx); - proxyService.submit(()->fetchGet(fullRequest, ctx, url)); + proxyService.submit(() -> fetchGet(fullRequest, ctx, url)); } - + + /** + * 准备进行业务处理 + * + * @param + * @return + * @date 2021-9-28 + */ private void fetchGet(final FullHttpRequest inbound, final ChannelHandlerContext ctx, final String url) { final HttpGet httpGet = new HttpGet(url); //httpGet.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE); @@ -93,23 +107,23 @@ public void completed(final HttpResponse endpointResponse) { } catch (Exception e) { e.printStackTrace(); } finally { - + } } - + @Override public void failed(final Exception ex) { httpGet.abort(); ex.printStackTrace(); } - + @Override public void cancelled() { httpGet.abort(); } }); } - + private void handleResponse(final FullHttpRequest fullRequest, final ChannelHandlerContext ctx, final HttpResponse endpointResponse) throws Exception { FullHttpResponse response = null; try { @@ -117,24 +131,24 @@ private void handleResponse(final FullHttpRequest fullRequest, final ChannelHand // response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(value.getBytes("UTF-8"))); // response.headers().set("Content-Type", "application/json"); // response.headers().setInt("Content-Length", response.content().readableBytes()); - - + + byte[] body = EntityUtils.toByteArray(endpointResponse.getEntity()); // System.out.println(new String(body)); // System.out.println(body.length); - + response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(body)); response.headers().set("Content-Type", "application/json"); response.headers().setInt("Content-Length", Integer.parseInt(endpointResponse.getFirstHeader("Content-Length").getValue())); - + // todo 对输出数据进行过滤 filter.filter(response); // for (Header e : endpointResponse.getAllHeaders()) { // //response.headers().set(e.getName(),e.getValue()); // System.out.println(e.getName() + " => " + e.getValue()); // } - + } catch (Exception e) { e.printStackTrace(); response = new DefaultFullHttpResponse(HTTP_1_1, NO_CONTENT); @@ -151,13 +165,13 @@ private void handleResponse(final FullHttpRequest fullRequest, final ChannelHand ctx.flush(); //ctx.close(); } - + } - + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } - - + + } diff --git a/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/HttpEndpointRouter.java b/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/HttpEndpointRouter.java index 8e307ab7..4ad69842 100644 --- a/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/HttpEndpointRouter.java +++ b/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/HttpEndpointRouter.java @@ -2,10 +2,18 @@ import java.util.List; +/** + * @author jrl + * @date 2021-9-28 + */ public interface HttpEndpointRouter { - + /** + * @param + * @return + * @date 2021-9-28 + */ String route(List endpoints); - + // Load Balance // Random // RoundRibbon @@ -13,5 +21,5 @@ public interface HttpEndpointRouter { // - server01,20 // - server02,30 // - server03,50 - + } diff --git a/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/RandomHttpEndpointRouter.java b/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/RandomHttpEndpointRouter.java index 684d1ba5..a4a0ace3 100644 --- a/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/RandomHttpEndpointRouter.java +++ b/02nio/nio02/src/main/java/io/github/kimmking/gateway/router/RandomHttpEndpointRouter.java @@ -2,7 +2,10 @@ import java.util.List; import java.util.Random; - +/** + * @author jrl + * @date 2021-9-28 + */ public class RandomHttpEndpointRouter implements HttpEndpointRouter { @Override public String route(List urls) { diff --git a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java b/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java deleted file mode 100644 index acaea31e..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java +++ /dev/null @@ -1,24 +0,0 @@ -package java0.conc0301; - -public class DaemonThread { - - public static void main(String[] args) throws InterruptedException { - Runnable task = () -> { - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Thread t = Thread.currentThread(); - System.out.println("当前线程:" + t.getName()); - }; - Thread thread = new Thread(task); - thread.setName("test-thread-1"); - thread.setDaemon(true); - thread.start(); - - //Thread.sleep(5500); - } - - -} diff --git a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java deleted file mode 100644 index 1cbf6a5a..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java +++ /dev/null @@ -1,52 +0,0 @@ -package java0.conc0301.op; - -public class Join { - - public static void main(String[] args) { - Object oo = new Object(); - - MyThread thread1 = new MyThread("thread1 -- "); - //oo = thread1; - thread1.setOo(oo); - thread1.start(); - - synchronized (oo) { // 这里用oo或thread1/this - for (int i = 0; i < 100; i++) { - if (i == 20) { - try { - oo.wait(0); - //thread1.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println(Thread.currentThread().getName() + " -- " + i); - } - } - } - -} - -class MyThread extends Thread { - - private String name; - private Object oo; - - public void setOo(Object oo) { - this.oo = oo; - } - - public MyThread(String name) { - this.name = name; - } - - @Override - public void run() { - synchronized (oo) { // 这里用oo或this,效果不同 - for (int i = 0; i < 100; i++) { - System.out.println(name + i); - } - } - } - -} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java deleted file mode 100644 index 33ad0bab..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java +++ /dev/null @@ -1,45 +0,0 @@ -package java0.conc0302.lock; - -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -class ConditionDemo { - final Lock lock = new ReentrantLock(); - final Condition notFull = lock.newCondition(); - final Condition notEmpty = lock.newCondition(); - - final Object[] items = new Object[20]; - int putptr, takeptr, count; - - public void put(Object x) throws InterruptedException { - lock.lock(); - try { - // 当count等于数组的大小时,当前线程等待,直到notFull通知,再进行生产 - while (count == items.length) - notFull.await(); - items[putptr] = x; - if (++putptr == items.length) putptr = 0; - ++count; - notEmpty.signal(); - } finally { - lock.unlock(); - } - } - - public Object take() throws InterruptedException { - lock.lock(); - try { - // 当count为0,进入等待,直到notEmpty通知,进行消费。 - while (count == 0) - notEmpty.await(); - Object x = items[takeptr]; - if (++takeptr == items.length) takeptr = 0; - --count; - notFull.signal(); - return x; - } finally { - lock.unlock(); - } - } -} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java deleted file mode 100644 index 1dc47538..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java +++ /dev/null @@ -1,38 +0,0 @@ -package java0.conc0302.lock; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.ReentrantLock; - -public class TestFair { - public static volatile int race=0; - public static ReentrantLock lock = new ReentrantLock(true); // 改成false会好100倍 - public static void increase(){ - lock.lock(); - race++; //变量自增操作 - lock.unlock(); - } - private static final int THREADS_COUNT=20; - public static void main(String[]args){ - int count = Thread.activeCount(); - long now = System.currentTimeMillis(); - System.out.println(count); - AtomicReference sign =new AtomicReference<>(); - Thread[]threads=new Thread[THREADS_COUNT]; //定义20个线程 - for(int i=0;icount) { - Thread.yield(); - } - System.out.println(lock.getClass().getName() + " ts = "+ (System.currentTimeMillis()-now)); - } -} - diff --git a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java deleted file mode 100644 index dee7b07c..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java +++ /dev/null @@ -1,29 +0,0 @@ - -package java0.conc0302.threadpool; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class NewSingleThreadExecutorDemo { - - public static void main(String[] args) { - - ExecutorService executorService = Executors.newSingleThreadExecutor(); - - for (int i = 0; i < 10; i++) { - final int no = i; - executorService.execute(() -> { - System.out.println("start:" + no); - try { - Thread.sleep(1000L); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("end:" + no); - }); - } - executorService.shutdown(); - System.out.println("Main Thread End!"); - } - -} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java b/03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java deleted file mode 100644 index 14a16383..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java +++ /dev/null @@ -1,23 +0,0 @@ -package java0.conc0303.future; - -import java.util.Random; -import java.util.concurrent.*; - -public class FutureDemo1 { - public static void main(String[] args) { - ExecutorService executor = Executors.newCachedThreadPool(); - Future result = executor.submit(new Callable() { - public Integer call() throws Exception { - return new Random().nextInt(); - } - }); - executor.shutdown(); - try { - System.out.println("result:" + result.get()); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java b/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java deleted file mode 100644 index b93731be..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java +++ /dev/null @@ -1,33 +0,0 @@ -package java0.conc0303.tool; - -import java.util.concurrent.CountDownLatch; - -public class CountDownLatchDemo { - public static void main(String[] args) throws InterruptedException { - CountDownLatch countDownLatch = new CountDownLatch(5); - for(int i=0;i<5;i++){ - new Thread(new readNum(i,countDownLatch)).start(); - } - countDownLatch.await(); // 注意跟CyclicBarrier不同,这里在主线程await - System.out.println("==>各个子线程执行结束。。。。"); - System.out.println("==>主线程执行结束。。。。"); - } - - static class readNum implements Runnable{ - private int id; - private CountDownLatch latch; - public readNum(int id,CountDownLatch latch){ - this.id = id; - this.latch = latch; - } - @Override - public void run() { - synchronized (this){ - System.out.println("id:"+id+","+Thread.currentThread().getName()); - //latch.countDown(); - System.out.println("线程组任务"+id+"结束,其他任务继续"); - latch.countDown(); - } - } - } -} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java b/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java deleted file mode 100644 index 2acb724a..00000000 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java +++ /dev/null @@ -1,36 +0,0 @@ -package java0.conc0303.tool; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Semaphore; - -public class SemaphoreDemo2 { - - private final static int threadCount = 20; - - public static void main(String[] args) throws Exception { - - ExecutorService exec = Executors.newCachedThreadPool(); - - final Semaphore semaphore = new Semaphore(5); - - for (int i = 0; i < threadCount; i++) { - final int threadNum = i; - exec.execute(() -> { - try { - semaphore.acquire(3); // 获取全部许可,退化成串行执行 - test(threadNum); - semaphore.release(3); // 释放多个许可 - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - exec.shutdown(); - } - - private static void test(int threadNum) throws Exception { - System.out.println("id:"+threadNum+","+Thread.currentThread().getName()); - Thread.sleep(1000); - } - } diff --git a/03concurrency/0301/pom.xml "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/pom.xml" similarity index 100% rename from 03concurrency/0301/pom.xml rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/pom.xml" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/DaemonThread.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/DaemonThread.java" new file mode 100644 index 00000000..d1fa53a8 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/DaemonThread.java" @@ -0,0 +1,40 @@ +package java0.conc0301; + +/** + * 如果JVM判断到当前进程只剩下守护线程,那么就会直接把这个进程给停掉 + * + * @author jrl + * @date 2021/10/12 + */ +public class DaemonThread { + + public static void main(String[] args) throws InterruptedException { + + /** knowledge point: + * 实例化接口,其实是匿名内部类(这里用lambda来实现匿名内部类),本质上来说还是实例化类 + */ + Runnable task = () -> { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Thread t = Thread.currentThread(); + System.out.println("当前线程:" + t.getName()); + }; + Thread thread = new Thread(task); + thread.setName("test-thread-1"); + /** knowledge point: + * 设置该线程为守护线程 + * setDaemon()需要在start()之前,否则会抛运行时异常 + */ + thread.setDaemon(true); + thread.start(); + /** knowledge point: + * 可以通过增加main线程的执行时间,来让守护线程被执行(因为守护线程需要大概五秒) + */ + Thread.sleep(5500); + } + + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0301/Runner1.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/Runner1.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/Runner1.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/Runner1.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0301/Runner2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/Runner2.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/Runner2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/Runner2.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0301/RunnerMain.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/RunnerMain.java" similarity index 75% rename from 03concurrency/0301/src/main/java/java0/conc0301/RunnerMain.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/RunnerMain.java" index 626f2d38..695ab680 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/RunnerMain.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/RunnerMain.java" @@ -18,10 +18,10 @@ public static void main(String[] args) throws IOException { thread2.interrupt(); // i = true - System.out.println(Thread.activeCount()); + System.out.println("Thread.activeCount():"+Thread.activeCount()); Thread.currentThread().getThreadGroup().list(); - System.out.println(Thread.currentThread().getThreadGroup().getParent().activeGroupCount()); + System.out.println("sout:"+Thread.currentThread().getThreadGroup().getParent().activeGroupCount()); Thread.currentThread().getThreadGroup().getParent().list(); diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadA.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadA.java" similarity index 76% rename from 03concurrency/0301/src/main/java/java0/conc0301/ThreadA.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadA.java" index 50e548f6..726fbe60 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/ThreadA.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadA.java" @@ -1,5 +1,11 @@ package java0.conc0301; +/** + * 创建线程的三种基本方式: + * 1. 继承 Thread 类 + * + * @author Joly + */ public class ThreadA extends Thread { public void run() { diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadB.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadB.java" similarity index 92% rename from 03concurrency/0301/src/main/java/java0/conc0301/ThreadB.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadB.java" index fe7dda58..ba7d2f4c 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/ThreadB.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadB.java" @@ -1,5 +1,11 @@ package java0.conc0301; +/** + * 创建线程的三种基本方式: + * 2. 实现 Runnable接口,再用 Thread类 + * + * @author Joly + */ public class ThreadB implements Runnable { @Override diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadC.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadC.java" similarity index 67% rename from 03concurrency/0301/src/main/java/java0/conc0301/ThreadC.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadC.java" index cc01e3b8..015d2645 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/ThreadC.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadC.java" @@ -2,6 +2,12 @@ import java.util.concurrent.Callable; +/** + * 创建线程的三种基本方式: + * 3. 实现 Callable接口,放在 Task 里,再用 Thread 类 + * + * @author Joly + */ public class ThreadC implements Callable { @Override @@ -12,5 +18,4 @@ public String call() throws Exception { } - } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadCount.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadCount.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/ThreadCount.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadCount.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadMain.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadMain.java" similarity index 76% rename from 03concurrency/0301/src/main/java/java0/conc0301/ThreadMain.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadMain.java" index 5478e112..62567240 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/ThreadMain.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadMain.java" @@ -3,21 +3,29 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; +/** + * 创建线程的三种基本方式 + * + * @author Joly + */ public class ThreadMain { public static void main(String[] args) { - + //1 ThreadA threadA = new ThreadA(); threadA.start(); System.out.println("这是主线程:"); - + //2 + // Runnable 其实就是个任务 ThreadB threadB = new ThreadB(); new Thread(threadB).start(); System.out.println("这是主线程:"); - - ThreadC threadC = new ThreadC(); + //3 + ThreadC threadC = new ThreadC(); + //把 Callable 装进了 任务(FutureTask 实现了 Runnable)中 FutureTask futureTask = new FutureTask<>(threadC); new Thread(futureTask).start(); + System.out.println("这是主线程:begin!"); try { System.out.println("得到的返回结果是:" + futureTask.get()); diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadMain2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadMain2.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/ThreadMain2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadMain2.java" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/HighConcurrency.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/HighConcurrency.java" new file mode 100644 index 00000000..9af26bce --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/HighConcurrency.java" @@ -0,0 +1,30 @@ +package java0.conc0301.jrl; + +public class HighConcurrency { + + public static void main(String[] args) { + try { + Thread threadTest = new Thread() { + public void run() { + System.out.println("执行线程中方法"); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }; + threadTest.start(); + synchronized (threadTest) { + /** knowledge point: + * 如果synchronized获得对象锁是线程的实例时,此时比较特殊, + * 当该线程终止的时候,会调用线程自身的notifyAll()方法,会通知所有等待在该线程对象上的线程。 + */ + threadTest.wait(); //当线程终止的时候,会调用线程自身的notifyAll()方法 + } + System.out.println("执行到了这里"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/MultiObject.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/MultiObject.java" new file mode 100644 index 00000000..ee0148ec --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/MultiObject.java" @@ -0,0 +1,20 @@ +package java0.conc0301.jrl; + +/** + * @author jrl + * @date Create in 10:19 2023/2/7 + */ +public class MultiObject { + public static void main(String[] args) { + Object object1 = new Object(); + Object object2 = new Object(); + synchronized (object1) { + synchronized (object2) { + System.out.println("do something 1"); + System.out.println("业务上可以释放 object1 了"); + System.out.println("do something 2"); + System.out.println("业务上可以释放 object2 了"); + } + } + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/ThreadJoin.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/ThreadJoin.java" new file mode 100644 index 00000000..e5ab9362 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/ThreadJoin.java" @@ -0,0 +1,34 @@ +package java0.conc0301.jrl; + +import jdk.nashorn.internal.ir.Block; + +/** + * 练习join + * + * @author jrl + * @date Create in 12:42 2021-10-13 + */ +public class ThreadJoin { + static Integer lock = 1; + + public static void main(String[] args) throws InterruptedException { + Thread t1 = new Thread(() -> { + synchronized (lock) { + System.out.println("t1正在执行"); + } + }); + + t1.start(); + synchronized (lock) { + System.out.println("main线程正在执行,lock对象被main线程占有"); + try { + // 这个时候因为main线程占有了lock对象的锁,所以t1永远都拿不到lock对象的锁,t1就执行不动run方法里面的方法 + t1.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + System.out.println("main线程结束"); + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/TwiceStartMethod.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/TwiceStartMethod.java" new file mode 100644 index 00000000..e5c13c92 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/TwiceStartMethod.java" @@ -0,0 +1,17 @@ +package java0.conc0301.jrl; + +/** + * @author jrl + * @date Create in 19:52 2022/12/19 + */ +public class TwiceStartMethod { + public static void main(String[] args) throws InterruptedException { + Thread thread = new Thread(() -> { + System.out.println("hello"); + }); + thread.start(); + Thread.sleep(5000); + thread.start(); + + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/GlobalVariable.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/GlobalVariable.java" new file mode 100644 index 00000000..3938e79b --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/GlobalVariable.java" @@ -0,0 +1,20 @@ +package java0.conc0301.jrl.share; + +/** + * 有状态:会有线程安全问题 + * + * @author jrl + * @date Create in 21:50 2023/1/16 + */ +public class GlobalVariable implements Runnable { + + Integer ii = 0; + + @Override + public void run() { + for (int i = 0; i < 100000; i++) { + ii++; + } + System.out.println(ii);//111474 + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariable.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariable.java" new file mode 100644 index 00000000..fc094c14 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariable.java" @@ -0,0 +1,18 @@ +package java0.conc0301.jrl.share; + +/** + * 无状态:没有线程安全问题,因为都是局部变量。每个线程都只是调用了这个方法,而并没有使用临界变量。 + * @author jrl + * @date Create in 21:43 2023/1/16 + */ +public class LocalVariable implements Runnable { + + @Override + public void run() { + Integer ii = 0; + for (int i = 0; i < 100000; i++) { + ii++; + } + System.out.println(ii);//10000 + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariableMain.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariableMain.java" new file mode 100644 index 00000000..0628bc8d --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariableMain.java" @@ -0,0 +1,22 @@ +package java0.conc0301.jrl.share; + +/** + * 模仿 多线程调用 Spring MVC,其中 Controller 采用了默认的单例模式。 + * 分业务有状态和业务无状态。 + * + * @author jrl + * @date Create in 21:45 2023/1/16 + */ +public class LocalVariableMain { + public static void main(String[] args) { + //无状态 + LocalVariable runnable1 = new LocalVariable(); + new Thread(runnable1).start(); + new Thread(runnable1).start(); + + // 有状态 + GlobalVariable runnable2 = new GlobalVariable(); + new Thread(runnable2).start(); + new Thread(runnable2).start(); + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/Join.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/Join.java" new file mode 100644 index 00000000..b7af9bac --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/Join.java" @@ -0,0 +1,62 @@ +package java0.conc0301.op; + +public class Join { + + public static void main(String[] args) throws InterruptedException { + Object oo = new Object(); + + MyThread thread1 = new MyThread("thread1 -- "); +// oo = thread1; + thread1.setOo(oo); + thread1.start(); + Thread.sleep(1000); + System.out.println("main Lock:" + oo.toString()); + System.out.println("main holds lock----" + Thread.holdsLock(oo)); + /** knowledge point: + * 这里用oo和thread1是不一样的,因为对于join这个方法本身就涉及到了对thread1的锁。 + * 对于wait实践后也不一样,推测和thread1 执行完后就不存在对thread1的锁的这么一个情况 + * */ + synchronized (oo) { // 这里用oo或thread1/this + System.out.println("main inner holds lock----" + Thread.holdsLock(oo)); + for (int i = 0; i < 10; i++) { + if (i == 2) { + try { +// oo.wait(); +// System.out.println("main before join----" + Thread.holdsLock(oo)); + /** knowledge point: 对呀,join是不会释放对象锁的,但是会释放对象为线程的锁,这里就是对thread1的锁会被main释放掉*/ + thread1.join(); +// System.out.println("main after join----" + Thread.holdsLock(oo)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println(Thread.currentThread().getName() + " -- " + i); + } + } + } + +} + +class MyThread extends Thread { + + private String name; + private Object oo; + + public void setOo(Object oo) { + this.oo = oo; + } + + public MyThread(String name) { + this.name = name; + } + + @Override + public void run() { + synchronized (oo) { // 这里用oo或this,效果不同 + for (int i = 0; i < 100; i++) { + System.out.println(name + i); + } + } + } + +} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/WaitAndNotify.java" similarity index 72% rename from 03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/WaitAndNotify.java" index e3956c10..3e17fb29 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/WaitAndNotify.java" @@ -1,5 +1,8 @@ package java0.conc0301.op; +/** + * @author Joly + */ public class WaitAndNotify { public static void main(String[] args) { MethodClass methodClass = new MethodClass(); @@ -19,54 +22,62 @@ public static void main(String[] args) { e.printStackTrace(); } }, "t2"); -// Thread t3 = new Thread(() -> { -// try { -// methodClass.customer(); -// } catch (InterruptedException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// }, "t3"); + Thread t3 = new Thread(() -> { + try { + methodClass.customer(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }, "t3"); t1.start(); t2.start(); - //t3.start(); - + t3.start(); + } } class MethodClass { // 定义生产最大量 private final int MAX_COUNT = 20; - + int productCount = 0; - + + /** + * 每次生产一个产品,仓库容量20 + * + * @param + * @return + * @date 2023/1/1 + */ public synchronized void product() throws InterruptedException { while (true) { System.out.println(Thread.currentThread().getName() + ":::run:::" + productCount); - Thread.sleep(10); + Thread.sleep(100); if (productCount >= MAX_COUNT) { System.out.println("货舱已满,,.不必再生产"); - + wait(); - }else { + } else { productCount++; } - + System.out.println(Thread.currentThread().getName() + "继续"); + notifyAll(); } } - + public synchronized void customer() throws InterruptedException { while (true) { System.out.println(Thread.currentThread().getName() + ":::run:::" + productCount); - Thread.sleep(10); + Thread.sleep(100); if (productCount <= 0) { System.out.println("货舱已无货...无法消费"); wait(); - }else { + } else { productCount--; } - + notifyAll(); } } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Counter.java" similarity index 85% rename from 03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Counter.java" index 848c0900..573fe270 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Counter.java" @@ -1,22 +1,26 @@ package java0.conc0301.sync; public class Counter { - + private int sum = 0; private Object lock = new Object(); public void incr() { - synchronized(lock) { +// synchronized (this){ +// sum = sum + 1; +// } + synchronized (lock){ sum = sum + 1; } } + public int getSum() { return sum; } - + public static void main(String[] args) throws InterruptedException { int loop = 10_0000; - + // test single thread Counter counter = new Counter(); for (int i = 0; i < loop; i++) { @@ -24,8 +28,11 @@ public static void main(String[] args) throws InterruptedException { } System.out.println("single thread: " + counter.getSum()); - + // test multiple threads + /** doubt: + * 这里用不用final有什么区别 + */ final Counter counter2 = new Counter(); Thread t1 = new Thread(() -> { for (int i = 0; i < loop / 2; i++) { @@ -42,7 +49,7 @@ public static void main(String[] args) throws InterruptedException { Thread.sleep(1000); System.out.println("multiple threads: " + counter2.getSum()); - - + + } } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Cref.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Cref.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/sync/Cref.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Cref.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/TestSetGet.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/TestSetGet.java" similarity index 94% rename from 03concurrency/0301/src/main/java/java0/conc0301/sync/TestSetGet.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/TestSetGet.java" index db251617..fc24080d 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/sync/TestSetGet.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/TestSetGet.java" @@ -28,14 +28,14 @@ public static class SetGet { int a = 0; public synchronized void set(int v) throws Exception { System.out.println(Thread.currentThread().getName() +" setting " +v); - Thread.sleep(1000); + // Thread.sleep(1000); a = v; System.out.println(Thread.currentThread().getName() +" set " +v); } public synchronized int get() throws Exception { System.out.println(Thread.currentThread().getName() +" getting "); - Thread.sleep(10000); + // Thread.sleep(10000); System.out.println(Thread.currentThread().getName() + " get "); return a; } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread1.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread1.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/sync/Thread1.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread1.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread2.java" similarity index 82% rename from 03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread2.java" index d0f0638b..f59596bc 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread2.java" @@ -4,19 +4,22 @@ public class Thread2 { public void m4t1() { + synchronized (this) { + System.out.println(this); int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); - try { - Thread.sleep(500); - } catch (InterruptedException ie) { - } +// try { +// Thread.sleep(500); +// } catch (InterruptedException ie) { +// } } } } public synchronized void m4t2() { + System.out.println(this); int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread3.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread3.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/sync/Thread3.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread3.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicCount.java" similarity index 87% rename from 03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicCount.java" index cece1ec3..a06e62ab 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicCount.java" @@ -3,6 +3,10 @@ import java.util.concurrent.atomic.AtomicInteger; +/** + * AtomicInteger + * @author Joly + */ public class AtomicCount { private AtomicInteger num = new AtomicInteger(); diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicMain.java" similarity index 71% rename from 03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicMain.java" index 297eb343..10033c48 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicMain.java" @@ -1,6 +1,11 @@ package java0.conc0302.atomic; +/** + * TODOQQQQQQ + * ʾLock̲߳ȫ + * @author Joly + */ public class AtomicMain { public static void main(String[] args) { @@ -10,7 +15,7 @@ public static void main(String[] args) { @Override public void run() { for (int j = 0; j < 10000; j++) { - count.add(); + count.add(); } } }).start(); @@ -21,7 +26,8 @@ public void run() { } catch (InterruptedException e) { e.printStackTrace(); } - + // TODO_Joly://num=338247 õǹƽòƽĻǶԵ + // ȣҲΪʲôܲԣҲƽզӰ System.out.println("num=" + count.getNum()); } diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/Count.java" similarity index 88% rename from 03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/Count.java" index 02fd13d5..279c2ca9 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/Count.java" @@ -1,6 +1,9 @@ package java0.conc0302.atomic; +/** + * @author Joly + */ public class Count { private int num = 0; diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/LongDemo.java" similarity index 89% rename from 03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/LongDemo.java" index 6a7356c6..4d5865c0 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/LongDemo.java" @@ -3,6 +3,10 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.LongAdder; +/** + * ʾԭ++̰߳ȫ + * @author Joly + */ public class LongDemo { public static void main(String[] args) { @@ -27,7 +31,8 @@ public void run() { } catch (InterruptedException e) { e.printStackTrace(); } - + //atomicLong=1000000 + // longAdder =1000000 System.out.println("atomicLong=" + atomicLong.get()); System.out.println("longAdder =" + longAdder.sum()); diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/SyncCount.java" similarity index 76% rename from 03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/SyncCount.java" index b95c7cff..b000e703 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/SyncCount.java" @@ -4,15 +4,21 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +/** + * ReentrantLock + * num +1ȡֵ + * + * @author Joly + */ public class SyncCount { - + //ҵ private int num = 0; - + // private Lock lock = new ReentrantLock(true); public int add() { + lock.lock(); try { - lock.lock(); return num++; } finally { lock.unlock(); diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo.java" new file mode 100644 index 00000000..6064a419 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo.java" @@ -0,0 +1,88 @@ +package java0.conc0302.lock; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * ReentrantLock + * Condition + * + * @author Joly + */ +public class ConditionDemo { + /** + * @author jrl + * @date 2022/12/26 + */ + final Lock lock = new ReentrantLock(); + + final Condition notFull = lock.newCondition(); + final Condition notEmpty = lock.newCondition(); + + //被操作的数组 + final Object[] items = new Object[20]; + + //数组已有元素的下一个位置,数组已有元素的最后一个位置,数组的已有元素的数量 + int putptr, takeptr, count; + + /** + * 在数组不满的时候,向数组内放置一个元素 + * + * @param + * @return + * @date 2022/12/26 + */ + public void put(Object x) throws InterruptedException { + //手动上锁 + lock.lock(); + try { + System.out.println(Thread.currentThread().getName()+"----------"+x+"开始执行任务"); + // 当count等于数组的大小时,当前线程等待,直到notFull通知,再进行生产 + //也就是说要等到满足了 notFull 这个 Condition 的时候,才开始继续执行 + while (count == items.length) { + System.out.println(Thread.currentThread().getName()+"----------"+x+"进入等待"); + //相当于 wait + notFull.await(); + } + System.out.println(Thread.currentThread().getName()+"----------"+x+"继续执行任务"); + //朝数组放置一个元素 + items[putptr] = x; + if (++putptr == items.length) { + putptr = 0; + } + ++count; + //相当于 notify + notEmpty.signal(); + } finally { + //手动解锁 + lock.unlock(); + } + } + + /** + * 在数组不为空时,从数组中取出一个元素 + * + * @param + * @return + * @date 2022/12/26 + */ + public Object take() throws InterruptedException { + lock.lock(); + try { + // 当count为0,进入等待,直到notEmpty通知,进行消费。 + while (count == 0) { + notEmpty.await(); + } + Object x = items[takeptr]; + if (++takeptr == items.length) { + takeptr = 0; + } + --count; + notFull.signal(); + return x; + } finally { + lock.unlock(); + } + } +} \ No newline at end of file diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo0.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo0.java" new file mode 100644 index 00000000..810b130c --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo0.java" @@ -0,0 +1,34 @@ +package java0.conc0302.lock; + +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author jrl + * @date Create in 12:58 2022/12/26 + */ +public class ConditionDemo0 { + public static void main(String[] args) throws InterruptedException { + ConditionDemo conditionDemo = new ConditionDemo(); + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 50; i++) { + executorService.submit(() -> { + try { + conditionDemo.put(Math.random()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + for (int i = 0; i < 50; i++) { + executorService.submit(() -> { + try { + conditionDemo.take(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count.java" similarity index 74% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/Count.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count.java" index 09197048..42926798 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count.java" @@ -3,10 +3,22 @@ import java.util.concurrent.locks.ReentrantLock; +/** + * ReentrantLock + * + * @author Joly + */ public class Count { final ReentrantLock lock = new ReentrantLock(); + /** + * 就是一个模拟获得锁,执行业务,释放锁的过程。 + * + * @param + * @return + * @date 2022/12/26 + */ public void get() { // final ReentrantLock lock = new ReentrantLock(); try { @@ -20,6 +32,13 @@ public void get() { } } + /** + * 就是一个模拟获得锁,执行业务,释放锁的过程。 + * + * @param + * @return + * @date 2022/12/26 + */ public void put() { // final ReentrantLock lock = new ReentrantLock(); try { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count2.java" similarity index 84% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/Count2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count2.java" index 8cd691d1..f26434fd 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count2.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count2.java" @@ -3,11 +3,20 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; +/** + * ReentrantReadWriteLock:读锁不互斥,写锁互斥 + * 读写 No + * 读读 Yes + * 写读 No + * 写写 No + * @author Joly + */ public class Count2 { private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); public void get() { + //读锁ReadLock rwLock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + " get begin"); @@ -21,6 +30,7 @@ public void get() { } public void put() { + //写锁WriteLock rwLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + " put begin"); diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count3.java" similarity index 63% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count3.java" index f99eaa3e..59ac8172 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count3.java" @@ -1,6 +1,12 @@ package java0.conc0302.lock; +/** + * num++ + * Ļȡ˳ͬ + * + * @author Joly + */ public class Count3 { private byte[] lock1 = new byte[1]; @@ -8,30 +14,52 @@ public class Count3 { public int num = 0; + /** + * num++ + * ʹ֤̰߳ȫ + * + * @param + * @return + * @date 2022/12/25 + */ public void add() { + // lock1 synchronized (lock1) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } + //lock2 synchronized (lock2) { num += 1; } + //ִҵ֮ͷŵһԴ֮ǰ System.out.println(Thread.currentThread().getName() + "_" + num); } } + /** + * num++ + * ʹ֤̰߳ȫ + * + * @param + * @return + * @date 2022/12/25 + */ public void lockMethod() { + //lock2 synchronized (lock2) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } + //lock1 synchronized (lock1) { num += 1; } + //ִҵ֮ͷŵһԴ֮ǰ System.out.println(Thread.currentThread().getName() + "_" + num); } } diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/LockMain.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockMain.java" similarity index 80% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/LockMain.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockMain.java" index e8f203e2..9e00ab43 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/LockMain.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockMain.java" @@ -1,6 +1,11 @@ package java0.conc0302.lock; +/** + * 模拟两个线程获取两个锁资源造成的死锁现象 + * + * @author Joly + */ public class LockMain { public static void main(String[] args) { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockSupportDemo.java" similarity index 66% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockSupportDemo.java" index 18f598f1..e452c345 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockSupportDemo.java" @@ -2,28 +2,44 @@ import java.util.concurrent.locks.LockSupport; +/** + * 没懂 + * LockSupport + * + * @author Joly + */ public class LockSupportDemo { - + //类锁 public static Object u = new Object(); + static ChangeObjectThread t1 = new ChangeObjectThread("t1"); static ChangeObjectThread t2 = new ChangeObjectThread("t2"); - + + /** + * 静态内部类:线程 + * + * @author jrl + * @date 2022/12/26 + */ public static class ChangeObjectThread extends Thread { public ChangeObjectThread(String name) { super(name); } - @Override public void run() { + + @Override + public void run() { synchronized (u) { System.out.println("in " + getName()); LockSupport.park(); + // TODO_Joly:这应该是另一个线程了吧 if (Thread.currentThread().isInterrupted()) { - System.out.println("被中断了"); + System.out.println(getName() + "被中断了"); } - System.out.println("继续执行"); + System.out.println(getName() + "继续执行"); } } } - + public static void main(String[] args) throws InterruptedException { t1.start(); Thread.sleep(1000L); @@ -31,6 +47,7 @@ public static void main(String[] args) throws InterruptedException { Thread.sleep(3000L); t1.interrupt(); LockSupport.unpark(t2); + System.out.println("0000000000000000000000000"); t1.join(); t2.join(); } diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ObjectCache.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ObjectCache.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/ObjectCache.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ObjectCache.java" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README" new file mode 100644 index 00000000..1327467d --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README" @@ -0,0 +1,6 @@ +# ˵ +1. + LockMain.java + Count3.java + ThreadA.java + ThreadB.java \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java" similarity index 70% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java" index d0ff5f98..38b8a7e0 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java" @@ -1,9 +1,16 @@ package java0.conc0302.lock; +/** + * ReentrantLock + * + * @author Joly + */ public class ReentrantLockDemo { public static void main(String[] args) { + // DONE_Joly:这两个线程可以在使用通一把锁的情况下,同时拥有这把锁吗?(可重入锁) + //--->不可以,毕竟是用一把锁。 final Count count = new Count(); for (int i = 0; i < 2; i++) { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java" similarity index 95% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java" index e36e3375..ed4cc639 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java" @@ -1,6 +1,11 @@ package java0.conc0302.lock; +/** + * ReentrantReadWriteLock + * + * @author Joly + */ public class ReentrantReadWriteLockDemo { public static void main(String[] args) { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java" similarity index 81% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java" index 82b4001b..b38e3097 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java" @@ -5,8 +5,14 @@ import java.util.Map; import java.util.concurrent.locks.ReentrantReadWriteLock; +/** + * ReentrantReadWriteLock + * 模拟去缓冲区获取数据,如果获取不到就进行赋值操作的功能 + * @author Joly + */ public class ReentrantReadWriteLockDemo2 { + //充当缓冲区 private final Map map = new HashMap<>(); private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); @@ -22,7 +28,7 @@ public Object readWrite(String key) { rwLock.readLock().unlock(); rwLock.writeLock().lock(); try { - if (value == null) { + if (value == null) {// 因为释放读锁到开启写锁的过程中可能value被赋值了 value = "aaaa"; } } finally { @@ -41,7 +47,7 @@ public Object readWrite(String key) { public static void main(String[] args) { ReentrantReadWriteLockDemo2 demo2 = new ReentrantReadWriteLockDemo2(); - demo2.readWrite("bingfabiancheng"); + demo2.readWrite("并发编程"); } } diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/TestFair.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/TestFair.java" new file mode 100644 index 00000000..922cd093 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/TestFair.java" @@ -0,0 +1,54 @@ +package java0.conc0302.lock; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantLock; + +/** + * 测试ReentrantLock使用公平排序策略与否的性能差异 + * @author Joly + */ +public class TestFair { + //互斥变量 + public static volatile int race = 0; + + //25875 true + //80 false 300倍 + public static ReentrantLock lock = new ReentrantLock(true); // 改成false会好100倍 + + public static void increase() { + lock.lock(); + race++; //变量自增操作 + System.out.println(Thread.currentThread().getName()); + lock.unlock(); + } + + private static final int THREADS_COUNT = 20; + + public static void main(String[] args) { + //获取线程组里的活跃线程数量 + int count = Thread.activeCount(); + long now = System.currentTimeMillis(); + System.out.println(count); + // TODO_Joly:这个原本想拿来干嘛? + AtomicReference sign = new AtomicReference<>(); + Thread[] threads = new Thread[THREADS_COUNT]; //定义20个线程 + for (int i = 0; i < THREADS_COUNT; i++) { + threads[i] = new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 100000; i++) { + increase(); + } + } + }); + threads[i].start(); + } + //等待所有累加线程都结束。 噢!这个方式牛逼! + while (Thread.activeCount() > count) { + Thread.yield();// 哈哈,让一让,我再让一让 + } + System.out.println(count); + System.out.println(lock.getClass().getName() + " ts = " + (System.currentTimeMillis() - now)); + } +} + diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadA.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadA.java" similarity index 71% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadA.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadA.java" index 5bc7d65a..efc5432e 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadA.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadA.java" @@ -1,6 +1,10 @@ package java0.conc0302.lock; +/** + * ThreadA ִ Count3 е add num++ + * @author Joly + */ public class ThreadA extends Thread { private Count3 count3; @@ -8,6 +12,7 @@ public ThreadA(Count3 count3) { this.count3 = count3; } + @Override public void run() { count3.add(); } diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadB.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadB.java" similarity index 70% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadB.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadB.java" index ee6942f1..6f67ccf9 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadB.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadB.java" @@ -1,6 +1,10 @@ package java0.conc0302.lock; +/** + * ThreadA ִ Count3 е lockMethod num++ + * @author Joly + */ public class ThreadB extends Thread { private Count3 count3; @@ -8,6 +12,7 @@ public ThreadB(Count3 count3) { this.count3 = count3; } + @Override public void run() { count3.lockMethod(); } diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/jrl/LockProperties.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/jrl/LockProperties.java" new file mode 100644 index 00000000..798dce59 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/jrl/LockProperties.java" @@ -0,0 +1,38 @@ +package java0.conc0302.lock.jrl; + + +import java.util.concurrent.*; + +/** + * 锁相关的一些属性 + * + * @author jrl + * @date Create in 09:59 2021-10-27 + */ +public class LockProperties { + public static void main(String[] args) { + MyThreadCaller myThreadCaller = new MyThreadCaller(); + Thread myThread = new Thread(myThreadCaller); + myThread.start(); + + } +} + +class MyThreadCaller implements Runnable { + @Override + public void run() { + Object lock = this; + synchronized (lock) { + for (int i = 0; i < 10; i++) { + System.out.println("this is " + i + "th"); + /** knowledge point: 用于检测该线程是否持有指定的锁*/ + System.out.println("Thread.holdsLock( lock )" + Thread.holdsLock(lock)); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } +} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java" similarity index 52% rename from 03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java" index 22240c51..3cf1f01f 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java" @@ -4,19 +4,27 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; +/** + * knowledge point: + * 1.当子线程(异步)抛出异常后会影响主线程吗?--->在同一个try里的代码会被影响,其他的不会 + * 2.Future能够拿到子线程的异常,那么具体都有什么内容呢?--->可以直接catch拿到子线程抛出来的异常 + * 3.子线程异常了以后,在主线程中shutdown子线程,会抛异常吗?--->不会,就正常执行。 + * 甚至子线程当前还有任务正在执行的话,不会强行关闭,而是等执行完了当前任务,再关闭子线程,也就是所谓的优雅停机。 + * @author Joly + */ public class ExceptionDemo { - - public static void main(String[] args) { + + public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(1); - + try { Future future = executorService.submit(() -> { throw new RuntimeException("executorService.submit()"); }); - + //这里是执行不到的,因为在try里,执行到这之前,获取future的时候应该就已经得知有异常了 double b = future.get(); - System.out.println(b); - + System.out.println("main============"+b); + } catch (Exception ex) { System.out.println("catch submit"); ex.printStackTrace(); @@ -31,8 +39,9 @@ public static void main(String[] args) { // ex.printStackTrace(); // } // + Thread.sleep(1000); executorService.shutdown(); System.out.println("Main Thread End!"); } - + } diff --git a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java" similarity index 81% rename from 03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java" index 664b6942..77f85fec 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java" @@ -5,9 +5,16 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +/** + * knowledge point: + * Executors:线程池的工具类 + */ public class ExecutorServiceDemo { public static void main(String[] args) { + /** knowledge point: + * newScheduledThreadPool:支持定时以及周期性执行任务 + * */ ScheduledExecutorService executorService = Executors.newScheduledThreadPool(16); try { String str = executorService.submit(new Callable() { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java" similarity index 79% rename from 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java" index 2137af53..0073a545 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java" @@ -4,6 +4,12 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +/** + * NewCachedThreadPoolһɻ̳߳ء + * ̳߳صĴС˴̣߳ôͻⲿ̣߳60s ִģ + * ʱֻ̳߳߳߳ȫڲϵͳܹ߳ + * @author Joly + */ public class NewCachedThreadPoolDemo { public static void main(String[] args) { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java" similarity index 57% rename from 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java" index 8d4052b2..8312bf58 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java" @@ -4,15 +4,24 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +/** + * NewFixedTreadPool:创建固定大小的线程池。 + * 每次提交一个任务就创建一个线程,直到线程数到达最大线程数。 + * 线程池的大小一旦到达最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新的线程。 + * @author Joly + */ public class NewFixedThreadPoolDemo { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(16); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 20; i++) { final int no = i; executorService.execute(() -> { try { System.out.println("start:" + no); + // DONE_Joly:线程抛异常之后,这个线程会被干掉还是接着接下一个任务? + //---> 被干掉。 + int a = 1/0; Thread.sleep(1000L); System.out.println("end:" + no); } catch (InterruptedException e) { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java" similarity index 69% rename from 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java" index 3a618f0c..fdc139f2 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java" @@ -5,9 +5,15 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +/** + * NewScheduledThreadExecutor: + * 创建一个不限制大小的线程池,此线程池支持定时以及周期性执行任务的需求。 + * + * @author Joly + */ public class NewScheduledThreadExecutorDemo { - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { ScheduledExecutorService executorService = Executors.newScheduledThreadPool(16); @@ -26,8 +32,10 @@ public void run() { } }; // 10s后执行 - executorService.schedule(runnable, 10, TimeUnit.SECONDS); + // executorService.schedule(runnable, 10, TimeUnit.SECONDS); + executorService.scheduleAtFixedRate(runnable, 5, 5, TimeUnit.SECONDS); } + Thread.sleep(1000000); executorService.shutdown(); System.out.println("Main Thread End!"); diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java" new file mode 100644 index 00000000..8a487fbf --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java" @@ -0,0 +1,46 @@ + +package java0.conc0302.threadpool; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * NewSingleThreadExecutor:创建一个单线程的线程池。 + * 这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有的任务。 + * 如果这个线程因为异常结束了,那么会有新的线程来代替它。 + * 此线程池保证所有任务的执行顺序会按照任务的提交顺序来执行。 + * @author Joly + * @date 2022/12/23 + */ +public class NewSingleThreadExecutorDemo { + + public static void main(String[] args) throws InterruptedException { + + ExecutorService executorService = Executors.newSingleThreadExecutor(); + + for (int i = 0; i < 3; i++) { + final int no = i; + Future submit = executorService.submit(() -> { + System.out.println("start:" + no); + try { + Thread.sleep(1000L); + int a = 1/0; + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("end:" + no); + }); + try { + System.out.println(submit.get()); + } catch (ExecutionException e) { + System.out.println("执行异常:"+no); + e.printStackTrace(); + } + } + executorService.shutdown(); + System.out.println("Main Thread End!"); + } + +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/jolyne/ThreadPoolExecutor0.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/jolyne/ThreadPoolExecutor0.java" new file mode 100644 index 00000000..bff7aa04 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/jolyne/ThreadPoolExecutor0.java" @@ -0,0 +1,299 @@ +package java0.conc0302.threadpool.jolyne; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * @author jrl + * @date Create in 14:23 2022/12/22 + */ +public class ThreadPoolExecutor0 { + public static void main(String[] args) { + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5000, TimeUnit.MILLISECONDS, new BlockingDeque() { + @Override + public void addFirst(Runnable runnable) { + + } + + @Override + public void addLast(Runnable runnable) { + + } + + @Override + public boolean offerFirst(Runnable runnable) { + return false; + } + + @Override + public boolean offerLast(Runnable runnable) { + return false; + } + + @Override + public void putFirst(Runnable runnable) throws InterruptedException { + + } + + @Override + public void putLast(Runnable runnable) throws InterruptedException { + + } + + @Override + public boolean offerFirst(Runnable runnable, long timeout, TimeUnit unit) throws InterruptedException { + return false; + } + + @Override + public boolean offerLast(Runnable runnable, long timeout, TimeUnit unit) throws InterruptedException { + return false; + } + + @Override + public Runnable takeFirst() throws InterruptedException { + return null; + } + + @Override + public Runnable takeLast() throws InterruptedException { + return null; + } + + @Override + public Runnable pollFirst(long timeout, TimeUnit unit) throws InterruptedException { + return null; + } + + @Override + public Runnable pollLast(long timeout, TimeUnit unit) throws InterruptedException { + return null; + } + + @Override + public boolean removeFirstOccurrence(Object o) { + return false; + } + + @Override + public boolean removeLastOccurrence(Object o) { + return false; + } + + @Override + public boolean add(Runnable runnable) { + return false; + } + + @Override + public boolean offer(Runnable runnable) { + return false; + } + + @Override + public void put(Runnable runnable) throws InterruptedException { + + } + + @Override + public boolean offer(Runnable runnable, long timeout, TimeUnit unit) throws InterruptedException { + return false; + } + + @Override + public Runnable remove() { + return null; + } + + @Override + public Runnable poll() { + return null; + } + + @Override + public Runnable take() throws InterruptedException { + return null; + } + + @Override + public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException { + return null; + } + + @Override + public Runnable element() { + return null; + } + + @Override + public Runnable peek() { + return null; + } + + @Override + public boolean remove(Object o) { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + @Override + public int size() { + return 0; + } + + @Override + public Iterator iterator() { + return null; + } + + @Override + public void push(Runnable runnable) { + + } + + @Override + public Runnable removeFirst() { + return null; + } + + @Override + public Runnable removeLast() { + return null; + } + + @Override + public Runnable pollFirst() { + return null; + } + + @Override + public Runnable pollLast() { + return null; + } + + @Override + public Runnable getFirst() { + return null; + } + + @Override + public Runnable getLast() { + return null; + } + + @Override + public Runnable peekFirst() { + return null; + } + + @Override + public Runnable peekLast() { + return null; + } + + @Override + public Runnable pop() { + return null; + } + + @Override + public Iterator descendingIterator() { + return null; + } + + @Override + public int remainingCapacity() { + return 0; + } + + @Override + public int drainTo(Collection c) { + return 0; + } + + @Override + public int drainTo(Collection c, int maxElements) { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Object[] toArray() { + return new Object[0]; + } + + @Override + public T[] toArray(T[] a) { + return null; + } + + @Override + public boolean containsAll(Collection c) { + return false; + } + + @Override + public boolean addAll(Collection c) { + return false; + } + + @Override + public boolean removeAll(Collection c) { + return false; + } + + @Override + public boolean retainAll(Collection c) { + return false; + } + + @Override + public void clear() { + + } + }, new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName("pool0" + "thread" + Math.random()); + return thread; + } + }); + Runnable runnable = new Runnable() { + @Override + public void run() { + System.out.println("hello"); + } + }; + threadPoolExecutor.allowCoreThreadTimeOut(true); + threadPoolExecutor.submit(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + threadPoolExecutor.execute(runnable); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/Homework03.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/Homework03.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/Homework03.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/Homework03.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java" similarity index 67% rename from 03concurrency/0301/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java" index 1ec7f12b..f7aed69f 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java" @@ -5,12 +5,13 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; +// TODO_Joly:我没看懂 public class ConcurrentHashMapDemo { - + public static void main(String[] args) { demo1(); } - + public static void demo1() { final Map count = new ConcurrentHashMap<>(); final CountDownLatch endLatch = new CountDownLatch(2); @@ -19,6 +20,7 @@ public static void demo1() { public void run() { AtomicInteger oldValue; for (int i = 0; i < 5; i++) { + // TODO_Joly:ConcurrentHashMap 保证的就是 存取元素的时候是串行的对吧 oldValue = count.get("a"); if (null == oldValue) { AtomicInteger zeroValue = new AtomicInteger(0); @@ -29,12 +31,19 @@ public void run() { } oldValue.incrementAndGet(); } + // TODO_Joly:a 就没被 put 过 + // 因为 a 是全局唯一的,这样就也不需要 put, + // 当场改,当场用。 + // 所以,a 本身需要是线程安全的类型,所以就用了原子类, + // 因为如果 a 不是线程安全的类型的话,改 a 的过程就可能发生多个线程瞎几把动的情况。 + + // 这里的 CountDownLatch 就单纯是个计数器,配合 主线程 中使用 await,来实现线程间的协作 endLatch.countDown(); } }; new Thread(task).start(); new Thread(task).start(); - + try { endLatch.await(); System.out.println(count); @@ -42,5 +51,5 @@ public void run() { e.printStackTrace(); } } - + } diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java" similarity index 76% rename from 03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java" index df60dc64..191c343d 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java" @@ -7,56 +7,56 @@ import java.util.concurrent.CopyOnWriteArrayList; public class CopyOnWriteArrayListDemo { - + public static void main(String[] args) { - + // ArrayList,LinkedList,Vector不安全,运行报错 // why Vector 也不安全 -// List list = new ArrayList(); + // List list = new ArrayList(); // List list = new LinkedList<>(); -// List list = new Vector<>(); - + List list = new Vector<>(); + // 只有CopyOnWriteArrayList 安全,不报错 - List list = new CopyOnWriteArrayList(); - + // List list = new CopyOnWriteArrayList(); + for (int i = 0; i < 10000; i++) { list.add(i); } - + T1 t1 = new T1(list); T2 t2 = new T2(list); t1.start(); t2.start(); - + } - + public static class T1 extends Thread { private List list; - - public T1(List list) - { + + public T1(List list) { this.list = list; } - + public void run() { + // 读 for (Integer i : list) { } } } - + public static class T2 extends Thread { private List list; - - public T2(List list) - { + + public T2(List list) { this.list = list; } - + public void run() { + // 写 for (int i = 0; i < list.size(); i++) { list.remove(i); } } } - + } diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo2.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo2.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/LinkedHashMapDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/LinkedHashMapDemo.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/collection/LinkedHashMapDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/LinkedHashMapDemo.java" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/README.md" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/README.md" new file mode 100644 index 00000000..b91f6750 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/README.md" @@ -0,0 +1,2 @@ +## 内容 +1. 常用的线程安全类型 \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/SyncListDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/SyncListDemo.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/collection/SyncListDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/SyncListDemo.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/TreeMapDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/TreeMapDemo.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/collection/TreeMapDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/TreeMapDemo.java" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Arrays0.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Arrays0.java" new file mode 100644 index 00000000..4c77014f --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Arrays0.java" @@ -0,0 +1,18 @@ +package java0.conc0303.collection.joly; + +import java.util.Arrays; +import java.util.List; + +/** + * @author jrl + * @date Create in 19:35 2023/2/15 + */ +public class Arrays0 { + public static void main(String[] args) { + List asList = Arrays.asList(1, 2, 3); + asList.set(1,1); + // 这里调用的是 AbstractList 里的 add() 方法,也就是说,List 默认实现就是不让加减元素个数 + // 所以这里会 抛异常Exception in thread "main" java.lang.UnsupportedOperationException + asList.add(1); + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Collections0.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Collections0.java" new file mode 100644 index 00000000..a9633b69 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Collections0.java" @@ -0,0 +1,26 @@ +package java0.conc0303.collection.joly; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author jrl + * @date Create in 19:25 2023/2/15 + */ +public class Collections0 { + public static void main(String[] args) { + List arrayList = new ArrayList<>(); + // 等于说对 用户的list进行了一层包装,类似于 AOP + List synchronizedList = Collections.synchronizedList(arrayList); + synchronizedList.add("a"); + + + // 不可以对 集合 进行 crud + List unmodifiableList = Collections.unmodifiableList(arrayList); + // Exception in thread "main" java.lang.UnsupportedOperationException + unmodifiableList.set(1,"a"); + + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/ConcurrentHashMapDemo0.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/ConcurrentHashMapDemo0.java" new file mode 100644 index 00000000..4b64af30 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/ConcurrentHashMapDemo0.java" @@ -0,0 +1,44 @@ +package java0.conc0303.collection.joly; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +public class ConcurrentHashMapDemo0 { + + public static void main(String[] args) { + demo1(); + } + + public static void demo1() { + final Map count = new ConcurrentHashMap<>(); + final CountDownLatch endLatch = new CountDownLatch(2); + Runnable task = new Runnable() { + @Override + public void run() { + Integer oldValue; + for (int i = 0; i < 5; i++) { + oldValue = count.get("a"); + if (null == oldValue) { + // AtomicInteger zeroValue = new AtomicInteger(0); + oldValue = count.putIfAbsent("a", 0); + oldValue = 0; + } + oldValue++; + } + endLatch.countDown(); + } + }; + new Thread(task).start(); + new Thread(task).start(); + + try { + endLatch.await(); + System.out.println(count); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/future/CompletableFutureDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/CompletableFutureDemo.java" similarity index 59% rename from 03concurrency/0301/src/main/java/java0/conc0303/future/CompletableFutureDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/CompletableFutureDemo.java" index c5d1e900..56dd2376 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/future/CompletableFutureDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/CompletableFutureDemo.java" @@ -2,81 +2,95 @@ import java.util.concurrent.CompletableFuture; +/** + * CompletableFuture + * 异步+函数式编程+对多个异步结果进行综合处理 + * @author Joly + */ public class CompletableFutureDemo { - - public static void main(String[] args){ - + + public static void main(String[] args) { + // 1.变换结果 System.out.println("=====>1.变换结果"); - String result1 = CompletableFuture.supplyAsync(()->{return "Hello ";}).thenApplyAsync(v -> v + "world").join(); + String result1 = CompletableFuture.supplyAsync(() -> { + return "Hello "; + }).thenApplyAsync(v -> v + "world").join(); System.out.println(result1); - + // 2.消费 - CompletableFuture.supplyAsync(()->{return "Hello ";}).thenAccept(v -> { System.out.println("=====>2.消费");System.out.println("consumer: " + v);}); - + CompletableFuture.supplyAsync(() -> { + return "Hello "; + }).thenAccept(v -> { + System.out.println("=====>2.消费"); + System.out.println("consumer: " + v); + }); + // 3.组合 System.out.println("=====>3.组合"); - String result3 = CompletableFuture.supplyAsync(()->{ + String result3 = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "Hello"; - }).thenCombine(CompletableFuture.supplyAsync(()->{ + }).thenCombine(CompletableFuture.supplyAsync(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } return "world"; - }),(s1,s2)->{return s1 + " " + s2;}).join(); - System.out.println("thenCombine:"+result3); - + }), (s1, s2) -> { + return s1 + " " + s2; + }).join(); + System.out.println("thenCombine:" + result3); + CompletableFuture.supplyAsync(() -> "Hello, java course.") .thenApply(String::toUpperCase).thenCompose(s -> CompletableFuture.supplyAsync(s::toLowerCase)) - .thenAccept(v -> { System.out.println("thenCompose:"+v);}); - + .thenAccept(v -> { + System.out.println("thenCompose:" + v); + }); + // 4.竞争 System.out.println("=====>4.竞争"); - String result4 = CompletableFuture.supplyAsync(()->{ + String result4 = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } return "Hi Boy"; - }).applyToEither(CompletableFuture.supplyAsync(()->{ + }).applyToEither(CompletableFuture.supplyAsync(() -> { try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } return "Hi Girl"; - }),(s)->{return s;}).join(); + }), (s) -> { + return s; + }).join(); System.out.println(result4); - + // 5.补偿异常 System.out.println("=====>5.补偿异常"); - String result5 = CompletableFuture.supplyAsync(()->{ + String result5 = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } - if(true) { + if (true) { throw new RuntimeException("exception test!"); } - return "Hi Boy"; - }).exceptionally(e->{ // Fluent API + }).exceptionally(e -> { // Fluent API System.out.println(e.getMessage()); return "Hello world!"; }).join(); System.out.println(result5); - - - } - + } diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureDemo1.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureDemo1.java" new file mode 100644 index 00000000..9e16a8fe --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureDemo1.java" @@ -0,0 +1,47 @@ +package java0.conc0303.future; + +import java.util.Random; +import java.util.concurrent.*; + +/** + * Future˳̵߳쳣 + * 첽ָͬͨģʽ߳A߳Bȥɻ߳AǷҪԵ߳BɻĽ + * ˵̵߳״̬ǷCPUԴ + * + * @author Joly + */ +public class FutureDemo1 { + public static void main(String[] args) { + ExecutorService executor = Executors.newCachedThreadPool(); + executor.submit(() -> { + // Runnable쳣û + int a = 1 / 0; + }); + System.out.println("main1"); + //첽ǻһ߳BȥɻȻǰ߳Aִ, + //߳Bִ֮xὫ͸A̡߳ + Future result = executor.submit(new Callable() { + @Override + public Integer call() throws Exception { + // Callable쳣˱̣߳˸߳.Ӱ츸̵ִ߳ + //DZ Future#get ŻʵǸ߳쳣Ȼ˳չʾ̵߳쳣 + int a = 1 / 0; + Thread.sleep(10000); + return new Random().nextInt(); + } + }); + System.out.println("main2"); + executor.shutdown(); + try { + //˵ʱпòİ + //Java̳߳ʵˣִ̻߳߳꣡ + //һõõֵ + //һҪȥ Future#get Ż߳쳣getĻҲԼ쳣ԼģӰ츸̡߳ + System.out.println("result:" + result.get()); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0303/future/FutureTask1.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureTask1.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/future/FutureTask1.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureTask1.java" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/jolyne/Future0.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/jolyne/Future0.java" new file mode 100644 index 00000000..4f9446be --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/jolyne/Future0.java" @@ -0,0 +1,24 @@ +package java0.conc0303.future.jolyne; + +import java.util.concurrent.*; + +/** + * @author jrl + * @date Create in 19:03 2022/12/22 + */ +public class Future0 { + public static void main(String[] args) throws ExecutionException, InterruptedException { + ExecutorService pool = Executors.newCachedThreadPool(); + Future submit = pool.submit(new Callable() { + + @Override + public String call() throws Exception { + return "hello"; + } + }); + System.out.println(submit.get()); + pool.shutdown(); + System.out.println(pool.isShutdown()); + boolean b = pool.awaitTermination(1000, TimeUnit.MILLISECONDS); + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/stream/StreamParallelDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/stream/StreamParallelDemo.java" similarity index 50% rename from 03concurrency/0301/src/main/java/java0/conc0303/stream/StreamParallelDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/stream/StreamParallelDemo.java" index aaf9567d..4c66e9ee 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/stream/StreamParallelDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/stream/StreamParallelDemo.java" @@ -7,11 +7,18 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +/** + * knowledge point: stream 可以支持并发,使用 parallel()即可,底层是 Java 默默实现了的。 + */ public class StreamParallelDemo { public static void main(String[] args) { List list = new ArrayList<>(); IntStream.range(1, 10000).forEach(i -> list.add(i)); + // TODO_Joly:BlockingQueue 什么特点? + // ---> BlockingQueue blockingQueue = new LinkedBlockingQueue(10000); + // DONE_Joly:Returns an equivalent stream that is parallel。什么意思? + // ---> 意思就是,接下来的操作是利用了线程池实现了并发操作。默认会采用 CPU核心数 * 2 个线程数。 List longList = list.stream().parallel() .map(i -> i.longValue()) .sorted() @@ -19,16 +26,19 @@ public static void main(String[] args) { // // 串行,单线程 // longList.stream().forEach( // 并行,默认使用CPU * 2个线程 - longList.stream().forEach( + longList.stream().parallel().forEach( i -> { - try { - blockingQueue.put(i); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }); + try { + // blockingQueue 线程安全 + blockingQueue.put(i); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + List collect = blockingQueue.stream().sorted().collect(Collectors.toList()); System.out.println("blockingQueue:" + blockingQueue.toString()); + System.out.println("collect:" + collect.toString()); } - - + + } diff --git a/03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java" similarity index 67% rename from 03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java" index bbfe35e0..576093c5 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java" @@ -1,47 +1,59 @@ package java0.conc0303.threadlocal; +/** + * knowledge point: + * ThreadLocal: + * 1. ķǩʵ־Ĭ + */ public class ThreadLocalDemo { - + // knowledge use:ʹ ThreadLocal 洢 Integer ͵ seqNum + // кţ0ʼ+1 private static ThreadLocal seqNum = new ThreadLocal() { + // Ĭֵ public Integer initialValue() { return 0; } }; - + public ThreadLocal getThreadLocal() { return seqNum; } - + + //ȥ ThreadLocal public int getNextNum() { seqNum.set(seqNum.get() + 1); return seqNum.get(); } - - + + public static void main(String[] args) { ThreadLocalDemo threadLocalMain = new ThreadLocalDemo(); - + SnThread client1 = new SnThread(threadLocalMain); SnThread client2 = new SnThread(threadLocalMain); SnThread client3 = new SnThread(threadLocalMain); - + client1.start(); client2.start(); client3.start(); } - - + + private static class SnThread extends Thread { private ThreadLocalDemo sn; - + public SnThread(ThreadLocalDemo sn) { this.sn = sn; } - + + @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("thread[" + Thread.currentThread().getName() + "] ---> sn [" + sn.getNextNum() + "]"); } + // DONE_Joly:ΪʲôҪΪʲôҪӵǰ߳µ ThreadLocalMap Ƴ key Ϊ ThreadLocal ļֵ + //--->Ϊ˱ڴй©Ϊ ThreadLocalMap Entry value һֱڱõģֻҪֹ̲߳value + // Ͳᱻ GCͻڴй©ڴ sn.getThreadLocal().remove(); } } diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/jolyne/ThreadLocal0.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/jolyne/ThreadLocal0.java" new file mode 100644 index 00000000..83d096f5 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/jolyne/ThreadLocal0.java" @@ -0,0 +1,42 @@ +package java0.conc0303.threadlocal.jolyne; + +import java.util.HashMap; +import java.util.Map; + +/** + * 每一个 ThreadLocal 实例 都是一个 key-value, + * key 默认强制设置为 ThreadLocal,value 设置为 用户值。 + * + * 每个 thread 实例中的 threadLocals 里面可以放置多个 threadLocal。 + * + * @author jrl + * @date Create in 14:43 2022/12/20 + */ +public class ThreadLocal0 { + static ThreadLocal tls = new ThreadLocal<>(); + static ThreadLocal> tlm = new ThreadLocal<>(); + + public static void main(String[] args) { + ThreadDemo threadDemo1 = new ThreadDemo(); + ThreadDemo threadDemo2 = new ThreadDemo(); + ThreadDemo threadDemo3 = new ThreadDemo(); + threadDemo1.start(); + threadDemo2.start(); + threadDemo3.start(); + } + + static class ThreadDemo extends Thread { + @Override + public void run() { + super.run(); + System.out.println("run run run--->" + Thread.currentThread().getName()); + tls.set(Thread.currentThread().getName()); + System.out.println(tls.get()); + Map map = new HashMap<>(); + map.put("threadName", currentThread().getName()); + tlm.set(map); + Map map1 = tlm.get(); + System.out.printf(map1.toString()); + } + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java" new file mode 100644 index 00000000..0f22cddc --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java" @@ -0,0 +1,59 @@ +package java0.conc0303.tool; + +import java.util.concurrent.CountDownLatch; + +/** + * I said 123, you shot just count down ! + * CountDownLatch(闭锁)可以看作一个只能做减法的计数器,可以让一个或多个线程等待执行。 + * 场景: Master 线程等待 Worker 线程把任务执行完 + * 示例: + * 等所有人干完手上的活,包工头宣布下班休息。 + * 吃酒席: 大家围成一桌, 等剩下的座位数归0, 服务员才上菜 + *

+ * 特点: + * 1、采用减法计数, + * 2、各个子线程内countdown, + * 3、调用线程/主线程里await,作为聚合点,一直到计数为0 + * + * @author Joly + */ +public class CountDownLatchDemo { + public static void main(String[] args) throws InterruptedException { + // DONE_Joly:我没懂,我以为只会被执行5次任务的,结果应该是执行了50次....那CountDownLatch拿来有什么用? + //---> 是为了让主线程等待子线程某个可被计算的量之后继续执行 + CountDownLatch countDownLatch = new CountDownLatch(5); + for (int i = 0; i < 50; i++) { + new Thread(new ReadNum(i, countDownLatch)).start(); + } + //主线程等着 CountDownLatch 减到0,才继续执行 + countDownLatch.await(); // 注意跟CyclicBarrier不同,这里在主线程await + System.out.println("==>各个子线程执行结束。。。。"); + System.out.println("==>主线程执行结束。。。。"); + } + + /** + * 任务 + * + * @author jrl + * @date 2023/1/1 + */ + static class ReadNum implements Runnable { + private int id; + private CountDownLatch latch; + + public ReadNum(int id, CountDownLatch latch) { + this.id = id; + this.latch = latch; + } + + @Override + public void run() { + // latch.countDown(); + synchronized (this) { + System.out.println("id:" + id + "," + Thread.currentThread().getName()); + System.out.println("线程组任务" + id + "结束,其他任务继续"); + latch.countDown(); + } + } + } +} \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java" similarity index 71% rename from 03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java" index 62a1007a..377e720b 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java" @@ -5,17 +5,23 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +/** + * @author Joly + */ public class CountDownLatchDemo2 { - + private final static int threadCount = 200; - + public static void main(String[] args) throws Exception { - + //os:哟,我是超级执行器! ExecutorService exec = Executors.newCachedThreadPool(); - + // DONE_Joly:为什么总是把 CountDownLatch 的 count 和 线程数或者任务数 设置的一样? + //---> 这里是想要等所有的任务都执行完了之后,主线程再继续执行 final CountDownLatch countDownLatch = new CountDownLatch(threadCount); - + + //执行 threadCount 个任务 for (int i = 0; i < threadCount; i++) { + // TODO_Joly:final? final int threadNum = i; exec.execute(() -> { try { @@ -28,11 +34,13 @@ public static void main(String[] args) throws Exception { } }); } + // DONE_Joly:难道 CuntDownLatch 只是拿来等待任务执行完成的吗 + //--->是的 countDownLatch.await(); System.out.println("==>所有程序员完成任务,项目顺利上线!"); - //exec.shutdown(); + exec.shutdown(); } - + private static void test(int threadNum) throws Exception { Thread.sleep(100); System.out.println(String.format("程序员[%d]完成任务。。。", threadNum)); diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java" similarity index 51% rename from 03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java" index 628d980d..b0291b46 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java" @@ -2,44 +2,69 @@ import java.util.concurrent.CyclicBarrier; +/** + * CyclicBarrier:可以让一组线程等待满足某个条件后同时执行。 + * CyclicBarrier 默认的构造方法是 CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线 + * 程调用 await() 方法告诉 CyclicBarrier 我已经到达了屏障,然后当前线程被阻塞,直到 parties 个线程 + * 到达,结束阻塞。 + * 使用场景: 任务执行到一定阶段, 等待其他任务对齐 + * + * 2. 其实用 wait/notify 或者 condition 或者 信号量 都是可以实现的,所以这个就是工具类 + * @author jrl + * @date 2023/1/1 + */ public class CyclicBarrierDemo { public static void main(String[] args) throws InterruptedException { CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() { + // 这是回调之后要执行的内容 + //只有一个子线程会执行回调内容 @Override public void run() { - System.out.println("回调>>"+Thread.currentThread().getName()); + System.out.println("回调>>" + Thread.currentThread().getName()); System.out.println("回调>>线程组执行结束"); System.out.println("==>各个子线程执行结束。。。。"); } }); for (int i = 0; i < 5; i++) { - new Thread(new readNum(i,cyclicBarrier)).start(); + new Thread(new ReadNum(i, cyclicBarrier)).start(); } - - // ==>>> - - + + // ==>>> + + System.out.println("==>主线程执行结束。。。。"); - + //CyclicBarrier 可以重复利用, // 这个是CountDownLatch做不到的 // for (int i = 11; i < 16; i++) { // new Thread(new readNum(i,cyclicBarrier)).start(); // } } - static class readNum implements Runnable{ + + /** + * 任务 + * + * @author jrl + * @date 2023/1/1 + */ + static class ReadNum implements Runnable { private int id; private CyclicBarrier cyc; - public readNum(int id,CyclicBarrier cyc){ + + public ReadNum(int id, CyclicBarrier cyc) { this.id = id; this.cyc = cyc; } + @Override public void run() { - synchronized (this){ - System.out.println("id:"+id+","+Thread.currentThread().getName()); + synchronized (this) { + System.out.println("id:" + id + "," + Thread.currentThread().getName()); try { + // DONE_Joly:这在等什么 + //---> 这是在回调 cyc.await(); + //所有线程过了屏障之后都会接着执行 System.out.println("线程组任务" + id + "结束,其他任务继续"); //cyc.await(); // 注意跟CountDownLatch不同,这里在子线程await } catch (Exception e) { diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java" similarity index 57% rename from 03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java" index 33e88260..a7aaacb2 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java" @@ -3,47 +3,57 @@ import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; +/** + * CyclicBarrier 重用 + * + * @author Joly + */ public class CyclicBarrierDemo2 { public static void main(String[] args) { int N = 4; - CyclicBarrier barrier = new CyclicBarrier(N); - - for(int i=0;i CyclicBarrier重用"); - - for(int i=0;i { + try { + // DONE_Joly:permits是什么 + //---> 是锁定的资源允许同时访问的x量,在创建的时候指定。 + //在使用时(acquire方法)说明一个线程要使用几个x + //换言之,x是一个计量数,并不代表有几个线程,完全看 初始量/单次使用量 + semaphore.acquire(3); // 获取超出一半的许可,退化成串行执行 + test(threadNum); + semaphore.release(3); // 释放多个许可 + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + exec.shutdown(); + } + + /** + * 输出指定的线程id以及其对应的线程名称 + * + * @param threadNum 线程id + * @date 2022/12/28 + */ + private static void test(int threadNum) throws Exception { + System.out.println("id:" + threadNum + "," + Thread.currentThread().getName()); + Thread.sleep(1000); + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java" similarity index 82% rename from 03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java" index 3a02dc78..a4b0ad96 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java" @@ -3,16 +3,27 @@ import java.util.concurrent.Semaphore; +/** + * Semaphore + * 我感觉这个例子在模仿 synchronized 和 wait notify + * + * @author jrl + * @date 2022/12/28 + */ public class SemaphoreDemo3 { public static void main(String[] args) { // 启动线程 + for (int i = 0; i < 10; i++) { + // 消费者 + new Thread(new Consumer()).start(); + } for (int i = 0; i <= 10; i++) { // 生产者 new Thread(new Producer()).start(); - // 消费者 - new Thread(new Consumer()).start(); + } + } @@ -25,7 +36,11 @@ static class Producer implements Runnable { @Override public void run() { + // DONE_Joly:++操作为什么没有发生线程不安全? int n = num++; + // ---> 哈哈哈,用 num + 1 就会线程不安全。 + // 看来,num++ 是个原语操作。 + // int n = num + 1; while (true) { try { buffer.put(n); @@ -61,15 +76,16 @@ static class Warehouse { final Semaphore notFull = new Semaphore(10); // 非空锁 final Semaphore notEmpty = new Semaphore(0); - // 核心锁 + // 核心锁 (实现了临界资源的互斥性) final Semaphore mutex = new Semaphore(1); - // 库存容量 + // 库存容量,每个商品就是个数字 final Object[] items = new Object[10]; + int putptr, takeptr, count; /** - * 放库存 + * 放库存(最终的执行一定是先放库存,因为notEmpty初始量是0) * * @param obj * @throws InterruptedException diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/README.md" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/README.md" new file mode 100644 index 00000000..d3518e38 --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/README.md" @@ -0,0 +1,3 @@ +# 代码来源 +* 极客时间-Java并发编程实战 + diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/pom.xml" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/pom.xml" new file mode 100644 index 00000000..94c90b61 --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/pom.xml" @@ -0,0 +1,66 @@ + + + + 4.0.0 + + org.example + Java并发编程实战 + 1.0-SNAPSHOT + war + + Java并发编程实战 Maven Webapp + + + + UTF-8 + 8 + 8 + + + + + junit + junit + 4.11 + test + + + + + Java并发编程实战 + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-war-plugin + 3.2.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + + diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/interview/MultiThread.java" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/interview/MultiThread.java" new file mode 100644 index 00000000..4905b646 --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/interview/MultiThread.java" @@ -0,0 +1,31 @@ +package top.jrl.concurrency.interview; + +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; + +/** + * https://javaguide.cn/java/concurrent/java-concurrent-questions-01.html#%E4%BD%95%E4%B8%BA%E7%BA%BF%E7%A8%8B + * 通过 JMX 来看一下一个普通的 Java 程序有哪些线程 + * @author jrl + * @date Create in 15:16 2022/5/22 + */ +public class MultiThread { + public static void main(String[] args) { + // 获取 Java 线程管理 MXBean + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + // 不需要获取同步的 monitor 和 synchronizer 信息,仅获取线程和线程堆栈信息 + ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); + // 遍历线程信息,仅打印线程 ID 和线程名称信息 + for (ThreadInfo threadInfo : threadInfos) { + System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName()); + } + // [6] Monitor Ctrl-Break + // [5] Attach Listener //添加事件 + // [4] Signal Dispatcher // 分发处理给 JVM 信号的线程 + // [3] Finalizer //调用对象 finalize 方法的线程 + // [2] Reference Handler //清除 reference 线程 + // [1] main //main 线程,程序入口 + } +} + diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part1/Calc.java" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part1/Calc.java" new file mode 100644 index 00000000..be73594c --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part1/Calc.java" @@ -0,0 +1,41 @@ +package top.jrl.concurrency.part1; + +/** + * @author jrl + * @date Create in 14:46 2022/5/2 + */ +public class Calc { + + private static long count = 0; + + private synchronized void add10K() { + int idx = 0; + while (idx++ < 10000) { + count += 1; + } + } + + public static long calc() throws InterruptedException { + final Calc calc = new Calc(); + // 创建两个线程,执行add()操作 + Thread th1 = new Thread(() -> { + calc.add10K(); + }); + Thread th2 = new Thread(() -> { + calc.add10K(); + }); + + // 启动两个线程 + th1.start(); + th2.start(); + // 等待两个线程执行结束 + th1.join(); + th2.join(); + return count; + } + + public static void main(String[] args) throws InterruptedException { + long calcCount = calc(); + System.out.println(calcCount); + } +} diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Abc3.java" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Abc3.java" new file mode 100644 index 00000000..cc1dbcc7 --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Abc3.java" @@ -0,0 +1,59 @@ +package top.jrl.concurrency.part2; + +/** + * Happens-Before + * + * @author jrl + * @date Create in 17:35 2022/5/13 + */ +public class Abc3 { + static int abc2; + static volatile int v = 1; + + public static void main(String[] args) throws InterruptedException { + Abc3 abc3 = new Abc3(); + // abc3.one(); + // abc3.two(); + Thread b3 = new Thread(new Runnable() { + @Override + public void run() { + abc2 = 123; + v = 2; + } + }); + Thread b33 = new Thread(new Runnable() { + @Override + public void run() { + if (v == 2) { + System.out.println(abc2); + } + } + }); + b33.start(); + b3.start(); + } + + + private void two() throws InterruptedException { + Thread b = new Thread(new Runnable() { + @Override + public void run() { + abc2 = 123; + } + }); + b.start(); + b.join(); + System.out.println(abc2); + } + + private void one() { + int abc = 123; + new Thread(new Runnable() { + @Override + public void run() { + // 这拿到的居然是同一个abc + System.out.println(abc); + } + }).start(); + } +} diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/BlockedQueue.java" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/BlockedQueue.java" new file mode 100644 index 00000000..40dd2e40 --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/BlockedQueue.java" @@ -0,0 +1,55 @@ +package top.jrl.concurrency.part2; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author jrl + * @date Create in 16:31 2022/5/29 + */ + +public class BlockedQueue { + static Integer a = 1; + static Integer b = 2; + static Integer lock = 3; + public static void main(String[] args) { + new Thread(()->{ + synchronized (lock){ + while(a==1){ + try { + lock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + while(b==2){ + try { + b.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }).start(); + new Thread(()->{ + synchronized (lock){ + while(a==1){ + try { + lock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + while(b==2){ + try { + // 这是错的,只能是lock来做条件变量 + b.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }).start(); + } +} diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Integer1.java" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Integer1.java" new file mode 100644 index 00000000..cd02bfcb --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Integer1.java" @@ -0,0 +1,16 @@ +package top.jrl.concurrency.part2; + +/** + * 因为balance为integer对象,当值被修改相当于换锁, + * TODO 还有integer有缓存-128到127,相当于同一个对象。 + * + * @author jrl + * @date Create in 11:38 2022/5/15 + */ +public class Integer1 { + public static void main(String[] args) { + Integer a = 1; + Integer b = 2; + System.out.println(a == b); // false + } +} diff --git "a/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Vector1.java" "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Vector1.java" new file mode 100644 index 00000000..d0b3a214 --- /dev/null +++ "b/03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/src/main/java/top/jrl/concurrency/part2/Vector1.java" @@ -0,0 +1,37 @@ +package top.jrl.concurrency.part2; + +import java.util.Vector; + +/** + * @author jrl + * @date Create in 14:30 2022/5/20 + */ +public class Vector1 { + static Vector v = new Vector(); + static Object o = 1; + + public static void main(String[] args) throws InterruptedException { + Thread t1 = new Thread(() -> { + for (int i = 0; i < 10000; i++) { + // if (!v.contains(o)){ + v.add(o); + // } + + } + System.out.println(v.size()); + }); + Thread t2 = new Thread(() -> { + for (int i = 0; i < 10000; i++) { + if (!v.contains(o)) { + v.add(o); + } + } + System.out.println(v.size()); + }); + t1.start(); + t2.start(); + t1.join(); + t2.join(); + System.out.println(v.size()); + } +} diff --git a/03concurrency/README2.md b/03concurrency/README2.md new file mode 100644 index 00000000..e0cf9399 --- /dev/null +++ b/03concurrency/README2.md @@ -0,0 +1,12 @@ +Week04 作业 + +1.(选做)把示例代码,运行一遍,思考课上相关的问题。也可以做一些比较。 + +2.(必做)思考有多少种方式,在 main 函数启动一个新线程,运行一个方法,拿到这 +个方法的返回值后,退出主线程? 写出你的方法,越多越好,提交到 GitHub。 +一个简单的代码参考: https://github.com/kimmking/JavaCourseCodes/tree/main/03concurrency/0301 /src/main/java/java0/conc0303/Homework03.java + +3.(选做)列举常用的并发操作 API 和工具类,简单分析其使用场景和优缺点。 +4.(选做)请思考: 什么是并发? 什么是高并发? 实现高并发高可用系统需要考虑哪些 因素,对于这些你是怎么理解的? +5.(选做)请思考: 还有哪些跟并发类似 / 有关的场景和问题,有哪些可以借鉴的解决 办法。 +6.(必做)把多线程和并发相关知识梳理一遍,画一个脑图,截图上传到 GitHub 上。 可选工具:xmind,百度脑图,wps,MindManage,或其他。 \ No newline at end of file diff --git a/03concurrency/README3.md b/03concurrency/README3.md new file mode 100644 index 00000000..153388fb --- /dev/null +++ b/03concurrency/README3.md @@ -0,0 +1,3 @@ +# 信息来源 +* 极客时间-Java进阶训练营 +* 极客时间-Java并发实战 \ No newline at end of file diff --git a/04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambda8.java b/04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambda8.java new file mode 100644 index 00000000..20aeb8af --- /dev/null +++ b/04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambda8.java @@ -0,0 +1,20 @@ +package lambdasinaction.jrl; + +/** + * MyLambdaInterface + * java8 处理lambda表达式 + * + * @author jrl + * @date 2022/1/30 + */ +public class MyLambda8 { + public static void main(String[] args) { + /** knowledge point: + * 相当于实现了一个匿名内部类 + * (但之所以用匿名内部类,其实是因为想要实现匿名函数, + * 可是java里不可能有脱离类的函数,所以就用了匿名内部类) + */ + MyLambdaInterface myLambdaInterfaceImpl = s -> System.out.println(s); + myLambdaInterfaceImpl.doSomeShit("you"); + } +} diff --git a/04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambdaInterface.java b/04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambdaInterface.java new file mode 100644 index 00000000..10e0e17f --- /dev/null +++ b/04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambdaInterface.java @@ -0,0 +1,16 @@ +package lambdasinaction.jrl; + +/** + * @author jrl + * @date 2022/1/30 + */ +public interface MyLambdaInterface { + /** + * 用来对比java7和java8怎么实现接口的抽象方法 + * + * @author jrl + * @date 2022/1/30 + * @param s 待输出值 + */ + void doSomeShit(String s); +} diff --git a/04fx/XML/pom.xml b/04fx/XML/pom.xml new file mode 100644 index 00000000..a6bc4b6c --- /dev/null +++ b/04fx/XML/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + org.example + XML + 1.0-SNAPSHOT + + + + org.dom4j + dom4j + 2.1.1 + + + + jaxen + jaxen + 1.1.6 + + + + + \ No newline at end of file diff --git a/04fx/XML/src/main/java/src/com/woniuxy/basic/xml/SAXReaderLearn.java b/04fx/XML/src/main/java/src/com/woniuxy/basic/xml/SAXReaderLearn.java new file mode 100644 index 00000000..35862489 --- /dev/null +++ b/04fx/XML/src/main/java/src/com/woniuxy/basic/xml/SAXReaderLearn.java @@ -0,0 +1,71 @@ +package src.com.woniuxy.basic.xml; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.io.SAXReader; + +import java.io.File; + +/** + * 读取xml文件学习 + * + * @author 小虫子的小日常 + * + */ +public class SAXReaderLearn { + public static void main(String[] args) { + /* + * 1.获取SAXReader对象,通过该对象加载xml文件(通过获得Document对象) + */ + SAXReader reader = new SAXReader(); + try { + Document document = reader.read(new File("D:\\ITLearn\\IdeaProject\\xunlianying_jinjie\\JavaCourseCodes\\04fx\\XML\\src\\main\\resources\\jdbc.xml")); + + /* + * 2.读取xml文件内容:方式一:原始版,不用XPath,挨着去找需要的内容 + */ + // // 获取根元素 + // Element root = document.getRootElement(); + // + // // 判断就是否有根元素以此来判定该XML文件是否为空 + // if (root != null) {// 如果root存在,则说明XML文件不为空 + // + // // 获取元素 + // List namedEles = root.elements(); + // for (Element nameEle : namedEles) { + // if (nameEle.attributeValue("name").equals("myjdbc")) { + // List propertyEles = nameEle.elements(); + // for (Element propertyEle : propertyEles) { + // if (propertyEle.attributeValue("name").equals("driverClass")) { + // System.out.println("driverClass:" + propertyEle.getText()); + // } else if (propertyEle.attributeValue("name").equals("jdbcUrl")) + // { + // System.out.println("jdbcUrl:" + propertyEle.getText()); + // } else if (propertyEle.attributeValue("name").equals("user")) { + // System.out.println("user:" + propertyEle.getText()); + // } else if (propertyEle.attributeValue("name").equals("password")) + // { + // System.out.println("password:" + propertyEle.getText()); + // } + // + // } + // } + // } + // } + + /* + * 2.读取xml文件内容:方式二:XPath版,导jaxen.jar,利用给的路径去找 + */ + // 用绝对路径(/开头,代表从 根节点开始) + String driverClass = document + .selectSingleNode("/jdbc-config/named-config[@name='myjdbc']/property[@name='driverClass']") + .getText(); + System.out.println(driverClass); + // 用相对路径(//开头,代表从任意节点开始) + String driverClass2 = document.selectSingleNode("//property[@name='driverClass']").getText(); + System.out.println(driverClass2); + } catch (DocumentException e) { + e.printStackTrace(); + } + } +} diff --git a/04fx/XML/src/main/java/src/com/woniuxy/basic/xml/XMLWriterLearn.java b/04fx/XML/src/main/java/src/com/woniuxy/basic/xml/XMLWriterLearn.java new file mode 100644 index 00000000..468b4014 --- /dev/null +++ b/04fx/XML/src/main/java/src/com/woniuxy/basic/xml/XMLWriterLearn.java @@ -0,0 +1,65 @@ +package src.com.woniuxy.basic.xml; + +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * XML写出配置文件 + * + * @author 小虫子的小日常 + * + */ +public class XMLWriterLearn { + public static void main(String[] args) { + /* + * 1.编写配置文件的DOM(Document Object Model 文档对象模型)树内容 + */ + // 获取Document对象 + Document document = DocumentHelper.createDocument(); + // 添加Element、Attribute(包括属性名和属性值)、文本内容 + Element school = document.addElement("school"); + school.addAttribute("name", "SWUN"); + school.setText("小可爱的学校"); + Element major = school.addElement("major"); + major.addAttribute("name", "IOT"); + Element myClass = major.addElement("class"); + myClass.addAttribute("name", "1401"); + myClass.setText("可爱的班级"); + /* + * 2.设置格式 + */ + // 获取OutputFormat对象 + OutputFormat format = OutputFormat.createPrettyPrint(); + // 利用输出格式对象设置XML的编码格式 + format.setEncoding("utf-8"); + /* + * 3.获取输出流,将内容写到本地 + */ + // 获取输出流 + XMLWriter writer = null; + try { + writer = new XMLWriter(new FileWriter(new File("D:\\ITLearn\\IdeaProject\\xunlianying_jinjie\\JavaCourseCodes\\04fx\\XML\\src\\main\\resources\\swun.xml")),format); + // 将内容写出 + writer.write(document); + } catch (IOException e) { + e.printStackTrace(); + } finally { + // 关闭流 + try { + if (writer != null) { + writer.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/04fx/XML/src/main/resources/jdbc.xml b/04fx/XML/src/main/resources/jdbc.xml new file mode 100644 index 00000000..9a770c74 --- /dev/null +++ b/04fx/XML/src/main/resources/jdbc.xml @@ -0,0 +1,15 @@ + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/woniushops + root + 123456 + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/woniushops + root + 123456 + + \ No newline at end of file diff --git a/04fx/XML/src/main/resources/swun.xml b/04fx/XML/src/main/resources/swun.xml new file mode 100644 index 00000000..905d88f4 --- /dev/null +++ b/04fx/XML/src/main/resources/swun.xml @@ -0,0 +1,7 @@ + + +小可爱的学校 + + 可爱的班级 + + diff --git a/app/.gitignore b/04fx/app/.gitignore similarity index 100% rename from app/.gitignore rename to 04fx/app/.gitignore diff --git a/09mq/rocket/.mvn/wrapper/MavenWrapperDownloader.java b/04fx/app/.mvn/wrapper/MavenWrapperDownloader.java similarity index 100% rename from 09mq/rocket/.mvn/wrapper/MavenWrapperDownloader.java rename to 04fx/app/.mvn/wrapper/MavenWrapperDownloader.java diff --git a/09mq/rocket/.mvn/wrapper/maven-wrapper.jar b/04fx/app/.mvn/wrapper/maven-wrapper.jar similarity index 100% rename from 09mq/rocket/.mvn/wrapper/maven-wrapper.jar rename to 04fx/app/.mvn/wrapper/maven-wrapper.jar diff --git a/09mq/rocket/.mvn/wrapper/maven-wrapper.properties b/04fx/app/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from 09mq/rocket/.mvn/wrapper/maven-wrapper.properties rename to 04fx/app/.mvn/wrapper/maven-wrapper.properties diff --git a/04fx/app/README.md b/04fx/app/README.md new file mode 100644 index 00000000..df337e4e --- /dev/null +++ b/04fx/app/README.md @@ -0,0 +1,4 @@ +## ʾ Spring Boot Զ +*ԶãǾһstarter* + + diff --git a/09mq/rocket/mvnw b/04fx/app/mvnw old mode 100755 new mode 100644 similarity index 100% rename from 09mq/rocket/mvnw rename to 04fx/app/mvnw diff --git a/09mq/rocket/mvnw.cmd b/04fx/app/mvnw.cmd similarity index 100% rename from 09mq/rocket/mvnw.cmd rename to 04fx/app/mvnw.cmd diff --git a/app/pom.xml b/04fx/app/pom.xml similarity index 100% rename from app/pom.xml rename to 04fx/app/pom.xml diff --git a/app/src/main/java/com/example/app/App.java b/04fx/app/src/main/java/com/example/app/App.java similarity index 78% rename from app/src/main/java/com/example/app/App.java rename to 04fx/app/src/main/java/com/example/app/App.java index bcd641a1..7402ca99 100644 --- a/app/src/main/java/com/example/app/App.java +++ b/04fx/app/src/main/java/com/example/app/App.java @@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; + @SpringBootApplication public class App { @@ -13,13 +14,13 @@ public static void main(String[] args) { } - // ==== 测试自动配置 ==== @Autowired WebInfo info; + // DONE_Joly:什么都没注册,那这里的目的是什么--->为了运行一下,看看WebInfo注入了没有 @Bean - public void printInfo(){ + public void printInfo() { System.out.println(info.getName()); } diff --git a/app/src/main/java/com/example/app/WebAutoConfiguration.java b/04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java similarity index 65% rename from app/src/main/java/com/example/app/WebAutoConfiguration.java rename to 04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java index e63d295f..2c1b004b 100644 --- a/app/src/main/java/com/example/app/WebAutoConfiguration.java +++ b/04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java @@ -6,6 +6,11 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +/** + * knowledge point: + * Import注解:和 Spring 的 xml 配置文件中的一样 + * EnableConfigurationProperties注解: + */ @Configuration @Import(WebConfiguration.class) @EnableConfigurationProperties(WebProperties.class) @@ -13,13 +18,13 @@ public class WebAutoConfiguration { @Autowired WebProperties properties; - + // TODO_Joly:这里就算不import也可以注入的吧 @Autowired WebConfiguration configuration; @Bean - public WebInfo creatInfo(){ - return new WebInfo(configuration.name + "-"+properties.getA()); + public WebInfo creatInfo() { + return new WebInfo(configuration.name + "-" + properties.getA()); } } diff --git a/app/src/main/java/com/example/app/WebConfiguration.java b/04fx/app/src/main/java/com/example/app/WebConfiguration.java similarity index 69% rename from app/src/main/java/com/example/app/WebConfiguration.java rename to 04fx/app/src/main/java/com/example/app/WebConfiguration.java index d645d77b..6ea3b6c5 100644 --- a/app/src/main/java/com/example/app/WebConfiguration.java +++ b/04fx/app/src/main/java/com/example/app/WebConfiguration.java @@ -2,6 +2,9 @@ import org.springframework.context.annotation.Configuration; +/** + * knowledge point: @Configuration 表示是一个做配置的类 + */ @Configuration public class WebConfiguration { diff --git a/app/src/main/java/com/example/app/WebInfo.java b/04fx/app/src/main/java/com/example/app/WebInfo.java similarity index 100% rename from app/src/main/java/com/example/app/WebInfo.java rename to 04fx/app/src/main/java/com/example/app/WebInfo.java diff --git a/app/src/main/java/com/example/app/WebProperties.java b/04fx/app/src/main/java/com/example/app/WebProperties.java similarity index 73% rename from app/src/main/java/com/example/app/WebProperties.java rename to 04fx/app/src/main/java/com/example/app/WebProperties.java index 713fbeed..1109a497 100644 --- a/app/src/main/java/com/example/app/WebProperties.java +++ b/04fx/app/src/main/java/com/example/app/WebProperties.java @@ -1,7 +1,9 @@ package com.example.app; import org.springframework.boot.context.properties.ConfigurationProperties; - +/** knowledge point: + * ConfigurationProperties注解:用于根据配置文件注册应用程序的Bean + * */ @ConfigurationProperties(prefix = "web") public class WebProperties { diff --git a/app/src/main/resources/META-INF/spring.factories b/04fx/app/src/main/resources/META-INF/spring.factories similarity index 100% rename from app/src/main/resources/META-INF/spring.factories rename to 04fx/app/src/main/resources/META-INF/spring.factories diff --git a/app/src/main/resources/application.properties b/04fx/app/src/main/resources/application.properties similarity index 100% rename from app/src/main/resources/application.properties rename to 04fx/app/src/main/resources/application.properties diff --git a/app/src/test/java/com/example/app/AppApplicationTests.java b/04fx/app/src/test/java/com/example/app/AppApplicationTests.java similarity index 100% rename from app/src/test/java/com/example/app/AppApplicationTests.java rename to 04fx/app/src/test/java/com/example/app/AppApplicationTests.java diff --git a/04fx/java8/README.md b/04fx/java8/README.md new file mode 100644 index 00000000..31d380c3 --- /dev/null +++ b/04fx/java8/README.md @@ -0,0 +1,5 @@ +## ʾ Lombokstreamlambda +* Spring Framework +### Lombok +* A +* LombokDemo \ No newline at end of file diff --git a/04fx/java8/pom.xml b/04fx/java8/pom.xml index 695421a5..2b811640 100644 --- a/04fx/java8/pom.xml +++ b/04fx/java8/pom.xml @@ -37,6 +37,7 @@ guava 29.0-jre + org.projectlombok lombok diff --git a/04fx/java8/src/main/java/io/kimmking/java8/A.java b/04fx/java8/src/main/java/io/kimmking/java8/A.java index e3027fce..0ff5a824 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/A.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/A.java @@ -3,6 +3,12 @@ import lombok.*; import lombok.extern.slf4j.Slf4j; +/** + * ʾLombok + * + * @author Joly + * @date 2022/4/24 + */ @ToString @NoArgsConstructor @AllArgsConstructor diff --git a/04fx/java8/src/main/java/io/kimmking/java8/CollectionDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/CollectionDemo.java index 90670a12..74b92950 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/CollectionDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/CollectionDemo.java @@ -6,10 +6,15 @@ import java.util.List; import java.util.stream.Collectors; +/** + * 用Collections操作完list以后,再使用stream来操作list + * + * @author 小虫子的小日常 + */ public class CollectionDemo { public static void main(String[] args) throws IOException { - - List list = Arrays.asList(4,2,3,5,1,2,2,7,6); // Arrays还可以包装stream + /** knowledge point: 用Arrays.asList的目的是简便操作,这样就不用new一个List出来,然后一个一个往里面加元素了*/ + List list = Arrays.asList(4, 2, 3, 5, 1, 2, 2, 7, 6); // Arrays还可以包装stream print(list); Collections.sort(list); print(list); @@ -17,20 +22,24 @@ public static void main(String[] args) throws IOException { print(list); Collections.shuffle(list); print(list); - + System.out.println(Collections.frequency(list, 2)); System.out.println(Collections.max(list)); - - Collections.fill(list,8); + + Collections.fill(list, 8); print(list); - + list = Collections.singletonList(6); print(list); - + } - + private static void print(List list) { - System.out.println(String.join(",",list.stream().map(i -> i.toString()).collect(Collectors.toList()).toArray(new String[]{}))); + System.out.println(String.join(",", + list.stream() + .map(i -> i.toString()) + .collect(Collectors.toList()) + .toArray(new String[]{}))); } - + } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/ForeachDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/ForeachDemo.java index b4f8507d..4922d924 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/ForeachDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/ForeachDemo.java @@ -15,7 +15,6 @@ public static void main(String[] args) { System.out.println(demo.x); } - private void test() { List list = Arrays.asList(1,2); int y = 1; diff --git a/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java index 7de88d61..572d922e 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java @@ -20,7 +20,6 @@ public static void main(String[] args) { Class c = (Class) p.getActualTypeArguments()[0]; System.out.println(c); } - public static class Person { } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java index e505fec7..8a7ae818 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java @@ -14,108 +14,131 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.util.List; import java.util.Map; +/** + * 演示Guava + * + * @author Joly + * @date 2022/4/26 + */ +@Slf4j public class GuavaDemo { - + // 常规情况下,一个项目用一个EventBus就够了 static EventBus bus = new EventBus(); + static { + // 被调用方(类似于消费者)向EventBus注册 bus.register(new GuavaDemo()); } - - + + @SneakyThrows public static void main(String[] args) throws IOException { - + List lists = testString(); - + List list = testList(); - + testMap(list); - + testBiMap(lists); - + testEventBus(); - + } - + private static void testEventBus() { + log.info("=====testEventBus====="); // EventBus // SPI+service loader // Callback/Listener // Student student2 = new Student(2, "KK02"); - System.out.println(Thread.currentThread().getName()+" I want " + student2 + " run now."); + System.out.println(Thread.currentThread().getName() + " I want " + student2 + " run now."); bus.post(new AEvent(student2)); + int a = 1; } - + private static void testBiMap(List lists) { + log.info("=====testBiMap====="); + // Guava里的双向Map BiMap words = HashBiMap.create(); words.put("First", 1); words.put("Second", 2); words.put("Third", 3); - + System.out.println(words.get("Second").intValue()); + // 翻转key和value(也就是说key和value相互换值),从而根据原来的value可以找到原来的key System.out.println(words.inverse().get(3)); - - Map map1 = Maps.toMap(lists.listIterator(), a -> a+"-value"); + + Map map1 = Maps.toMap(lists.listIterator(), a -> a + "-value"); + //Exception in thread "main" java.lang.UnsupportedOperationException + // at com.google.common.collect.ImmutableMap.put(ImmutableMap.java:529) + // 因为这是一个immutable的Map,所以不可以对这个map进行任何更新操作 + // map1.put("34344","changed"); + // map1.put("12345","11"); print(map1); } - + private static void testMap(List list) { + log.info("=====testMap====="); //Map map = list.stream().collect(Collectors.toMap(a->a,a->(a+1))); - Multimap bMultimap = ArrayListMultimap.create(); + // 用Guava创建了多值的map:在放入用一个key,value的时候不会覆盖上一个value,而是增加一个value + Multimap multimap = ArrayListMultimap.create(); list.forEach( - a -> bMultimap.put(a,a+1) + a -> multimap.put(a, a + 1) ); - print(bMultimap); + print(multimap); } - + private static List testList() { + log.info("=====testList====="); // 更强的集合操作 // 简化 创建 - - List list = Lists.newArrayList(4,2,3,5,1,2,2,7,6); - - List> list1 = Lists.partition(list,3); + + List list = Lists.newArrayList(4, 2, 3, 5, 1, 2, 2, 7, 6); + // 分片,把list拆成了三个list。在对一大堆数据进行分组的时候非常的有用。 + List> list1 = Lists.partition(list, 3); print(list1); return list; } - + private static List testString() { + log.info("=====testString====="); // 字符串处理 - // - List lists = Lists.newArrayList("a","b","g","8","9"); - + // + List lists = Lists.newArrayList("a", "b", "g", "8", "9"); + lists.set(1, "aaaaaa"); String result = Joiner.on(",").join(lists); System.out.println(result); - + String test = "34344,,,34,34,哈哈"; lists = Splitter.on(",").splitToList(test); System.out.println(lists); return lists; } - + private static void print(Object obj) { System.out.println(JSON.toJSONString(obj)); } - - + + @Data @AllArgsConstructor - public static class AEvent{ + public static class AEvent { private Student student; } - + @Subscribe - public void handle(AEvent ae){ - System.out.println(Thread.currentThread().getName()+" "+ae.student + " is running."); + public void handle(AEvent ae) { + System.out.println(Thread.currentThread().getName() + " " + ae.student + " is running."); } - - - + + } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java index 94996f3b..a0f405dd 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java @@ -1,90 +1,128 @@ package io.kimmking.java8; +import com.google.common.base.Function; + import java.io.Serializable; import java.util.Arrays; import java.util.Collection; -public class LambdaDemo { - - public static void main(String args[]){ +/** + * 泛型TextendsA&B&C的话,传进来的T就必需把ABC的接口都实现了。 + * extends在这里表示的是一种层级关系,同时&的作用就是接口的多实现 + * + * @author Joly + */ +public class LambdaDemo { + + public static void main(String[] args) { LambdaDemo demo = new LambdaDemo(); - + // java7及以前用匿名类的方式来实现接口里的方法 MathOperation op = new MathOperation() { @Override public Integer operation(int a, int b) { return 1; } }; - + Integer operation = (Integer) op.operation(1, 2); + System.out.println(operation); + + // java 8 及以后用lambda来实现接口里的方法 MathOperation op1 = (a, b) -> 1; + Integer operation1 = (Integer) op1.operation(1, 1); + System.out.println(operation1); MathOperation op2 = new MathOperation() { @Override public Integer operation(int a, int b) { - return a+b; + return a + b; } }; - + // 类型声明 MathOperation addition = (int a, int b) -> a + b; - - // 不用类型声明 - MathOperation subtraction = (int a, int b) -> a - b ; - + + // 不用类型声明 + MathOperation subtraction = (int a, int b) -> a - b; + // 大括号中的返回语句 - MathOperation multiplication = (int a, int b) -> { + MathOperation multiplication = (int a, int b) -> { //int c = 1000; return a * b;// + c; }; - + // 没有大括号及返回语句 MathOperation division = (int a, int b) -> a / b; - + System.out.println("10 + 5 = " + demo.operate(10, 5, addition)); System.out.println("10 - 5 = " + demo.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + demo.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + demo.operate(10, 5, division)); - + //System.out.println("10 ^ 5 = " + demo.operate(10, 5, (a, b) -> new Double(Math.pow(a,b)).intValue())); - - System.out.println("10 ^ 5 = " + demo.operate(10, 5, (a, b) -> Math.pow(a,b))); + + System.out.println("10 ^ 5 = " + demo.operate(10, 5, (a, b) -> Math.pow(a, b))); Runnable task = () -> System.out.println(1111); // 不用括号 GreetingService greetService1 = message -> System.out.println("Hello " + message); - + // 用括号 GreetingService greetService2 = (message) -> { System.out.println(message); }; - + // 类似函数指令的用法 + // 因为sayMessage的参数是String,println的参数也是String,所以在写println的时候就直接可以不写参数了 + // 这样就进一步简化了 GreetingService greetService3 = System.out::println; - Arrays.asList(1,2,3).forEach( x -> System.out.println(x+3)); - Arrays.asList(1,2,3).forEach( LambdaDemo::println ); - + + // 构造器也可以简化 + Function doubleDoubleFunction = Double::new; + + Arrays.asList(1, 2, 3).forEach(x -> System.out.println(x + 3)); + Arrays.asList(1, 2, 3).forEach(LambdaDemo::println); greetService1.sayMessage("kimmking"); greetService2.sayMessage("Java"); greetService3.sayMessage("CuiCuilaoshi"); } - + private static void println(int x) { - System.out.println(x+3); + System.out.println(x + 3); } - + + /** + * 有参数,有返回值(泛型) + * + * @author jrl + * @date 2022/2/26 + */ interface MathOperation { T operation(int a, int b); // 返回类型+函数名+参数类型的列表 } - + + /** + * 有参数,没有返回值 + * + * @author jrl + * @date 2022/2/26 + */ interface GreetingService { void sayMessage(String message); } - - private T operate(int a, int b, MathOperation mathOperation){ + + + /** + * A方法实现执行:参数abc和要使用abc参数的B方法 + * 这样使得用B方法更加的简单,相当于结合了实现B方法和调用B方法 + * + * @author jrl + * @date 2022/2/26 + */ + private T operate(int a, int b, MathOperation mathOperation) { return mathOperation.operation(a, b); } - + } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java index a1333f4f..7def8c0c 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java @@ -5,6 +5,12 @@ import java.io.IOException; +/** + * ʾLombok + * + * @author Joly + * @date 2022/4/24 + */ @Log public class LombokDemo { @@ -20,19 +26,34 @@ public static void main(String[] args) throws IOException { A b = A.builder().age(1).name("KKK").build(); new LombokDemo().demo(); - + Student student1 = new Student(); student1.setId(1); student1.setName("KK01"); System.out.println(student1.toString()); - + Student student2 = new Student(2, "KK02"); //student2.init(); System.out.println(student2.toString()); + new LombokDemo().testData(); } - + private void demo() { - log.info("demo in log."); + /** knowledge point: + * logidealombokڱɵ + * */ + log.info("demo in log."); } - + + /** + * LombokDataע + * + * @param + * @return + * @date 2022/4/24 + */ + private void testData() { + new Student4Data("ֻname"); + } + } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java index b2771ff3..735008a8 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java @@ -6,47 +6,69 @@ import java.util.*; import java.util.stream.Collectors; +/** + * stream + * + * @author Joly + * @date 2022-2-27 + */ public class StreamDemo { - + public static void main(String[] args) throws IOException { - - List list = Arrays.asList(4,2,3,5,1,2,2,7,6); + //9个元素 + List list = Arrays.asList(4, 2, 3, 5, 1, 2, 2, 7, 6); print(list); - - // Optional - Optional first = list.stream().findFirst(); - System.out.println(first.map(i -> i * 100).orElse(100)); + // Optional + // Optional看样子是配合stream一起出现的,1.8. + // DONE_Joly:Optional 的目的是什么 ---> 因为流操作的时候,如果返回的不是Optional,而是Integer一类的,那么有可能就会返回一个null,那么再往后操作 + //就会NPE,这个时候为了规避这种问题就采用了中间形式Optional,如果为空的话,就是Optional的value为空。 + // 那么这就说明了,所谓的终止操作只是逻辑上的,实际在语法层面并没有真的给终止操作带来的一个用户想要的数据形式,就像是Integer还是用Optional给封装了。 + Optional first = list.stream() + .findFirst();//终止操作--->查找与匹配:findFirst() + // DONE_Joly Optional 也有一套自己的类似stream的操作--->因为Optional是一个中间的形式,所以当然会有stream的那一套操作了 + //orElse的作用是如果为空,就使用orElse里的参数 + System.out.println(first.map(i -> i * 100).filter(i -> i > 100).orElse(100)); //1,2,3 // 0, 1, 2, 3 - int sum = list.stream().filter( i -> i<4).distinct().reduce(0,(a,b)->a+b); - System.out.println("sum="+sum); + // reduce:迭代式的进行数据操作:0+1=1,1+2=3,3+3=6,由于拿到第一个元素的时候没有与之对应的操作数,所以就需要我们给一个,这里给的0 + int sum = list.stream().filter(i -> i < 4).distinct().reduce(0, (a, b) -> a + b); + System.out.println("sum=" + sum); //1,2,3 // 1, 1, 2, 3 - int multi = list.stream().filter( i -> i<4).distinct().reduce(1,(a,b)->a*b); - System.out.println("multi="+multi); - - //Map map1 = list.stream().collect(Collectors.toMap(a->a,a->(a+1))); - Map map = list.stream().parallel().collect(Collectors.toMap(a->a,a->(a+1),(a,b)->a, LinkedHashMap::new)); + int multi = list.stream().filter(i -> i < 4).distinct().reduce(1, (a, b) -> a * b); + System.out.println("multi=" + multi); + //Collectors.toMap(key,value) + Map map1 = list.stream().collect(Collectors.toMap(a -> a, a -> (a + 1))); + // DONE_Joly:parallel 是拿来做什么的--->指明可以采用多线程的方式来处理,默认是单线程的哒 + //Collectors.toMap(key,value,key重了取哪个value,用哪种Map来装值) + Map map = list.stream().parallel().collect(Collectors.toMap(a -> a, a -> (a + 1), (a, b) -> a, LinkedHashMap::new)); print(map); - - + + //forEach的参数是个lambda表达式 map.forEach((k, v) -> System.out.println("key:value = " + k + ":" + v)); - List list1 = map.entrySet().parallelStream().map(e -> e.getKey()+e.getValue()).collect(Collectors.toList()); + //parallelStream指明可以采用多线程的方式来处理 + List list1 = map.entrySet().parallelStream().map(e -> e.getKey() + e.getValue()).collect(Collectors.toList()); print(list1); - + // parallelStream() - + // 总结: - // 1. Fluent API:继续Stream + // 1. Fluent API:继续Stream。 FluentAPI的意思就是说,可以一直点点点下去的操作,就是流操作 // 2. 终止操作:得到结果 - - + + } - - + + /** + * 使用JSON的方式输出 + * + * @param + * @return + * @date 2022-2-27 + */ private static void print(Object obj) { System.out.println(JSON.toJSONString(obj)); } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/Student.java b/04fx/java8/src/main/java/io/kimmking/java8/Student.java index f08748c4..514a4184 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/Student.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/Student.java @@ -11,35 +11,40 @@ import java.io.Serializable; - +/** + * ʾLombok + * + * @author Joly + * @date 2022/4/24 + */ @Data @NoArgsConstructor @ToString @Slf4j public class Student implements Serializable, ApplicationContextAware { - + private int id; private String name; - + private ApplicationContext applicationContext; - + public Student(int id, String name) { this.id = id; this.name = name; } - - public void init(){ + + public void init() { System.out.println("hello..........."); log.debug("ddddddddddddddd"); } - - public Student create(){ - + + public Student create() { + this.applicationContext.getBeanDefinitionNames(); - Student s = new Student(101,"KK101"); + Student s = new Student(101, "KK101"); return s; } - + @Override public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; diff --git a/04fx/java8/src/main/java/io/kimmking/java8/Student4Data.java b/04fx/java8/src/main/java/io/kimmking/java8/Student4Data.java new file mode 100644 index 00000000..30427bb9 --- /dev/null +++ b/04fx/java8/src/main/java/io/kimmking/java8/Student4Data.java @@ -0,0 +1,15 @@ +package io.kimmking.java8; + +import lombok.Data; + +/** + * LombokDataע + * + * @author jrl + * @date Create in 22:03 2022/4/24 + */ +@Data +public class Student4Data { + private final String name; + private int age; +} diff --git a/04fx/java8/src/main/java/io/kimmking/java8/jrl/GenericJrl.java b/04fx/java8/src/main/java/io/kimmking/java8/jrl/GenericJrl.java new file mode 100644 index 00000000..0eacbcfb --- /dev/null +++ b/04fx/java8/src/main/java/io/kimmking/java8/jrl/GenericJrl.java @@ -0,0 +1,10 @@ +package io.kimmking.java8.jrl; + +/** + * Է͵Ļʹ + * + * @author jrl + * @date 2022/1/31 + */ +public class GenericJrl { +} diff --git a/04fx/java8/src/main/java/io/kimmking/java8/jrl/LambdaDemoJrl.java b/04fx/java8/src/main/java/io/kimmking/java8/jrl/LambdaDemoJrl.java new file mode 100644 index 00000000..95a65ba3 --- /dev/null +++ b/04fx/java8/src/main/java/io/kimmking/java8/jrl/LambdaDemoJrl.java @@ -0,0 +1,41 @@ +package io.kimmking.java8.jrl; + +import java.io.Serializable; +import java.util.Collection; + +/** + * @author jrl + * @date 2022/1/31 + */ +public class LambdaDemoJrl { + public static void main(String[] args) { + MathOperation mathOperation = (a, b) -> Long.valueOf(a + b); + Long operation = mathOperation.operation(1, 2); + System.out.println(operation); + GreetingService greetingService = s -> System.out.println(s); + greetingService.sayMessage("hello"); + } + + /** + * ڲӿ + * + * @author jrl + * @date 2022/1/31 + */ + interface MathOperation { + /** + * abһЩѧ + * + * @param a 1 + * @param b 2 + * @return Ľ + * @date 2022/1/31 + */ + T operation(int a, int b); // ++͵б + } + + interface GreetingService { + void sayMessage(String message); + } + +} diff --git a/04fx/java8/src/main/java/jrl/AInterface.java b/04fx/java8/src/main/java/jrl/AInterface.java new file mode 100644 index 00000000..dc6f1e26 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/AInterface.java @@ -0,0 +1,9 @@ +package jrl; + +/** + * @author jrl + * @date Create in 16:27 2022-2-25 + */ +public interface AInterface { + void a1(Object o); +} diff --git a/04fx/java8/src/main/java/jrl/AnonymityClazz.java b/04fx/java8/src/main/java/jrl/AnonymityClazz.java new file mode 100644 index 00000000..36b9682a --- /dev/null +++ b/04fx/java8/src/main/java/jrl/AnonymityClazz.java @@ -0,0 +1,22 @@ +package jrl; + +/** + * @author jrl + * @date Create in 16:27 2022-2-25 + */ +public class AnonymityClazz { + public static void main(String[] args) { + // 以匿名类的方式实现A接口 + AInterface aImpl = new AInterface() { + @Override + public void a1(Object o) { + System.out.println("匿名类的实现"); + } + }; + aImpl.a1("o"); + AInterface aLambdaImpl = (o) -> System.out.println("lambda实现"); + AInterface aLambdaImpl2 = v -> System.out.println(v); + aLambdaImpl.a1("lambda"); + aLambdaImpl2.a1("o"); + } +} diff --git a/04fx/java8/src/main/java/jrl/ClassLoaderBasicLearn.java b/04fx/java8/src/main/java/jrl/ClassLoaderBasicLearn.java new file mode 100644 index 00000000..525580e0 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/ClassLoaderBasicLearn.java @@ -0,0 +1,10 @@ +package jrl; + +import sun.java2d.pipe.BufferedTextPipe; + +public class ClassLoaderBasicLearn { + public static void main(String[] args) { +// new Byte[5]; +// System.out.println(arr[5]); + } +} diff --git a/04fx/java8/src/main/java/jrl/ClassLoaderLearn.java b/04fx/java8/src/main/java/jrl/ClassLoaderLearn.java new file mode 100644 index 00000000..365baf37 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/ClassLoaderLearn.java @@ -0,0 +1,28 @@ +package jrl; + + +public class ClassLoaderLearn { + static double a = Math.random(); + + static { + System.out.println("初始化代码块"); + System.out.println("静态代码块中a的值为:" + a); + } + + public ClassLoaderLearn() { + System.out.println("构造函数"); + System.out.println("静态变量a的值为:" + a); + } + + /** + * knowledge point: + * 静态属性的初始化和静态方法的执行,只会执行一次。是在类加载阶段。 + * 创建对象阶段会执行构造函数。 + */ + public static void main(String[] args) { + for (int i = 0; i < 2; i++) { + new ClassLoaderLearn(); + System.out.println("主方法中a的值:"+a); + } + } +} \ No newline at end of file diff --git a/04fx/java8/src/main/java/jrl/ConstClass.java b/04fx/java8/src/main/java/jrl/ConstClass.java new file mode 100644 index 00000000..6c31a115 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/ConstClass.java @@ -0,0 +1,9 @@ +package jrl; + +public class ConstClass { + static { + System.out.println("ConstClass init!"); + } + + public static final String HELLOWORLD = "hello world!"; +} diff --git a/04fx/java8/src/main/java/jrl/Father.java b/04fx/java8/src/main/java/jrl/Father.java new file mode 100644 index 00000000..b7805fda --- /dev/null +++ b/04fx/java8/src/main/java/jrl/Father.java @@ -0,0 +1,5 @@ +package jrl; + +public class Father { + final static int f1 = 1; +} diff --git a/04fx/java8/src/main/java/jrl/NotInitialization.java b/04fx/java8/src/main/java/jrl/NotInitialization.java new file mode 100644 index 00000000..455570ab --- /dev/null +++ b/04fx/java8/src/main/java/jrl/NotInitialization.java @@ -0,0 +1,43 @@ +package jrl; + +/** + * knowledge point: + * 类初始化的时机 + */ +public class NotInitialization { + public static void main(String[] args) { + + SuperClass[] sca = new SuperClass[10]; + /** + * output : + * + * 通过数组定义来引用类不会触发此类的初始化 + * 虚拟机在运行时动态创建了一个数组类 + */ + System.out.println("----------------------------------------------------"); + new SuperClass(); + /** + * output: SuperClass init! + * 不是数组的话,就会在new的时候正常触发初始化了 + * */ + System.out.println("-----------------------------------------------------"); + System.out.println(SubClass.value); + /** + * output : SuperClass init! + * 1127 + * + * 通过子类引用父类的静态对象不会导致子类的初始化 + * 只有直接定义这个字段的类才会被初始化 + */ + + + System.out.println(ConstClass.HELLOWORLD); + /** + * output : + * + * 常量在编译阶段会存入调用类的常量池当中,本质上并没有直接引用到定义类常量的类, + * 因此不会触发定义常量的类的初始化。 + * “hello world” 在编译期常量传播优化时已经存储到 NotInitialization 常量池中了。 + */ + } +} \ No newline at end of file diff --git a/04fx/java8/src/main/java/jrl/README.md b/04fx/java8/src/main/java/jrl/README.md new file mode 100644 index 00000000..0d2d32c6 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/README.md @@ -0,0 +1 @@ +## ЩʱģֵֹJava \ No newline at end of file diff --git a/04fx/java8/src/main/java/jrl/Son.java b/04fx/java8/src/main/java/jrl/Son.java new file mode 100644 index 00000000..0d491480 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/Son.java @@ -0,0 +1,12 @@ +package jrl; + + +public class Son extends Father { + + + public static void main(String[] args) { + System.out.println(f1); + + + } +} diff --git a/04fx/java8/src/main/java/jrl/SubClass.java b/04fx/java8/src/main/java/jrl/SubClass.java new file mode 100644 index 00000000..e76c1e11 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/SubClass.java @@ -0,0 +1,7 @@ +package jrl; + +public class SubClass extends SuperClass { + static { + System.out.println("SubClass init!"); + } +} diff --git a/04fx/java8/src/main/java/jrl/SuperClass.java b/04fx/java8/src/main/java/jrl/SuperClass.java new file mode 100644 index 00000000..c4481012 --- /dev/null +++ b/04fx/java8/src/main/java/jrl/SuperClass.java @@ -0,0 +1,9 @@ +package jrl; + +public class SuperClass { + static { + System.out.println("SuperClass init!"); + } + + public static int value = 1127; +} diff --git a/04fx/jdbc/.gitignore b/04fx/jdbc/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/04fx/jdbc/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/04fx/jdbc/.mvn/wrapper/maven-wrapper.jar b/04fx/jdbc/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..c1dd12f1 Binary files /dev/null and b/04fx/jdbc/.mvn/wrapper/maven-wrapper.jar differ diff --git a/04fx/jdbc/.mvn/wrapper/maven-wrapper.properties b/04fx/jdbc/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..b7cb93e7 --- /dev/null +++ b/04fx/jdbc/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/04fx/jdbc/README.md b/04fx/jdbc/README.md new file mode 100644 index 00000000..b36d7ec3 --- /dev/null +++ b/04fx/jdbc/README.md @@ -0,0 +1,5 @@ +### ҵ +10.оһ JDBC ӿںݿӳأǵƺ÷ +1. ʹ JDBC ԭӿڣʵݿɾIJ +2. ʹPrepareStatement ʽʽĽ +3. Hikari ӳأĽύ뵽 GitHub \ No newline at end of file diff --git a/app/mvnw b/04fx/jdbc/mvnw old mode 100755 new mode 100644 similarity index 94% rename from app/mvnw rename to 04fx/jdbc/mvnw index a16b5431..8a8fb228 --- a/app/mvnw +++ b/04fx/jdbc/mvnw @@ -36,6 +36,10 @@ if [ -z "$MAVEN_SKIP_RC" ] ; then + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + if [ -f /etc/mavenrc ] ; then . /etc/mavenrc fi @@ -145,7 +149,7 @@ if [ -z "$JAVACMD" ] ; then JAVACMD="$JAVA_HOME/bin/java" fi else - JAVACMD="`which java`" + JAVACMD="`\\unset -f command; \\command -v java`" fi fi @@ -212,9 +216,9 @@ else echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." fi if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" fi while IFS="=" read key value; do case "$key" in (wrapperUrl) jarUrl="$value"; break ;; @@ -233,9 +237,9 @@ else echo "Found wget ... using wget" fi if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi elif command -v curl > /dev/null; then if [ "$MVNW_VERBOSE" = true ]; then @@ -305,6 +309,8 @@ WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain exec "$JAVACMD" \ $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/app/mvnw.cmd b/04fx/jdbc/mvnw.cmd similarity index 84% rename from app/mvnw.cmd rename to 04fx/jdbc/mvnw.cmd index c8d43372..1d8ab018 100644 --- a/app/mvnw.cmd +++ b/04fx/jdbc/mvnw.cmd @@ -46,8 +46,8 @@ if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") @REM Execute a user defined script before this one if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre @REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* :skipRcPre @setlocal @@ -120,9 +120,9 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B ) @@ -134,7 +134,7 @@ if exist %WRAPPER_JAR% ( ) ) else ( if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" ) if "%MVNW_VERBOSE%" == "true" ( echo Couldn't find %WRAPPER_JAR%, downloading it ... @@ -158,7 +158,13 @@ if exist %WRAPPER_JAR% ( @REM work with both Windows and non-Windows executions. set MAVEN_CMD_LINE_ARGS=%* -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end @@ -168,15 +174,15 @@ set ERROR_CODE=1 :end @endlocal & set ERROR_CODE=%ERROR_CODE% -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost @REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" :skipRcPost @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause +if "%MAVEN_BATCH_PAUSE%"=="on" pause -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% -exit /B %ERROR_CODE% +cmd /C exit /B %ERROR_CODE% diff --git a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JDBCCRUD.java b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JDBCCRUD.java new file mode 100644 index 00000000..182872fd --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JDBCCRUD.java @@ -0,0 +1,44 @@ +package top.jrl.homework.jdbc; + +import java.sql.*; + +/** + * 使用 JDBC 原生接口,实现数据库的增删改查操作。 + * + * @author jrl + * @date Create in 22:12 2022/4/21 + */ +public class JDBCCRUD { + public static void main(String[] args) throws SQLException { + //1.注册驱动(mysql针对JDBC提供的驱动) + // Class.forName("com.mysql.jdbc.Driver"); + //2.获取连接对象 + String url = "jdbc:mysql://47.115.148.27:3306/base1"; + Connection connection = DriverManager.getConnection(url, "joly1", "some_pass"); + //3.获取执行SQL语句 + Statement statement = connection.createStatement(); + String sql = "select * from person where age = '25' "; + //4.调用执行者对象方法,执行SQL语句获取结果集 + //5.处理结果集 + //4.1 查 + ResultSet resultSet = statement.executeQuery(sql); + // TODO_Joly:这里有个顺序bug,我不知道为什么。都执行完了sql以后再去处理结果集就会报错。 + // TODO_Joly:说连接已经断开了 + //5.1 查 + while (resultSet.next()) { + int age = resultSet.getInt("age"); + System.out.println(age); + } + //4.2 增 + int executeUpdate = statement.executeUpdate("insert into person values (26,'Jolin-super',0)"); + //5.2 增 + if (executeUpdate != -1) { + System.out.println(executeUpdate); + } + //6.关闭资源 + // TODO_Joly:resultSet\statement为什么要关闭,这俩本质是啥.我可能还不太明白关闭到底意味着什么。 + resultSet.close(); + statement.close(); + connection.close(); + } +} diff --git a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JdbcApplication.java b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JdbcApplication.java new file mode 100644 index 00000000..ffa11843 --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JdbcApplication.java @@ -0,0 +1,13 @@ +package top.jrl.homework.jdbc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class JdbcApplication { + + public static void main(String[] args) { + SpringApplication.run(JdbcApplication.class, args); + } + +} diff --git a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/MyHikariDataSource.java b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/MyHikariDataSource.java new file mode 100644 index 00000000..2e06f98d --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/MyHikariDataSource.java @@ -0,0 +1,33 @@ +package top.jrl.homework.jdbc; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * https://www.baeldung.com/hikaricp + * + * @author jrl + * @date Create in 14:16 2022/4/23 + */ +public class MyHikariDataSource { + // let's look at HikariCP, a lightning-fast JDBC connection pooling framework + private static HikariConfig config = new HikariConfig(); + private static HikariDataSource ds; + + static { + config.setJdbcUrl("jdbc:mysql://47.115.148.27:3306/base1"); + config.setUsername("joly1"); + config.setPassword("some_pass"); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + ds = new HikariDataSource(config); + } + + public static Connection getConnection() throws SQLException { + return ds.getConnection(); + } +} diff --git a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/PrepareStatementJDBC.java b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/PrepareStatementJDBC.java new file mode 100644 index 00000000..6f93c11d --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/PrepareStatementJDBC.java @@ -0,0 +1,75 @@ +package top.jrl.homework.jdbc; + + +import java.sql.*; +import java.util.Arrays; +import java.util.Random; + +/** + * 2)使用事务,PrepareStatement 方式,批处理方式,改进上述操作。 + * 3)配置 Hikari 连接池,改进上述操作。 + * + * @author jrl + * @date Create in 13:59 2022/4/22 + */ + +public class PrepareStatementJDBC { + + public static void main(String[] args) throws SQLException { + //2.获取连接对象 + // String url = "jdbc:mysql://47.115.148.27:3306/base1"; + // Connection connection = DriverManager.getConnection(url, "joly1", "some_pass"); + Connection connection = MyHikariDataSource.getConnection(); + //3.获取执行SQL语句 + String sql = "select * from person where age = ? "; + String updateSql = "update person set age = ? where name = ?"; + PreparedStatement preparedStatement = connection.prepareStatement(sql); + PreparedStatement preparedStatement1 = connection.prepareStatement(updateSql); + //4.调用执行者对象方法,执行SQL语句获取结果集 + //5.处理结果集 + //4.1 查 + preparedStatement.setInt(1, 25); + ResultSet resultSet = preparedStatement.executeQuery(); + //4.2 更新 + for (int i = 0; i < 3; i++) { + preparedStatement1.setInt(1, new Random().nextInt(100)); + preparedStatement1.setString(2, "Jolin" + "-" + i); + connection.setAutoCommit(false); + int executeUpdate = preparedStatement1.executeUpdate(); + if (executeUpdate != 0) { + System.out.println(executeUpdate); + + } + if (new Random().nextInt(10) > 5) { + connection.commit(); + System.out.println("commit" + i); + } else { + connection.rollback(); + System.out.println("rollback" + i); + } + } + // 4.3 使用批处理 + connection.setAutoCommit(false); + for (int i = 0; i < 3; i++) { + preparedStatement1.setInt(1, new Random().nextInt(100)); + preparedStatement1.setString(2, "Jolin" + "-" + i); + preparedStatement1.addBatch(); + } + int[] ints = preparedStatement1.executeBatch(); + connection.commit(); + Arrays.stream(ints).forEach( + System.out::println + ); + + //5.1 查 + while (resultSet.next()) { + int age = resultSet.getInt("age"); + System.out.println(age); + } + + //6.关闭资源 + // 使用Hikari的情况下,就会去调用Hikari的实现。因为这个close是个抽象方法呀 + connection.close(); + + } +} diff --git a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/BasicConnectionPool.java b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/BasicConnectionPool.java new file mode 100644 index 00000000..b0854a61 --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/BasicConnectionPool.java @@ -0,0 +1,102 @@ +package top.jrl.homework.jdbc.connection; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author jrl + * @date Create in 11:37 2022/4/23 + */ +public class BasicConnectionPool implements ConnectionPool { + private String url; + private String user; + private String password; + // 剩下还没被用的connection + private List connectionPool; + // 正在被用的connection + private List usedConnections = new ArrayList<>(); + private static int INITIAL_POOL_SIZE = 10; + + /** + * 初始化数据库连接池:创建多个连接,并放入连接池(容器)中 + * As it's much better to keep the creation of connections database agnostic, + * we've used the former within the create() static factory method. + * + * @param + * @return + * @date 2022/4/23 + */ + public static BasicConnectionPool create( + String url, String user, + String password) throws SQLException { + + List pool = new ArrayList<>(INITIAL_POOL_SIZE); + for (int i = 0; i < INITIAL_POOL_SIZE; i++) { + pool.add(createConnection(url, user, password)); + } + return new BasicConnectionPool(url, user, password, pool); + } + + private static Connection createConnection( + String url, String user, String password) + throws SQLException { + return DriverManager.getConnection(url, user, password); + } + + @Override + public Connection getConnection() { + // 从数据库连接池中拿出来一个连接 + Connection connection = connectionPool + .remove(connectionPool.size() - 1); + // 把这个连接放到已使用连接池中 + usedConnections.add(connection); + return connection; + } + + @Override + public boolean releaseConnection(Connection connection) { + // 把这个连接放回数据库连接池 + connectionPool.add(connection); + // 从已经使用连接池中把这个连接移除掉 + return usedConnections.remove(connection); + } + + /** + * 数据库连接池总大小是剩下的➕已使用的 + * + * @param + * @return + * @date 2022/4/23 + */ + public int getSize() { + return connectionPool.size() + usedConnections.size(); + } + + @Override + public String getUrl() { + return null; + } + + @Override + public String getUser() { + return null; + } + + @Override + public String getPassword() { + return null; + } + + public BasicConnectionPool(String url, String user, String password, List connectionPool) { + this.url = url; + this.user = user; + this.password = password; + this.connectionPool = connectionPool; + + } + + +} diff --git a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/ConnectionPool.java b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/ConnectionPool.java new file mode 100644 index 00000000..b3badd55 --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/ConnectionPool.java @@ -0,0 +1,25 @@ +package top.jrl.homework.jdbc.connection; + +import java.sql.Connection; + +/** + * 自制数据库连接池 + * https://www.baeldung.com/java-connection-pooling + * + * @author jrl + * @date Create in 11:35 2022/4/23 + */ +public interface ConnectionPool { + Connection getConnection(); + + boolean releaseConnection(Connection connection); + + // DONE_Joly:数据库地址 + String getUrl(); + + // DONE_Joly:数据库用户名 + String getUser(); + + // DONE_Joly:数据库密码 + String getPassword(); +} diff --git a/04fx/jdbc/src/main/java/top/jrl/learn/transaction/TransactionApplication.java b/04fx/jdbc/src/main/java/top/jrl/learn/transaction/TransactionApplication.java new file mode 100644 index 00000000..86670f2d --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/learn/transaction/TransactionApplication.java @@ -0,0 +1,13 @@ +package top.jrl.learn.transaction; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TransactionApplication { + + public static void main(String[] args) { + SpringApplication.run(TransactionApplication.class, args); + } + +} diff --git a/04fx/jdbc/src/main/resources/application.properties b/04fx/jdbc/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/04fx/jdbc/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/04fx/jdbc/src/test/java/top/jrl/homework/jdbc/JdbcApplicationTests.java b/04fx/jdbc/src/test/java/top/jrl/homework/jdbc/JdbcApplicationTests.java new file mode 100644 index 00000000..9c4f9feb --- /dev/null +++ b/04fx/jdbc/src/test/java/top/jrl/homework/jdbc/JdbcApplicationTests.java @@ -0,0 +1,13 @@ +package top.jrl.homework.jdbc; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JdbcApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/04fx/jdbc/src/test/java/top/jrl/learn/transaction/TransactionApplicationTests.java b/04fx/jdbc/src/test/java/top/jrl/learn/transaction/TransactionApplicationTests.java new file mode 100644 index 00000000..a35080a9 --- /dev/null +++ b/04fx/jdbc/src/test/java/top/jrl/learn/transaction/TransactionApplicationTests.java @@ -0,0 +1,13 @@ +package top.jrl.learn.transaction; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class TransactionApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/04fx/my-starter/.gitignore b/04fx/my-starter/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/04fx/my-starter/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/04fx/my-starter/.mvn/wrapper/maven-wrapper.jar b/04fx/my-starter/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..c1dd12f1 Binary files /dev/null and b/04fx/my-starter/.mvn/wrapper/maven-wrapper.jar differ diff --git a/04fx/my-starter/.mvn/wrapper/maven-wrapper.properties b/04fx/my-starter/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..b7cb93e7 --- /dev/null +++ b/04fx/my-starter/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/04fx/my-starter/mvnw b/04fx/my-starter/mvnw new file mode 100644 index 00000000..8a8fb228 --- /dev/null +++ b/04fx/my-starter/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/04fx/my-starter/mvnw.cmd b/04fx/my-starter/mvnw.cmd new file mode 100644 index 00000000..1d8ab018 --- /dev/null +++ b/04fx/my-starter/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/04fx/my-starter/pom.xml b/04fx/my-starter/pom.xml new file mode 100644 index 00000000..cd654573 --- /dev/null +++ b/04fx/my-starter/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.6 + + + top.jrl.homework + my-starter + 0.0.1-SNAPSHOT + my-starter + 自定义一个starter + + 8 + + + + org.projectlombok + lombok + 1.18.12 + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/MyStarterApplication.java b/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/MyStarterApplication.java new file mode 100644 index 00000000..db36a334 --- /dev/null +++ b/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/MyStarterApplication.java @@ -0,0 +1,13 @@ +package top.jrl.homework.mystarter; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MyStarterApplication { + + public static void main(String[] args) { + SpringApplication.run(MyStarterApplication.class, args); + } + +} diff --git a/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokAutoConfigguration.java b/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokAutoConfigguration.java new file mode 100644 index 00000000..004ee320 --- /dev/null +++ b/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokAutoConfigguration.java @@ -0,0 +1,32 @@ +package top.jrl.homework.mystarter.config; + +import lombok.Lombok; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author jrl + * @date Create in 14:07 2022/4/19 + */ +@EnableConfigurationProperties(LombokPropertiesConfiguration.class) +@Configuration +@ConditionalOnClass(Lombok.class) +public class LombokAutoConfigguration { + @Autowired + LombokPropertiesConfiguration lombokPropertiesConfiguration; + + @Bean + @ConditionalOnMissingBean(Lombok.class) + @ConditionalOnProperty(name = "lombok.myproperties.enable", havingValue = "true", matchIfMissing = true) + public Lombok lombok() { + System.out.println("进行Lombok的自动配置"); + System.out.println("进行Lombok的自动配置"+lombokPropertiesConfiguration.a); + System.out.println("进行Lombok的自动配置"+lombokPropertiesConfiguration.getProperties()); + return new Lombok(); + } +} diff --git a/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokPropertiesConfiguration.java b/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokPropertiesConfiguration.java new file mode 100644 index 00000000..fa4a4e6c --- /dev/null +++ b/04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokPropertiesConfiguration.java @@ -0,0 +1,41 @@ +package top.jrl.homework.mystarter.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.Properties; + +/** + * @author jrl + * @date Create in 13:56 2022/4/19 + */ +@ConfigurationProperties(prefix = "lombok.myproperties") +public class LombokPropertiesConfiguration { + String a = "a-default"; + String b = "b-default"; + private Properties properties = new Properties(); + + public String getA() { + return a; + } + + public void setA(String a) { + this.a = a; + } + + public String getB() { + return b; + } + + public void setB(String b) { + this.b = b; + } + + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } +} diff --git a/04fx/my-starter/src/main/resources/META-INF/spring.factories b/04fx/my-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..c24937ca --- /dev/null +++ b/04fx/my-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +top/jrl/homework/mystarter/config/LombokAutoConfigguration \ No newline at end of file diff --git a/04fx/my-starter/src/main/resources/application.properties b/04fx/my-starter/src/main/resources/application.properties new file mode 100644 index 00000000..4b26f3d5 --- /dev/null +++ b/04fx/my-starter/src/main/resources/application.properties @@ -0,0 +1,3 @@ + +lombok.myproperties.a="aaa" +lombok.myproperties.b="bbb" \ No newline at end of file diff --git a/04fx/my-starter/src/test/java/top/jrl/homework/mystarter/MyStarterApplicationTests.java b/04fx/my-starter/src/test/java/top/jrl/homework/mystarter/MyStarterApplicationTests.java new file mode 100644 index 00000000..130ab422 --- /dev/null +++ b/04fx/my-starter/src/test/java/top/jrl/homework/mystarter/MyStarterApplicationTests.java @@ -0,0 +1,13 @@ +package top.jrl.homework.mystarter; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class MyStarterApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/04fx/spring01/README b/04fx/spring01/README new file mode 100644 index 00000000..f8f3d7f4 --- /dev/null +++ b/04fx/spring01/README @@ -0,0 +1,5 @@ +介绍Spring Framework. +没有引入Spring Boot,所以没有自动配置,都要自己手动的做. + + +Spring IOC\AOP\XML\JMS 演示 \ No newline at end of file diff --git a/04fx/spring01/pom.xml b/04fx/spring01/pom.xml index 505009a7..77e0e58f 100644 --- a/04fx/spring01/pom.xml +++ b/04fx/spring01/pom.xml @@ -3,16 +3,16 @@ 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"> 4.0.0 - + io.kimmking spring01 1.0 - + - - 4.3.29.RELEASE + 5.2.7.RELEASE + - + @@ -25,7 +25,7 @@ - + com.google.guava @@ -42,11 +42,11 @@ spring-core ${spring-version} - - - - - + + + + + org.springframework spring-beans @@ -87,11 +87,15 @@ spring-test ${spring-version} + org.springframework spring-messaging ${spring-version} + + org.springframework spring-jms @@ -102,7 +106,7 @@ spring-expression ${spring-version} - + com.alibaba fastjson @@ -151,18 +155,18 @@ 1.10.19 test - + org.apache.activemq activemq-client 5.15.0 - + - - - - + + + + diff --git a/04fx/spring01/src/main/java/io/kimmking/aop/ISchool.java b/04fx/spring01/src/main/java/io/kimmking/aop/ISchool.java index 3e9d8f1f..77d5b164 100644 --- a/04fx/spring01/src/main/java/io/kimmking/aop/ISchool.java +++ b/04fx/spring01/src/main/java/io/kimmking/aop/ISchool.java @@ -1,7 +1,16 @@ package io.kimmking.aop; +/** + * @author Joly + */ public interface ISchool { - + /** + * + * + * @param + * @return + * @date 2022/2/7 + */ void ding(); - + } diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/Main.java b/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/Main.java new file mode 100644 index 00000000..e54bbdc9 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/Main.java @@ -0,0 +1,9 @@ +package io.kimmking.jrl.annotation; + +/** + * @author jrl + * @date Create in 15:15 2022/4/15 + */ +@MyAnnotation(elementThree = "elementThreeValue") +public class Main { +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotation.java b/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotation.java new file mode 100644 index 00000000..03fccdda --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotation.java @@ -0,0 +1,22 @@ +package io.kimmking.jrl.annotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * @author jrl + * @date Create in 14:49 2022/4/15 + */ +@Target(ElementType.TYPE) +public @interface MyAnnotation { + String elementOne() default "elementOneValue"; + + String[] elementTwo() default { + + }; + + // ûdefaultĻʹøעʱͱָԪصֵ + String[] elementThree(); + +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotationImpl.java b/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotationImpl.java new file mode 100644 index 00000000..754ea0c0 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotationImpl.java @@ -0,0 +1,30 @@ +package io.kimmking.jrl.annotation; + +import java.lang.annotation.Annotation; + +/** + * @author jrl + * @date Create in 15:29 2022/4/15 + */ +public class MyAnnotationImpl implements MyAnnotation { + @Override + public String elementOne() { + return null; + } + + @Override + public String[] elementTwo() { + return new String[0]; + } + + @Override + public String[] elementThree() { + return new String[0]; + } + + /*Annotationӿ*/ + @Override + public Class annotationType() { + return this.getClass(); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/config/Configuration0.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/config/Configuration0.java new file mode 100644 index 00000000..00728704 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/config/Configuration0.java @@ -0,0 +1,30 @@ +package io.kimmking.jrl.homework.bean0.config; + +import io.kimmking.jrl.homework.bean0.pojo.HomeTeacher; +import io.kimmking.spring01.Student; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * beanע + * @author jrl + * @date Create in 17:30 2022/4/9 + */ +@Configuration +public class Configuration0 { + /** + * knowledge point: beanName ݷstudentFactory + */ + @Bean + Student studentFactory() { + return Student.create(); + } + + /** + * knowledge point: beanName ָ + */ + @Bean(name = "homeTeacher-config") + HomeTeacher homeTeacherFactory() { + return new HomeTeacher(); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/controller/HomeTeacherController.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/controller/HomeTeacherController.java new file mode 100644 index 00000000..abd5c53d --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/controller/HomeTeacherController.java @@ -0,0 +1,19 @@ +package io.kimmking.jrl.homework.bean0.controller; + +import io.kimmking.jrl.homework.bean0.pojo.HomeTeacher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author jrl + * @date Create in 14:22 2022/4/17 + */ +@Component +public class HomeTeacherController { + @Autowired + HomeTeacher homeTeacher; + + public void test() { + System.out.println(homeTeacher); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/Main0.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/Main0.java new file mode 100644 index 00000000..e877b14e --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/Main0.java @@ -0,0 +1,34 @@ +package io.kimmking.jrl.homework.bean0.main; + +import io.kimmking.jrl.homework.bean0.controller.HomeTeacherController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.ComponentScans; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author jrl + * @date Create in 17:39 2022/4/9 + */ + +@Configuration +public class Main0 { + + static HomeTeacherController homeTeacherController; + + @Autowired + public void setHomeTeacherController(HomeTeacherController homeTeacherController) { + Main0.homeTeacherController = homeTeacherController; + homeTeacherController.test(); + } + + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext4homework1.xml"); + String[] beanDefinitionNames = context.getBeanDefinitionNames(); + System.out.println(String.join(",", beanDefinitionNames)); + Main0.homeTeacherController.test(); + } + + +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/HomeTeacher.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/HomeTeacher.java new file mode 100644 index 00000000..225ac309 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/HomeTeacher.java @@ -0,0 +1,13 @@ +package io.kimmking.jrl.homework.bean0.pojo; + +import io.kimmking.spring01.Student; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author jrl + * @date Create in 17:11 2022/4/9 + */ +public class HomeTeacher { + + Student student; +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/SchoolTeacher.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/SchoolTeacher.java new file mode 100644 index 00000000..688e95bf --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/SchoolTeacher.java @@ -0,0 +1,17 @@ +package io.kimmking.jrl.homework.bean0.pojo; + +import io.kimmking.spring01.Student; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author jrl + * @date Create in 14:24 2022/4/9 + */ +@Component +@Data +public class SchoolTeacher { + @Autowired + Student favoriteStudent; +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/Base1.java b/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/Base1.java new file mode 100644 index 00000000..2f58425e --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/Base1.java @@ -0,0 +1,29 @@ +package io.kimmking.jrl.ioc0; + +import io.kimmking.jrl.ioc0.bean0.Home; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * ֤ڲbeanԭ--->ǵ + * + * @author jrl + * @date Create in 14:37 2023/1/24 + */ + +public class Base1 { + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext4jrlioc0.xml"); + Home home_friend = (Home) context.getBean("home_friend"); + Home home_friend2 = (Home) context.getBean("home_friend"); + //io.kimmking.jrl.ioc0.bean0.Relative@5f282abb + // io.kimmking.jrl.ioc0.bean0.Relative@5f282abb + // io.kimmking.jrl.ioc0.bean0.Home@167fdd33 + // io.kimmking.jrl.ioc0.bean0.Home@167fdd33 + System.out.println(home_friend.getRelativeOne()); + System.out.println(home_friend2.getRelativeOne()); + System.out.println(home_friend); + System.out.println(home_friend2); + + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Home.java b/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Home.java new file mode 100644 index 00000000..8fa67b3c --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Home.java @@ -0,0 +1,33 @@ +package io.kimmking.jrl.ioc0.bean0; + +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * + * + * @author jrl + * @date Create in 14:33 2023/1/24 + */ + +public class Home { + Relative relativeOne; + String name; + + public void setRelativeOne(Relative relativeOne) { + this.relativeOne = relativeOne; + } + + public void setName(String name) { + this.name = name; + } + + public Relative getRelativeOne() { + return relativeOne; + } + + public String getName() { + return name; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Relative.java b/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Relative.java new file mode 100644 index 00000000..8ff6d1a0 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Relative.java @@ -0,0 +1,27 @@ +package io.kimmking.jrl.ioc0.bean0; + +import org.springframework.stereotype.Component; + +/** + * + * + * @author jrl + * @date Create in 14:34 2023/1/24 + */ +public class Relative { + String name; + String gender; + Integer age; + + public void setName(String name) { + this.name = name; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public void setAge(Integer age) { + this.age = age; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/README.md b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/README.md new file mode 100644 index 00000000..550c26a5 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/README.md @@ -0,0 +1,9 @@ +## 相关学习 +### 代理模式 +#### 静态代理 +#### 动态代理 +##### JDK动态代理 +##### CGLIB动态代理 +### AOP的实现 +*** +## 作业 \ No newline at end of file diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/DebugInvocationHandler.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/DebugInvocationHandler.java new file mode 100644 index 00000000..ae085f02 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/DebugInvocationHandler.java @@ -0,0 +1,35 @@ +package io.kimmking.jrl.proxy.dynamic0; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * 这是对所有符合条件的方法的某一种增强 + * (所以实现了InvocationHandler的类就是真的去实现具体加强内容的类) + * + * @author jrl + * @date Create in 21:57 2022/4/7 + */ +public class DebugInvocationHandler implements InvocationHandler { + /** + * 被代理类实例 + */ + private final Object target; + + public DebugInvocationHandler(Object target) { + this.target = target; + } + /** + * 当代理对象(方法)被调用时,实际调用的方法是invoke() + * */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + //加强 + System.out.println("enhance before method send()"); + // 通过反射,调用被代理对象(精度是方法) + method.invoke(target, args); + //加强 + System.out.println("enhance after method send()"); + return null; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/JdkProxyFactory.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/JdkProxyFactory.java new file mode 100644 index 00000000..6cb26ba0 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/JdkProxyFactory.java @@ -0,0 +1,17 @@ +package io.kimmking.jrl.proxy.dynamic0; + +import java.lang.reflect.Proxy; + +/** + * @author jrl + * @date Create in 22:33 2022/4/7 + */ +public class JdkProxyFactory { + public static Object getProxy(Object target) { + /*利用JDK提供的Proxy,生成代理对象*/ + return Proxy.newProxyInstance( + target.getClass().getClassLoader(), + target.getClass().getInterfaces(), + new DebugInvocationHandler(target)); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/Main.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/Main.java new file mode 100644 index 00000000..22e6c9b9 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/Main.java @@ -0,0 +1,16 @@ +package io.kimmking.jrl.proxy.dynamic0; + +/** + * @author jrl + * @date Create in 22:37 2022/4/7 + */ +public class Main { + public static void main(String[] args) { + /*......这前面肯定会做一系列匹配,然后确定要对被代理类的某个方法进行加强*/ + /*获取代理类*/ + SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl()); + /*执行代理对象*/ + smsService.send("msg"); + /*......这个被代理类里的其他方法可以做别的加强,再创建一个代理类就好了,然后再执行代理对象*/ + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsService.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsService.java new file mode 100644 index 00000000..6f0daba9 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsService.java @@ -0,0 +1,17 @@ +package io.kimmking.jrl.proxy.dynamic0; + +/** + * 接口 + * @author jrl + * @date Create in 21:56 2022/4/7 + */ +public interface SmsService { + /** + * 将指定的信息进行处理后发送出去 + * + * @param message 指定的信息 + * @return 发送的信息 + * @date 2022/4/7 + */ + String send(String message); +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsServiceImpl.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsServiceImpl.java new file mode 100644 index 00000000..1f8b1615 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsServiceImpl.java @@ -0,0 +1,17 @@ +package io.kimmking.jrl.proxy.dynamic0; + + +/** + * 被代理类 + * + * @author jrl + * @date Create in 17:09 2022/4/7 + */ +public class SmsServiceImpl implements SmsService { + + @Override + public String send(String message) { + System.out.println("send message:" + message); + return message; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/AliService.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/AliService.java new file mode 100644 index 00000000..59d22acf --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/AliService.java @@ -0,0 +1,12 @@ +package io.kimmking.jrl.proxy.dynamic1; + +/** + * @author jrl + * @date Create in 23:11 2022/4/7 + */ +public class AliService { + public String send(String message) { + System.out.println("send message:" + message); + return message; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/CglibProxyFactory.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/CglibProxyFactory.java new file mode 100644 index 00000000..2a93784e --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/CglibProxyFactory.java @@ -0,0 +1,17 @@ +package io.kimmking.jrl.proxy.dynamic1; + +import org.springframework.cglib.proxy.Enhancer; + +/** + * @author jrl + * @date Create in 23:18 2022/4/7 + */ +public class CglibProxyFactory { + public static Object getProxy(Class target) { + Enhancer enhancer = new Enhancer(); + enhancer.setClassLoader(target.getClassLoader()); + enhancer.setSuperclass(target); + enhancer.setCallback(new DebugMethodInterceptor()); + return enhancer.create(); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/DebugMethodInterceptor.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/DebugMethodInterceptor.java new file mode 100644 index 00000000..04bb2beb --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/DebugMethodInterceptor.java @@ -0,0 +1,24 @@ +package io.kimmking.jrl.proxy.dynamic1; + + +import org.springframework.cglib.proxy.MethodInterceptor; +import org.springframework.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; + +/** + * @author jrl + * @date Create in 23:12 2022/4/7 + */ +public class DebugMethodInterceptor implements MethodInterceptor { + + @Override + public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { + //加强 + System.out.println("enhance before method send()"); + methodProxy.invokeSuper(o,objects); + //加强 + System.out.println("enhance after method send()"); + return null; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/Main.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/Main.java new file mode 100644 index 00000000..45c08563 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/Main.java @@ -0,0 +1,12 @@ +package io.kimmking.jrl.proxy.dynamic1; + +/** + * @author jrl + * @date Create in 23:20 2022/4/7 + */ +public class Main { + public static void main(String[] args) { + AliService aliService = (AliService) CglibProxyFactory.getProxy(AliService.class); + aliService.send("msg"); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/Main.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/Main.java new file mode 100644 index 00000000..4e337396 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/Main.java @@ -0,0 +1,12 @@ +package io.kimmking.jrl.proxy.static0; + +/** + * @author jrl + * @date Create in 21:14 2022/4/7 + */ +public class Main { + public static void main(String[] args) { + /*调用real Object 的时候就改成调用代理类对应的方法*/ + new SmsServiceProxy(new SmsServiceImpl()).send("msg"); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsService.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsService.java new file mode 100644 index 00000000..24ab0fe3 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsService.java @@ -0,0 +1,18 @@ +package io.kimmking.jrl.proxy.static0; + +/** + * 接口 + * + * @author jrl + * @date Create in 17:02 2022/4/7 + */ +public interface SmsService { + /** + * 将指定的信息进行处理后发送出去 + * + * @param message 指定的信息 + * @return 发送的信息 + * @date 2022/4/7 + */ + String send(String message); +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceImpl.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceImpl.java new file mode 100644 index 00000000..db466698 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceImpl.java @@ -0,0 +1,16 @@ +package io.kimmking.jrl.proxy.static0; + +/** + * 被代理类 + * + * @author jrl + * @date Create in 17:09 2022/4/7 + */ +public class SmsServiceImpl implements SmsService { + + @Override + public String send(String message) { + System.out.println("send message:" + message); + return message; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceProxy.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceProxy.java new file mode 100644 index 00000000..f3684234 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceProxy.java @@ -0,0 +1,24 @@ +package io.kimmking.jrl.proxy.static0; + +/** + * 代理类:对被代理类的方法做了加强 + * + * @author jrl + * @date Create in 17:11 2022/4/7 + */ +public class SmsServiceProxy implements SmsService { + + private final SmsService smsService; + + public SmsServiceProxy(SmsService smsService) { + this.smsService = smsService; + } + + @Override + public String send(String message) { + System.out.println("enhance before method send()"); + smsService.send(message); + System.out.println("enhance after method send()"); + return null; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/spring01/README b/04fx/spring01/src/main/java/io/kimmking/spring01/README new file mode 100644 index 00000000..459c4916 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/README @@ -0,0 +1 @@ +Spring AOP IOC \ No newline at end of file diff --git a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java index a2357bf6..996894bf 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -13,33 +13,101 @@ import java.io.Serializable; -@Data +/** + * pojo: + * 1.aop使用 + *

+ * 2.bean 生命周期: + * Aware: + * BeanNameAware + * ApplicationContextAware + * spring 负责对beanName和applicationContext这两个属性进行赋值(在构建Student bean的时候) + * + * @author jrl + * @date 2022/2/7 + */ + @AllArgsConstructor @NoArgsConstructor @ToString public class Student implements Serializable, BeanNameAware, ApplicationContextAware { + public Student(int id, String name) { + this.id = id; + this.name = name; + } private int id; private String name; - + /** + * knowledge point: BeanNameAware 用于在初始化Bean时将BeanName信息提供给该Bean应该是用反射实现的) + */ + // TODO_Joly:拿来有什么用? private String beanName; + /** + * knowledge point: ApplicationContextAware 用于在初始化Bean的时候将ApplicationContext提供给该Bean + */ private ApplicationContext applicationContext; - public void init(){ + @Override + public void setBeanName(String name) { + this.beanName = name; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + /** + * knowledge point: Bean 生命周期中的 初始化 中的 自定义init-method + */ + // TODO_Joly: + public void init() { System.out.println("hello..........."); } - - public static Student create(){ - return new Student(102,"KK102",null, null); + + + public static Student create() { + return new Student(101, "KK101", null, null); } + /** + * 输出beanName(是BeanNameAware给set进来的) + * 输出the names of all beans defined in this factory + * + * @param + * @return + * @date 2022/2/7 + */ public void print() { + System.out.println(this.name + "print()====>"); System.out.println(this.beanName); System.out.println(" context.getBeanDefinitionNames() ===>> " + String.join(",", applicationContext.getBeanDefinitionNames())); + } + public int getId() { + return id; } + public void setId(int id) { + this.id = id; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBeanName() { + return beanName; + } + + public ApplicationContext getApplicationContext() { + return applicationContext; + } } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java index fa919d39..8176fc8a 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java @@ -2,25 +2,42 @@ import org.aspectj.lang.ProceedingJoinPoint; +/** + * 应用spring aop: + * 方式一:XML + * 这个方式需要在XML中说明切点和切面在哪,然后在代码里写好切面 + * + * @author jrl + * @date 2022/2/6 + */ public class Aop1 { - - //前置通知 - public void startTransaction(){ - System.out.println(" ====>begin ding... "); //2 - } - - //后置通知 - public void commitTransaction(){ - System.out.println(" ====>finish ding... "); //4 - } - - //环绕通知 - public void around(ProceedingJoinPoint joinPoint) throws Throwable{ - System.out.println(" ====>around begin ding"); //1 - //调用process()方法才会真正的执行实际被代理的方法 - joinPoint.proceed(); - - System.out.println(" ====>around finish ding"); //3 - } - + + //前置通知 + public void startTransaction() { + System.out.println(" ====>begin ding... "); //2 + } + + //后置通知 + public void commitTransaction() { + System.out.println(" ====>finish ding... "); //4 + } + + /** + * knowledge point: + * 环绕通知执行优先级高于前置通知和后置通知, + * 在环绕通知中 joinPoint.proceed()必需要写,不然就不会调用原始类的方法了。 + */ + //环绕通知 + public void around(ProceedingJoinPoint joinPoint) throws Throwable { + System.out.println(" ====>around begin ding"); //1 + /** knowledge point: + * 调用process()方法才会真正的执行实际被代理的方法 + * 如果用了环绕通知,那么就需要显示的去调用原始类的方法,否则就会不执行原始类的方法。 + * 如果没有用环绕通知,那么就会自动的去调用原始类的方法。 + */ + joinPoint.proceed(); + + System.out.println(" ====>around finish ding"); //3 + } + } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java index 4edbe006..2f9380bc 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java @@ -8,30 +8,49 @@ import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; +/** + * spring aop: + * ʽʹעķʽ + * Aspectעһaop + * + * @author jrl + * @date 2022/2/6 + */ @Aspect public class Aop2 { - - @Pointcut(value="execution(* io.kimmking.*.Klass.*dong(..))") - public void point(){ - + + /** + * knowledge point: + * ˵еЩ + */ + @Pointcut(value = "execution(* io.kimmking.*.Klass.*dong(..))") + public void point() { + } - - @Before(value="point()") - public void before(){ + + /** + * knowledge point: + * Ҫ˵Ӧĸе + */ + @Before(value = "point()") + public void before() { System.out.println("========>begin klass dong... //2"); } - + @AfterReturning(value = "point()") - public void after(){ + public void after() { System.out.println("========>after klass dong... //4"); } - + @Around("point()") - public void around(ProceedingJoinPoint joinPoint) throws Throwable{ + public void around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("========>around begin klass dong //1"); + /** knowledge point: + * ԭʼӦķ + */ joinPoint.proceed(); System.out.println("========>around after klass dong //3"); - + } - + } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java index d6433bd6..0e95da12 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java @@ -8,22 +8,39 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.stereotype.Component; +/** + * knowledge point: + */ @Component public class HelloBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - System.out.println(" ==> postProcessBeanDefinitionRegistry: "+registry.getBeanDefinitionCount()); - System.out.println(" ==> postProcessBeanDefinitionRegistry: "+String.join(",",registry.getBeanDefinitionNames())); + /*ʼָbean*/ + System.out.println(" ==> postProcessBeanDefinitionRegistry: " + registry.getBeanDefinitionCount()); + System.out.println(" ==> postProcessBeanDefinitionRegistry: " + String.join(",", registry.getBeanDefinitionNames())); RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class); rootBeanDefinition.getPropertyValues().add("id", 101); rootBeanDefinition.getPropertyValues().add("name", "KK101"); + /*зָbean*/ registry.registerBeanDefinition("s101", rootBeanDefinition); + RootBeanDefinition rootBeanDefinition2 = new RootBeanDefinition(Student.class); + rootBeanDefinition2.getPropertyValues().add("id", 1125); + rootBeanDefinition2.getPropertyValues().add("name", "KK1125"); + registry.registerBeanDefinition("s1125", rootBeanDefinition2); + + RootBeanDefinition rootBeanDefinition3 = new RootBeanDefinition(Student.class); + rootBeanDefinition3.getPropertyValues().add("id", 112500); + rootBeanDefinition3.getPropertyValues().add("name", "KK112500"); + /*xmlļȼأͿԸxmlеݸ*/ + registry.registerBeanDefinition("student100", rootBeanDefinition3); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - System.out.println(" ==> postProcessBeanFactory: "+beanFactory.getBeanDefinitionCount()); - System.out.println(" ==> postProcessBeanFactory: "+String.join(",",beanFactory.getBeanDefinitionNames())); + System.out.println(" ==> postProcessBeanFactory: " + beanFactory.getBeanDefinitionCount()); + System.out.println(" ==> postProcessBeanFactory: " + String.join(",", beanFactory.getBeanDefinitionNames())); + /*õ*/ + // TODO_Joly:ûŽȥ beanFactory.registerSingleton("s102", Student.create()); } } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanPostProcessor.java b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanPostProcessor.java index 451c829b..85a66623 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanPostProcessor.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanPostProcessor.java @@ -5,11 +5,17 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; +/** + * knowledge point: + * 1.用于Spring Bean 的生命周期中的初始化阶段,可以统一的在bean核心初始化的前后进行初始化处理。 + * (会对每一个bean都进行执行这个接口的实现。) + * 2.要把实现了BeanPostProcessor的类加载到上下文中才生效(Component注解) + */ @Component public class HelloBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - System.out.println(" ====> postProcessBeforeInitialization " + beanName +":"+ bean); + System.out.println(" ====> postProcessBeforeInitialization " + beanName + ":" + bean); // 可以加点额外处理 // 例如 if (bean instanceof Student) { @@ -21,7 +27,7 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - System.out.println(" ====> postProcessAfterInitialization " + beanName +":"+ bean); + System.out.println(" ====> postProcessAfterInitialization " + beanName + ":" + bean); return bean; } } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java b/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java index 65268a7a..221c2d6e 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java @@ -5,13 +5,26 @@ import java.util.List; +/** + * 1.ʾAOP + * ûʵֽӿڣSpringĬʹCGLibʵAOP + * + * @author Joly + */ @Data -public class Klass { - +public class Klass { + List students; - - public void dong(){ + + /** + * + * + * @param + * @return + * @date 2022/2/7 + */ + public void dong() { System.out.println(this.getStudents()); } - + } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/README b/04fx/spring01/src/main/java/io/kimmking/spring02/README new file mode 100644 index 00000000..459c4916 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/README @@ -0,0 +1 @@ +Spring AOP IOC \ No newline at end of file diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/School.java b/04fx/spring01/src/main/java/io/kimmking/spring02/School.java index 7c700e64..57d9af76 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/School.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/School.java @@ -7,21 +7,34 @@ import javax.annotation.Resource; +/** + * ʾAOP + * ʵ˽ӿڣSpringĬʹJdkProxyʵAOP + * @author Joly + */ @Data public class School implements ISchool { - + /** + * knowledge point: + * springעķʽ + * 1.Autowiredע⣺Ĭϸע + * requiredڱʾöAǷʱͰע뵽BУ + * ǵõAʱҲõAķԵʱٰAעȥBҲأ + * Ĭtruetrueһע + * 2.Resourceע⣺Ĭϸע + */ // Resource @Autowired(required = true) //primary - Klass class1; - + Klass class1; + @Resource(name = "student100") Student student100; - + @Override - public void ding(){ - + public void ding() { + System.out.println("Class1 have " + this.class1.getStudents().size() + " students and one is " + this.student100); - + } - + } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java index a6263369..4acbe95b 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java @@ -5,46 +5,67 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +/** + * 1.演示:AOP + * 2.演示:Bean + * 2.1 向context中放入bean + * 方式一:xml配置文件() + * 方式二:注解(Component注解,Controller、Service、Repository等注解) + * 2.2 获取bean + * 方式一:根据xml中的bean的id获取 + * 方式二:根据xml或者注解方法注入的bean的类名获取 + * @author jrl + * @date 2022/4/6 + */ public class SpringDemo01 { - public static void main(String[] args) { - + /** knowledge point: + * spring加载xml配置文件,生成context和启动相关配置 + */ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); + // Student student123 = context.getBean(Student.class); - + /** knowledge point: + * spring 根据 XML配置文件中的bean的id获取bean + */ Student student123 = (Student) context.getBean("student123"); System.out.println(student123.toString()); student123.print(); - + Student student100 = (Student) context.getBean("student100"); - System.out.println(student100.toString()); + // println本来就要调用toString的--->对,没错,下面两行输出的内容式一样的 + System.out.println("student100.toString()====>" + student100.toString()); + System.out.println("student100 ====>" + student100); student100.print(); - Klass class1 = context.getBean(Klass.class); System.out.println(class1); - System.out.println("Klass对象AOP代理后的实际类型:"+class1.getClass()); - System.out.println("Klass对象AOP代理后的实际类型是否是Klass子类:"+(class1 instanceof Klass)); - + System.out.println("Klass对象AOP代理后的实际类型:" + class1.getClass()); + System.out.println("Klass对象AOP代理后的实际类型是否是Klass子类:" + (class1 instanceof Klass)); + ISchool school = context.getBean(ISchool.class); System.out.println(school); - System.out.println("ISchool接口的对象AOP代理后的实际类型:"+school.getClass()); - + System.out.println("ISchool接口的对象AOP代理后的实际类型:" + school.getClass()); + // DONE_Joly:此为何意 ---> 说明这接口拿到的实现对象是同一个代理对象 ISchool school1 = context.getBean(ISchool.class); System.out.println(school1); - System.out.println("ISchool接口的对象AOP代理后的实际类型:"+school1.getClass()); - + System.out.println("ISchool接口的对象AOP代理后的实际类型:" + school1.getClass()); + school1.ding(); - - class1.dong(); - - System.out.println(" context.getBeanDefinitionNames() ===>> "+ String.join(",", context.getBeanDefinitionNames())); + + class1.dong(); + + System.out.println(" context.getBeanDefinitionNames() ===>> " + String.join(",", context.getBeanDefinitionNames())); Student s101 = (Student) context.getBean("s101"); if (s101 != null) { System.out.println(s101); } + Student s1125 = (Student) context.getBean("s1125"); + if (s1125 != null) { + System.out.println(s1125); + } Student s102 = (Student) context.getBean("s102"); if (s102 != null) { System.out.println(s102); diff --git a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsListener.java b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsListener.java index 7518e6e2..e22f4ba2 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsListener.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsListener.java @@ -7,15 +7,22 @@ import javax.jms.MessageListener; import javax.jms.ObjectMessage; +/** + * 监听器 + * + * @author jrl + * @date 2022/2/11 + */ @Component(value = "jmsListener") public class JmsListener implements MessageListener { - + //收到信息时的动作 @Override - public void onMessage(Message m) { + public void onMessage(Message m) { ObjectMessage message = (ObjectMessage) m; try { - System.out.println("收到的信息:" + message.getObject()); + /* 业务处理:可以在这里调用业务处理方法*/ + System.out.println("收到的信息receive message:" + message.getObject()); } catch (JMSException e) { e.printStackTrace(); } diff --git a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsReceiver.java b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsReceiver.java index 1373b66f..22ed0c9c 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsReceiver.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsReceiver.java @@ -7,14 +7,16 @@ import java.io.IOException; public class JmsReceiver { - - public static void main( String[] args ) throws IOException { - - ApplicationContext context = new ClassPathXmlApplicationContext("classpath:springjms-receiver.xml"); - + + public static void main(String[] args) throws IOException { + /* + * 拉起配置文件 加不加classpath:都可以 (classpath:springjms-receiver.xml) + * */ + ApplicationContext context = new ClassPathXmlApplicationContext("springjms-receiver.xml"); + // TODO_Joly:这么写的目的只是为了不让程序挂掉,为了能够接收到消息是吗 System.in.read(); - + System.out.println("send successfully, please visit http://localhost:8161/admin to see it"); } - + } diff --git a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java index 2b1e72f3..ab69c4b5 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java @@ -5,18 +5,17 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class JmsSender { - - public static void main( String[] args ) - { + + public static void main(String[] args) { Student student2 = Student.create(); - + // 拉起配置文件 加不加classpath:都可以 ApplicationContext context = new ClassPathXmlApplicationContext("classpath:springjms-sender.xml"); - - SendService sendService = (SendService)context.getBean("sendService"); - + // 调用jmsTemplate + SendService sendService = (SendService) context.getBean("sendService"); + sendService.send(student2); - - System.out.println("send successfully, please visit http://localhost:8161/admin to see it"); + // DONE_Joly: http://localhost:8161/admin 8161是什么--->是activemq的访问地址 + System.out.println("send successfully, please visit http://47.115.148.27:8161/admin to see it"); } - + } diff --git a/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java b/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java index 15bafce1..1136cbd5 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java @@ -11,15 +11,23 @@ import javax.jms.Message; import javax.jms.Session; +/** + * 使用JMSTemplate来发送消息 + * + * @author jrl + * @date 2022/2/11 + */ @Component public class SendService { + @Autowired JmsTemplate jmsTemplate; - + // TODO_Joly:final? public void send(final Student user) { jmsTemplate.send("test.queue", new MessageCreator() { - + // TODO_Joly:为什么这里要限定Session(Java程序和JMS服务间的Session) public Message createMessage(Session session) throws JMSException { + // 把user序列化成json格式 return session.createObjectMessage(JSON.toJSONString(user)); } }); diff --git a/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java b/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java new file mode 100644 index 00000000..97f9218c --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java @@ -0,0 +1,36 @@ +package io.kimmking.utilsJ; + +/** + * @author jrl + * @date Create in 10:51 2021-11-24 + */ +public class Person { + int age; + String name; + + public Person(int age, String name) { + this.age = age; + this.name = name; + } + + public Person(int age) { + this.age = age; + + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java b/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java new file mode 100644 index 00000000..7e4718ac --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java @@ -0,0 +1,33 @@ +package io.kimmking.utilsJ; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +/** + * knowledge point: + * 可以将对象转为json形式的字符串, + * 也可以将json形式的字符串转为map形式的对象(也可以通过传Class对象,转成对应的类型) + */ + +/** + * @author jrl + * @date Create in 18:47 2021-11-23 + */ +public class fastjson { + public static void main(String[] args) { + //将json形式的字符串转为map形式的对象 + JSONObject jsonObject = JSON.parseObject("{\"age\":11,\"name\":\"mona\"}"); + //(也可以通过传Class对象,转成对应的类型) + Person person = JSON.parseObject("{\"age\":11,\"name\":\"mona\"}", Person.class); + System.out.println(jsonObject); + Object name = jsonObject.get("name"); + System.out.println(name); + System.out.println(person.getAge()); + Person p = new Person(11, "mona"); + //将对象转为json形式的字符串 + String s = JSON.toJSONString(p); + System.out.println(s); + //如果java对象的属性没有赋值,则输出的json字符串对应的属性直接不展示 + Person p1 = new Person(12); + System.out.println(JSON.toJSONString(p1)); + } +} diff --git a/04fx/spring01/src/main/resources/applicationContext.xml b/04fx/spring01/src/main/resources/applicationContext.xml index 681cf409..b5fc09ba 100644 --- a/04fx/spring01/src/main/resources/applicationContext.xml +++ b/04fx/spring01/src/main/resources/applicationContext.xml @@ -1,4 +1,17 @@ - + + + - + http://www.springframework.org/schema/context/spring-context-3.2.xsd + http://www.springframework.org/schema/aop + https://www.springframework.org/schema/aop/spring-aop.xsd"> + - - + + - - - + + - + - - - - - - + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + + - - + + + + + - - - - - + + + + + \ No newline at end of file diff --git a/04fx/spring01/src/main/resources/applicationContext4homework1.xml b/04fx/spring01/src/main/resources/applicationContext4homework1.xml new file mode 100644 index 00000000..90edc762 --- /dev/null +++ b/04fx/spring01/src/main/resources/applicationContext4homework1.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/04fx/spring01/src/main/resources/applicationContext4jrlioc0.xml b/04fx/spring01/src/main/resources/applicationContext4jrlioc0.xml new file mode 100644 index 00000000..34201ea7 --- /dev/null +++ b/04fx/spring01/src/main/resources/applicationContext4jrlioc0.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/04fx/spring01/src/main/resources/springjms-receiver.xml b/04fx/spring01/src/main/resources/springjms-receiver.xml index e0d9fbc6..46d32144 100644 --- a/04fx/spring01/src/main/resources/springjms-receiver.xml +++ b/04fx/spring01/src/main/resources/springjms-receiver.xml @@ -1,4 +1,5 @@ + - + - + - - + + - + - + - + - + - + + + + + - + \ No newline at end of file diff --git a/04fx/spring01/src/main/resources/springjms-sender.xml b/04fx/spring01/src/main/resources/springjms-sender.xml index 119ec07a..68cf6c4b 100644 --- a/04fx/spring01/src/main/resources/springjms-sender.xml +++ b/04fx/spring01/src/main/resources/springjms-sender.xml @@ -1,4 +1,5 @@ + - + - + - + - + diff --git a/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java b/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java index 0cfd0cb6..fd7bd105 100644 --- a/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java +++ b/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java @@ -11,8 +11,8 @@ //@EnableMongoRepositories public class Springboot01Application { - public static void main(String[] args) { - SpringApplication.run(Springboot01Application.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Springboot01Application.class, args); + } } diff --git a/04fx/starter-test/.gitignore b/04fx/starter-test/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/04fx/starter-test/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/04fx/starter-test/.mvn/wrapper/maven-wrapper.jar b/04fx/starter-test/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..c1dd12f1 Binary files /dev/null and b/04fx/starter-test/.mvn/wrapper/maven-wrapper.jar differ diff --git a/04fx/starter-test/.mvn/wrapper/maven-wrapper.properties b/04fx/starter-test/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..b7cb93e7 --- /dev/null +++ b/04fx/starter-test/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/04fx/starter-test/mvnw b/04fx/starter-test/mvnw new file mode 100644 index 00000000..8a8fb228 --- /dev/null +++ b/04fx/starter-test/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/04fx/starter-test/mvnw.cmd b/04fx/starter-test/mvnw.cmd new file mode 100644 index 00000000..1d8ab018 --- /dev/null +++ b/04fx/starter-test/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/04fx/starter-test/pom.xml b/04fx/starter-test/pom.xml new file mode 100644 index 00000000..6b78b6b7 --- /dev/null +++ b/04fx/starter-test/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.6 + + + top.jrl.homework + starter-test + 0.0.1-SNAPSHOT + starter-test + 对 my-starter 进行检测 + + 8 + + + + top.jrl.homework + my-starter + 0.0.1-SNAPSHOT + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/04fx/starter-test/src/main/java/top/jrl/homework/startertest/StarterTestApplication.java b/04fx/starter-test/src/main/java/top/jrl/homework/startertest/StarterTestApplication.java new file mode 100644 index 00000000..abfb86f1 --- /dev/null +++ b/04fx/starter-test/src/main/java/top/jrl/homework/startertest/StarterTestApplication.java @@ -0,0 +1,24 @@ +package top.jrl.homework.startertest; + +import lombok.Lombok; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class StarterTestApplication implements ApplicationRunner { + @Autowired + Lombok lombok; + + public static void main(String[] args) { + SpringApplication.run(StarterTestApplication.class, args); + } + + + @Override + public void run(ApplicationArguments args) throws Exception { + System.out.println(lombok); + } +} diff --git a/04fx/starter-test/src/main/resources/application.properties b/04fx/starter-test/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/04fx/starter-test/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/04fx/starter-test/src/test/java/top/jrl/homework/startertest/StarterTestApplicationTests.java b/04fx/starter-test/src/test/java/top/jrl/homework/startertest/StarterTestApplicationTests.java new file mode 100644 index 00000000..518af994 --- /dev/null +++ b/04fx/starter-test/src/test/java/top/jrl/homework/startertest/StarterTestApplicationTests.java @@ -0,0 +1,13 @@ +package top.jrl.homework.startertest; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class StarterTestApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/07rpc/dubbo/.gitignore b/07rpc/dubbo/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/07rpc/dubbo/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/07rpc/dubbo/.mvn/wrapper/maven-wrapper.jar b/07rpc/dubbo/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..c1dd12f1 Binary files /dev/null and b/07rpc/dubbo/.mvn/wrapper/maven-wrapper.jar differ diff --git a/07rpc/dubbo/.mvn/wrapper/maven-wrapper.properties b/07rpc/dubbo/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..22f219d2 --- /dev/null +++ b/07rpc/dubbo/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/07rpc/dubbo/README.md b/07rpc/dubbo/README.md new file mode 100644 index 00000000..c041dd8b --- /dev/null +++ b/07rpc/dubbo/README.md @@ -0,0 +1,2 @@ +# 项目说明 +1. 我用来学习Dubbo的 \ No newline at end of file diff --git a/07rpc/dubbo/mvnw b/07rpc/dubbo/mvnw new file mode 100644 index 00000000..8a8fb228 --- /dev/null +++ b/07rpc/dubbo/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/07rpc/dubbo/mvnw.cmd b/07rpc/dubbo/mvnw.cmd new file mode 100644 index 00000000..1d8ab018 --- /dev/null +++ b/07rpc/dubbo/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/07rpc/dubbo/pom.xml b/07rpc/dubbo/pom.xml new file mode 100644 index 00000000..634f3d47 --- /dev/null +++ b/07rpc/dubbo/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.1 + + + top.jrl.learm + dubbo + 0.0.1-SNAPSHOT + dubbo + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.dubbo + dubbo-spring-boot-starter + 2.7.8 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/DubboApplication.java b/07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/DubboApplication.java new file mode 100644 index 00000000..45e4d7db --- /dev/null +++ b/07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/DubboApplication.java @@ -0,0 +1,13 @@ +package top.jrl.learm.dubbo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DubboApplication { + + public static void main(String[] args) { + SpringApplication.run(DubboApplication.class, args); + } + +} diff --git a/07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/basic/Generic.java b/07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/basic/Generic.java new file mode 100644 index 00000000..bd5c2ed4 --- /dev/null +++ b/07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/basic/Generic.java @@ -0,0 +1,17 @@ +package top.jrl.learm.dubbo.basic; + +import org.apache.dubbo.config.ReferenceConfig; +import org.apache.dubbo.rpc.service.GenericService; + +/** + * @author jrl + * @date Create in 18:58 2022/6/24 + */ +public class Generic { + public static void main(String[] args) { + ReferenceConfig reference = new ReferenceConfig<>(); + GenericService genericService = reference.get(); + // genericService.$invoke() + + } +} diff --git a/07rpc/dubbo/src/main/resources/application.properties b/07rpc/dubbo/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/07rpc/dubbo/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/07rpc/dubbo/src/test/java/top/jrl/learm/dubbo/DubboApplicationTests.java b/07rpc/dubbo/src/test/java/top/jrl/learm/dubbo/DubboApplicationTests.java new file mode 100644 index 00000000..1fa621d6 --- /dev/null +++ b/07rpc/dubbo/src/test/java/top/jrl/learm/dubbo/DubboApplicationTests.java @@ -0,0 +1,13 @@ +package top.jrl.learm.dubbo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DubboApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/07rpc/rpc/.gitignore b/07rpc/rpc/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/07rpc/rpc/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/07rpc/rpc/.mvn/wrapper/maven-wrapper.jar b/07rpc/rpc/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..c1dd12f1 Binary files /dev/null and b/07rpc/rpc/.mvn/wrapper/maven-wrapper.jar differ diff --git a/07rpc/rpc/.mvn/wrapper/maven-wrapper.properties b/07rpc/rpc/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..22f219d2 --- /dev/null +++ b/07rpc/rpc/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/07rpc/rpc/README.md b/07rpc/rpc/README.md new file mode 100644 index 00000000..bc4466c6 --- /dev/null +++ b/07rpc/rpc/README.md @@ -0,0 +1,4 @@ +# 学习RPC时,Joly创建的练习模块 + +# 内容 +1. InterfaceA、ClassA、ClassA2、ServiceLoader1、META-INF用于联系ServiceLoader的使用,ServiceLoader是JDK对SPI的实现 \ No newline at end of file diff --git a/07rpc/rpc/mvnw b/07rpc/rpc/mvnw new file mode 100644 index 00000000..8a8fb228 --- /dev/null +++ b/07rpc/rpc/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/07rpc/rpc/mvnw.cmd b/07rpc/rpc/mvnw.cmd new file mode 100644 index 00000000..1d8ab018 --- /dev/null +++ b/07rpc/rpc/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/07rpc/rpc/pom.xml b/07rpc/rpc/pom.xml new file mode 100644 index 00000000..d67d7594 --- /dev/null +++ b/07rpc/rpc/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.0 + + + top.jrl.lean + rpc + 0.0.1-SNAPSHOT + rpc + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/07rpc/rpc/src/main/java/top/jrl/lean/rpc/RpcApplication.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/RpcApplication.java new file mode 100644 index 00000000..13f6e3ce --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/RpcApplication.java @@ -0,0 +1,13 @@ +package top.jrl.lean.rpc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RpcApplication { + + public static void main(String[] args) { + SpringApplication.run(RpcApplication.class, args); + } + +} diff --git a/07rpc/rpc/src/main/java/top/jrl/lean/rpc/generic/Generic1.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/generic/Generic1.java new file mode 100644 index 00000000..a0da17a4 --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/generic/Generic1.java @@ -0,0 +1,11 @@ +package top.jrl.lean.rpc.generic; + +/** + * @author jrl + * @date Create in 18:52 2022/6/24 + */ +public class Generic1 { + public static void main(String[] args) { + + } +} diff --git a/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA.java new file mode 100644 index 00000000..4128de3d --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA.java @@ -0,0 +1,13 @@ +package top.jrl.lean.rpc.syntac; + +/** + * @author jrl + * @date Create in 22:42 2022/6/23 + */ +public class ClassA implements InterfaceA { + @Override + public String sayHello() { + System.out.println("Hi"); + return "hello"; + } +} diff --git a/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA2.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA2.java new file mode 100644 index 00000000..b95f6357 --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA2.java @@ -0,0 +1,13 @@ +package top.jrl.lean.rpc.syntac; + +/** + * @author jrl + * @date Create in 22:42 2022/6/23 + */ +public class ClassA2 implements InterfaceA { + @Override + public String sayHello() { + System.out.println("Hi2"); + return "hello2"; + } +} diff --git a/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/InterfaceA.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/InterfaceA.java new file mode 100644 index 00000000..21d71a20 --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/InterfaceA.java @@ -0,0 +1,9 @@ +package top.jrl.lean.rpc.syntac; + +/** + * @author jrl + * @date Create in 22:40 2022/6/23 + */ +public interface InterfaceA { + String sayHello(); +} diff --git a/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/Reflec.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/Reflec.java new file mode 100644 index 00000000..70f11b53 --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/Reflec.java @@ -0,0 +1,11 @@ +package top.jrl.lean.rpc.syntac; + +/** + * @author jrl + * @date Create in 12:40 2022/6/14 + */ +public class Reflec { + public static void main(String[] args) throws IllegalAccessException, InstantiationException { + System.out.println(); + } +} diff --git a/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ServiceLoader1.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ServiceLoader1.java new file mode 100644 index 00000000..e2caea3b --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ServiceLoader1.java @@ -0,0 +1,16 @@ +package top.jrl.lean.rpc.syntac; + +import java.util.ServiceLoader; + +/** + * @author jrl + * @date Create in 16:36 2022/6/24 + */ +public class ServiceLoader1 { + public static void main(String[] args) { + ServiceLoader load = ServiceLoader.load(InterfaceA.class); + for (InterfaceA a : load) { + a.sayHello(); + } + } +} diff --git a/07rpc/rpc/src/main/resources/META-INF/services/top.jrl.lean.rpc.syntac.InterfaceA b/07rpc/rpc/src/main/resources/META-INF/services/top.jrl.lean.rpc.syntac.InterfaceA new file mode 100644 index 00000000..056d12f0 --- /dev/null +++ b/07rpc/rpc/src/main/resources/META-INF/services/top.jrl.lean.rpc.syntac.InterfaceA @@ -0,0 +1,2 @@ +top.jrl.lean.rpc.syntac.ClassA +top.jrl.lean.rpc.syntac.ClassA2 \ No newline at end of file diff --git a/07rpc/rpc/src/main/resources/application.properties b/07rpc/rpc/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/07rpc/rpc/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/07rpc/rpc/src/test/java/top/jrl/lean/rpc/RpcApplicationTests.java b/07rpc/rpc/src/test/java/top/jrl/lean/rpc/RpcApplicationTests.java new file mode 100644 index 00000000..a4b9d580 --- /dev/null +++ b/07rpc/rpc/src/test/java/top/jrl/lean/rpc/RpcApplicationTests.java @@ -0,0 +1,13 @@ +package top.jrl.lean.rpc; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RpcApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/07rpc/rpc01/README.md b/07rpc/rpc01/README.md new file mode 100644 index 00000000..ef9ee1ec --- /dev/null +++ b/07rpc/rpc01/README.md @@ -0,0 +1,15 @@ +#项目说明 +1. 自己实现一个基础的RPC框架 +2. 学习这个项目可以很好的理解到RPC的一些概念,建议自己动手再实现一次,直接记住得了 +# 项目内容 +1. rpcfx-core +* 是核心的框架代码 +2. rpcfx-demo-api +* 用于说明接口定义和接口参数及返回值的定义 +* 这里采用了共享接口的方式 +3. rpcfx-cunsumer +* 服务消费者 +4. rpcfx-provider +* 服务提供者 +# 项目实现 +1. 采用SpringBoot作为脚手架 \ No newline at end of file diff --git a/07rpc/rpc01/rpcfx-core/README.md b/07rpc/rpc01/rpcfx-core/README.md new file mode 100644 index 00000000..b1968d83 --- /dev/null +++ b/07rpc/rpc01/rpcfx-core/README.md @@ -0,0 +1,14 @@ +# 介绍 +RPC的核心部分,用于实现RPC的功能。其他模块是用于使用RPC功能的(通过引入core)。 +# 内容 +## 功能 +1. 可以给服务端注册服务(每个方法都是一个服务) + 1. A服务对应a名称 +2. 可以给客户端生成stub,这个stub对应了客户端想要调用的服务端的某个服务 + 1. 客户端和服务端需要根据定义好的服务描述方式来进行服务的定义,从而可以让客户端准确的选择到想要的服务 +3. 可以让客户端和服务端的网络通信不被用户感知,宛如是进行的本地调用 + 1. 网络协议 + 2. 序列化、反序列化方式 +## 代码实现 +### 架构设计 +1. \ No newline at end of file diff --git a/07rpc/rpc01/rpcfx-core/pom.xml b/07rpc/rpc01/rpcfx-core/pom.xml index 4570a59d..a074788c 100644 --- a/07rpc/rpc01/rpcfx-core/pom.xml +++ b/07rpc/rpc01/rpcfx-core/pom.xml @@ -29,7 +29,7 @@ lombok 1.18.16 - + com.squareup.okhttp3 okhttp diff --git a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxRequest.java b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxRequest.java index 5ee7b9e1..b2ee0d76 100644 --- a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxRequest.java +++ b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxRequest.java @@ -1,9 +1,14 @@ package io.kimmking.rpcfx.api; import lombok.Data; - +/** + * 请求:封装了服务消费者要消费的服务消费者的服务的描述信息(类名、方法名、参数) + * @author Joly + * @date 2022/6/22 + */ @Data public class RpcfxRequest { + // 因为用的是 共享API的方式来 定义的服务描述信息,所以知道是哪个类 private String serviceClass; private String method; private Object[] params; diff --git a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxResponse.java b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxResponse.java index b37747ad..913ad758 100644 --- a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxResponse.java +++ b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxResponse.java @@ -1,10 +1,17 @@ package io.kimmking.rpcfx.api; import lombok.Data; - +/** + * 响应:封装了服务提供者的服务的响应信息 + * @author Joly + * @date 2022/6/22 + */ @Data public class RpcfxResponse { + // 返回的结果数据 private Object result; + // 成功与否的状态 private boolean status; + // 异常 private Exception exception; } diff --git a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java index 5d1ae517..e0aa5e9b 100644 --- a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java +++ b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java @@ -16,12 +16,25 @@ import java.util.ArrayList; import java.util.List; +/** + * 客户端会调用的代码 + * + * @author Joly + * @date 2022/6/22 + */ public final class Rpcfx { static { ParserConfig.getGlobalInstance().addAccept("io.kimmking"); } + /** + * 有了注册中心的代理,会在基础RPC之上添加一些功能 + * + * @param + * @return + * @date 2022/6/23 + */ public static T createFromRegistry(final Class serviceClass, final String zkUrl, Router router, LoadBalancer loadBalance, Filter filter) { // 加filte之一 @@ -39,6 +52,13 @@ public static T createFromRegistry(final Class serviceClass, fin } + /** + * 单纯的代理,简单的实现RPC + * + * @param + * @return + * @date 2022/6/23 + */ public static T create(final Class serviceClass, final String url, Filter... filters) { // 0. 替换动态代理 -> 字节码生成 @@ -46,6 +66,12 @@ public static T create(final Class serviceClass, final String url, Filter } + /** + * 实现服务消费者对服务提供者某个服务的调用 + * + * @author Joly + * @date 2022/6/22 + */ public static class RpcfxInvocationHandler implements InvocationHandler { public static final MediaType JSONTYPE = MediaType.get("application/json; charset=utf-8"); @@ -64,6 +90,13 @@ public RpcfxInvocationHandler(Class serviceClass, String url, Filter... f // int byte char float double long bool // [], data class + /** + * 代理后,会替换原方法的执行 + * + * @param + * @return + * @date 2022/6/22 + */ @Override public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { @@ -71,18 +104,21 @@ public Object invoke(Object proxy, Method method, Object[] params) throws Throwa // mock == true, new Student("hubao"); RpcfxRequest request = new RpcfxRequest(); + // 因为服务描述就是这么定义的服务提供者和服务消费者如何确认要消费的服务,所以就要传输这些信息 + // 如果换了别的服务描述方式,那么这里的参数可能就会不同.但本质上还是确定类&&方法&&参数 + // 只是在不同的地方确认这个区别而已 request.setServiceClass(this.serviceClass.getName()); request.setMethod(method.getName()); request.setParams(params); - if (null!=filters) { + if (null != filters) { for (Filter filter : filters) { if (!filter.filter(request)) { return null; } } } - + // 远程调用 RpcfxResponse response = post(request, url); // 加filter地方之三 @@ -90,14 +126,22 @@ public Object invoke(Object proxy, Method method, Object[] params) throws Throwa // 这里判断response.status,处理异常 // 考虑封装一个全局的RpcfxException - + // 对服务提供者的服务结果进行反序列化处理 return JSON.parse(response.getResult().toString()); } + /** + * 进行远程调用 + * + * @param + * @return + * @date 2022/6/22 + */ private RpcfxResponse post(RpcfxRequest req, String url) throws IOException { + /*1. 序列化*/ String reqJson = JSON.toJSONString(req); - System.out.println("req json: "+reqJson); - + System.out.println("req json: " + reqJson); + /*2. 选择网络通信协议并进行网络传输,这里用的HTTP*/ // 1.可以复用client // 2.尝试使用httpclient或者netty client OkHttpClient client = new OkHttpClient(); @@ -105,8 +149,10 @@ private RpcfxResponse post(RpcfxRequest req, String url) throws IOException { .url(url) .post(RequestBody.create(JSONTYPE, reqJson)) .build(); + // DONE_JOLY:同步还是异步的---> OKHttp都提供了支持,这里用的是同步的 String respJson = client.newCall(request).execute().body().string(); - System.out.println("resp json: "+respJson); + System.out.println("resp json: " + respJson); + /*3. 反序列化服务结果,并返回结果*/ return JSON.parseObject(respJson, RpcfxResponse.class); } } diff --git a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/server/RpcfxInvoker.java b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/server/RpcfxInvoker.java index a6f77dac..088d9ebb 100644 --- a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/server/RpcfxInvoker.java +++ b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/server/RpcfxInvoker.java @@ -9,7 +9,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; - +/** + * 服务端会调用的代码 + * @author Joly + * @date 2022/6/22 + */ public class RpcfxInvoker { private RpcfxResolver resolver; @@ -17,12 +21,18 @@ public class RpcfxInvoker { public RpcfxInvoker(RpcfxResolver resolver){ this.resolver = resolver; } - + /** + * 调用 + * @date 2022/6/22 + * @param + * @return + */ public RpcfxResponse invoke(RpcfxRequest request) { RpcfxResponse response = new RpcfxResponse(); String serviceClass = request.getServiceClass(); // 作业1:改成泛型和反射 + // 现在是通过spring 的 bean来做的映射关系 Object service = resolver.resolve(serviceClass);//this.applicationContext.getBean(serviceClass); try { diff --git a/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/Order.java b/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/Order.java index a2fd6c91..da625230 100644 --- a/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/Order.java +++ b/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/Order.java @@ -1,5 +1,5 @@ package io.kimmking.rpcfx.demo.api; - +/** knowledge point: 说明和接口相关的实体类信息*/ public class Order { private int id; diff --git a/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/OrderService.java b/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/OrderService.java index 1884fedb..b218c6f0 100644 --- a/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/OrderService.java +++ b/07rpc/rpc01/rpcfx-demo-api/src/main/java/io/kimmking/rpcfx/demo/api/OrderService.java @@ -1,5 +1,5 @@ package io.kimmking.rpcfx.demo.api; - +/** knowledge point: 说明接口信息*/ public interface OrderService { Order findOrderById(int id); diff --git a/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java b/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java index a4187d14..d067e8fe 100644 --- a/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java +++ b/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java @@ -28,18 +28,21 @@ public static void main(String[] args) { // UserService service = new xxx(); // service.findById + /*这里演示了两种生成stub的方式*/ + // 生成stub UserService userService = Rpcfx.create(UserService.class, "http://localhost:8080/"); + // 调用服务(由代理去做实际的远程调用) User user = userService.findById(1); System.out.println("find user id=1 from server: " + user.getName()); -// OrderService orderService = Rpcfx.create(OrderService.class, "http://localhost:8080/"); -// Order order = orderService.findOrderById(1992129); -// System.out.println(String.format("find order name=%s, amount=%f",order.getName(),order.getAmount())); -// -// // -// UserService userService2 = Rpcfx.createFromRegistry(UserService.class, "localhost:2181", new TagRouter(), new RandomLoadBalancer(), new CuicuiFilter()); + OrderService orderService = Rpcfx.create(OrderService.class, "http://localhost:8080/"); + Order order = orderService.findOrderById(1992129); + System.out.println(String.format("find order name=%s, amount=%f",order.getName(),order.getAmount())); -// SpringApplication.run(RpcfxClientApplication.class, args); + // 从注册中心选个服务,来生成stub + // UserService userService2 = Rpcfx.createFromRegistry(UserService.class, "localhost:2181", new TagRouter(), new RandomLoadBalancer(), new CuicuiFilter()); + + // SpringApplication.run(RpcfxClientApplication.class, args); } private static class TagRouter implements Router { diff --git a/07rpc/rpc01/rpcfx-demo-provider/README.md b/07rpc/rpc01/rpcfx-demo-provider/README.md new file mode 100644 index 00000000..cf9f8670 --- /dev/null +++ b/07rpc/rpc01/rpcfx-demo-provider/README.md @@ -0,0 +1,3 @@ +# 项目 +服务提供者 +# \ No newline at end of file diff --git a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/DemoResolver.java b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/DemoResolver.java index 65cffbd2..fff8073f 100644 --- a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/DemoResolver.java +++ b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/DemoResolver.java @@ -3,7 +3,11 @@ import io.kimmking.rpcfx.api.RpcfxResolver; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; - +/** + * 用于获取服务提供者的服务对象 + * @author Joly + * @date 2022/6/23 + */ public class DemoResolver implements RpcfxResolver, ApplicationContextAware { private ApplicationContext applicationContext; diff --git a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/OrderServiceImpl.java b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/OrderServiceImpl.java index 39821952..48ad591d 100644 --- a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/OrderServiceImpl.java +++ b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/OrderServiceImpl.java @@ -2,11 +2,15 @@ import io.kimmking.rpcfx.demo.api.Order; import io.kimmking.rpcfx.demo.api.OrderService; - +/** + * 服务提供者的服务 + * @author Joly + * @date 2022/6/22 + */ public class OrderServiceImpl implements OrderService { @Override public Order findOrderById(int id) { - return new Order(id, "Cuijing" + System.currentTimeMillis(), 9.9f); + return new Order(id, "JOLY's ORDER:" + System.currentTimeMillis(), 9.9f); } } diff --git a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java index d79e422e..91dd5cd3 100644 --- a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java +++ b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java @@ -71,9 +71,14 @@ private static void registerService(CuratorFramework client, String service) thr @Autowired RpcfxInvoker invoker; - + /** + * 网络通信时,会直接调用这个API。然后就会到skeleton操作的部分 + * @date 2022/6/23 + * @param + * @return + */ @PostMapping("/") - public RpcfxResponse invoke(@RequestBody RpcfxRequest request) { + public RpcfxResponse invoke(@RequestBody RpcfxRequest request) throws InstantiationException, IllegalAccessException { return invoker.invoke(request); } diff --git a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/UserServiceImpl.java b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/UserServiceImpl.java index 5c37d60a..27e7f3d1 100644 --- a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/UserServiceImpl.java +++ b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/UserServiceImpl.java @@ -3,6 +3,12 @@ import io.kimmking.rpcfx.demo.api.User; import io.kimmking.rpcfx.demo.api.UserService; +/** + * 服务提供者的服务 + * + * @author Joly + * @date 2022/6/22 + */ public class UserServiceImpl implements UserService { @Override diff --git a/07rpc/rpc01/rpcfx-demo-provider/src/main/resources/application.yml b/07rpc/rpc01/rpcfx-demo-provider/src/main/resources/application.yml index 5164ac23..ed49354d 100644 --- a/07rpc/rpc01/rpcfx-demo-provider/src/main/resources/application.yml +++ b/07rpc/rpc01/rpcfx-demo-provider/src/main/resources/application.yml @@ -1,6 +1,6 @@ server: port: 8080 - +# TODO_Joly 这是个什么用法,我真心找不到啊 profiles: active: true diff --git a/07rpc/rpc02/README2.md b/07rpc/rpc02/README2.md new file mode 100644 index 00000000..e69de29b diff --git a/07rpc/rpc02/dubbo-demo-provider/README.md b/07rpc/rpc02/dubbo-demo-provider/README.md new file mode 100644 index 00000000..2dce61b0 --- /dev/null +++ b/07rpc/rpc02/dubbo-demo-provider/README.md @@ -0,0 +1 @@ +1. SpringBoot 提供了对Dubbo的支持,搞了个starter,所以配置起来更加方便 \ No newline at end of file diff --git a/08cache/README2.md b/08cache/README2.md new file mode 100644 index 00000000..e69de29b diff --git a/08cache/cache/README.md b/08cache/cache/README.md new file mode 100644 index 00000000..acbb7bbd --- /dev/null +++ b/08cache/cache/README.md @@ -0,0 +1,11 @@ +# Ehcache +* Ehcache,a widely used, open-source Java-based cache. It features memory and disk stores, listeners, cache loaders, RESTful and SOAP APIs and other very useful features. +* 类似于 Redis,Redis的数据存在了Redis中,哈哈哈哈哈 +* 数据存在了JVM中 +# 项目内容 +1. mybatis 结合 ehcache 实现数据缓存功能(mybatis二级缓存) + 1. 看 UserMapper.java && UserMapper.xml && ehcache.xml +2. Spring cache 利用 ehcache(或者redis) 实现数据缓存功能(方法级别缓存) + 1. 看CacheConfig.java 进行全局配置,UserServiceImpl.java && UserService.java 进行配置和使用,CacheApplication.java 开启缓存 +3. 结合 wrk 压测 REST 接口性能,来感受度 + \ No newline at end of file diff --git a/08cache/cache/pom.xml b/08cache/cache/pom.xml index 88c9a37e..6e4bde0f 100644 --- a/08cache/cache/pom.xml +++ b/08cache/cache/pom.xml @@ -31,6 +31,7 @@ org.springframework.boot spring-boot-starter-web + org.mybatis.spring.boot mybatis-spring-boot-starter @@ -45,10 +46,12 @@ org.projectlombok lombok + org.springframework.boot spring-boot-starter-cache + org.springframework.boot spring-boot-starter-data-redis @@ -61,11 +64,13 @@ org.apache.commons commons-pool2 + net.sf.ehcache ehcache 2.8.3 + org.mybatis mybatis-ehcache diff --git a/08cache/cache/src/main/java/io/kimmking/cache/CacheApplication.java b/08cache/cache/src/main/java/io/kimmking/cache/CacheApplication.java index 65c7ae57..fae9e67f 100644 --- a/08cache/cache/src/main/java/io/kimmking/cache/CacheApplication.java +++ b/08cache/cache/src/main/java/io/kimmking/cache/CacheApplication.java @@ -7,7 +7,7 @@ @SpringBootApplication(scanBasePackages = "io.kimmking.cache") @MapperScan("io.kimmking.cache.mapper") -@EnableCaching +@EnableCaching // 开启缓存 public class CacheApplication { public static void main(String[] args) { diff --git a/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java b/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java index d4bdd8b1..e6dc725d 100644 --- a/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java +++ b/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java @@ -17,6 +17,11 @@ import static org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig; +/** + * knowledge point: + * 全局的 缓存配置,是 Spring Cache的 + * 在这个例子里,Spring Cache 是配合 Redis 来用的 + */ @Configuration public class CacheConfig extends CachingConfigurerSupport { @@ -24,13 +29,15 @@ public class CacheConfig extends CachingConfigurerSupport { private RedisConnectionFactory factory; /** - * 自定义生成redis-key + * Generate a key + * 这个例子里的key就是自定义生成的redis-key * * @return */ @Override @Bean public KeyGenerator keyGenerator() { + // TODO_Joly:这三个参数从哪来的 return (o, method, objects) -> { StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()).append("."); @@ -47,7 +54,7 @@ public KeyGenerator keyGenerator() { public RedisTemplate redisTemplate() { RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); - + /** knowledge point: 设置序列化器,Jackson2Json*/ GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer); diff --git a/08cache/cache/src/main/java/io/kimmking/cache/controller/UserController.java b/08cache/cache/src/main/java/io/kimmking/cache/controller/UserController.java index b19d9553..f5e1b91b 100644 --- a/08cache/cache/src/main/java/io/kimmking/cache/controller/UserController.java +++ b/08cache/cache/src/main/java/io/kimmking/cache/controller/UserController.java @@ -4,6 +4,7 @@ import io.kimmking.cache.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -16,8 +17,8 @@ public class UserController { @Autowired UserService userService; - @RequestMapping("/user/find") - User find(Integer id) { + @RequestMapping("/user/find/{id}") + User find(@PathVariable Integer id) { return userService.find(id); //return new User(1,"KK", 28); } diff --git a/08cache/cache/src/main/java/io/kimmking/cache/service/UserService.java b/08cache/cache/src/main/java/io/kimmking/cache/service/UserService.java index 22c3987b..66754212 100644 --- a/08cache/cache/src/main/java/io/kimmking/cache/service/UserService.java +++ b/08cache/cache/src/main/java/io/kimmking/cache/service/UserService.java @@ -4,7 +4,8 @@ import org.springframework.cache.annotation.CacheConfig; import java.util.List; - +// TODO_Joly: cacheNames 拿来干嘛的 +// Spring cache 提供的方法级别的统一操作 @CacheConfig(cacheNames = "users") public interface UserService { diff --git a/08cache/cache/src/main/resources/application.yml b/08cache/cache/src/main/resources/application.yml index 1d76edf5..5e2ab33a 100644 --- a/08cache/cache/src/main/resources/application.yml +++ b/08cache/cache/src/main/resources/application.yml @@ -3,22 +3,25 @@ server: spring: datasource: - username: root - password: - url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC + username: idea_user_all + password: 123456joly + url: jdbc:mysql://47.115.148.27:3306/cache?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC driver-class-name: com.mysql.jdbc.Driver cache: +# Spring Cache 使用的缓存类型 type: redis +# type: ehcache +# ehcache: +# config: ehcache.xml redis: - host: localhost + host: 47.115.148.27 +# 端口号默认6379 lettuce: pool: max-active: 16 max-wait: 10ms -# type: ehcache -# ehcache: -# config: ehcache.xml + mybatis: mapper-locations: classpath:mapper/*Mapper.xml diff --git a/08cache/cache/src/main/resources/mapper/UserMapper.xml b/08cache/cache/src/main/resources/mapper/UserMapper.xml index 0d2e8ae5..a82ac992 100644 --- a/08cache/cache/src/main/resources/mapper/UserMapper.xml +++ b/08cache/cache/src/main/resources/mapper/UserMapper.xml @@ -3,6 +3,7 @@ + diff --git a/08cache/ha/conf/redis6379.conf b/08cache/ha/conf/redis6379.conf index e33949fa..1452d6aa 100644 --- a/08cache/ha/conf/redis6379.conf +++ b/08cache/ha/conf/redis6379.conf @@ -65,7 +65,7 @@ # IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES # JUST COMMENT OUT THE FOLLOWING LINE. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -bind 127.0.0.1 ::1 +# bind 127.0.0.1 ::1 # Protected mode is a layer of security protection, in order to avoid that # Redis instances left open on the internet are accessed and exploited. @@ -362,7 +362,7 @@ rdb-del-sync-files no # The Append Only File will also be created inside this directory. # # Note that you must specify a directory here, not a file name. -dir "/Users/kimmking/logs/redis0" +dir "./" ################################# REPLICATION ################################# @@ -1866,4 +1866,4 @@ jemalloc-bg-thread yes # Generated by CONFIG REWRITE user default on nopass sanitize-payload ~* &* +@all -replicaof 127.0.0.1 6380 +replicaof 127.0.0.1 6379 diff --git a/08cache/ha/conf/redis6380.conf b/08cache/ha/conf/redis6380.conf index 20311df0..ebf10fd6 100644 --- a/08cache/ha/conf/redis6380.conf +++ b/08cache/ha/conf/redis6380.conf @@ -362,7 +362,8 @@ rdb-del-sync-files no # The Append Only File will also be created inside this directory. # # Note that you must specify a directory here, not a file name. -dir "/Users/kimmking/logs/redis1" +# 数据文件夹 +dir "/usr/redis/logs/6380" ################################# REPLICATION ################################# diff --git a/08cache/redis/README.md b/08cache/redis/README.md new file mode 100644 index 00000000..e5c92492 --- /dev/null +++ b/08cache/redis/README.md @@ -0,0 +1,2 @@ +# 项目内容 +1. 使用 Jedis 来操作 Redis \ No newline at end of file diff --git a/08cache/redis/pom.xml b/08cache/redis/pom.xml index 6f0603dd..03257f30 100644 --- a/08cache/redis/pom.xml +++ b/08cache/redis/pom.xml @@ -33,7 +33,7 @@ org.projectlombok lombok - + redis.clients jedis @@ -55,7 +55,7 @@ com.hazelcast hazelcast - + org.springframework.boot spring-boot-starter-data-redis diff --git a/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java b/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java index f685a7b8..83f48541 100644 --- a/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java +++ b/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java @@ -17,7 +17,9 @@ public class RedisApplication { public static void main(String[] args) { // C1.最简单demo - Jedis jedis = new Jedis("localhost", 6379); + // Jedis 基本上就是Redis命令的翻版 + Jedis jedis = new Jedis("47.115.148.27", 6379); + // Redis 信息 System.out.println(jedis.info()); jedis.set("uptime", new Long(System.currentTimeMillis()).toString()); System.out.println(jedis.get("uptime")); diff --git a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java index bd86f2fb..f526498b 100644 --- a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java +++ b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java @@ -13,12 +13,11 @@ public class RedissionDemo { @SneakyThrows public static void main(String[] args) { Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6379"); + config.useSingleServer().setAddress("redis://47.115.148.27:6379"); final RedissonClient client = Redisson.create(config); RMap rmap = client.getMap("map1"); RLock lock = client.getLock("lock1"); - try{ lock.lock(); diff --git a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java index 8534b3c8..e8ee90f3 100644 --- a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java +++ b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java @@ -10,9 +10,11 @@ public class RedissionDemo1 { public static void main(String[] args) { Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6379"); + config.useSingleServer().setAddress("redis://47.115.148.27:6379"); final RedissonClient client = Redisson.create(config); + // DONE_Joly: 虽然是两个JVM,但是这个lock应该是在Redis哪里做的统一的吧,所以RedissionDemo和RedissionDemo1应该只有一个能够获得锁的呀 + // ---> 是的呀,这就是分布式锁呀,就是只有一个JVM拿到了锁呀 RLock lock = client.getLock("lock1"); try{ diff --git a/09mq/activemq-demo/pom.xml b/09mq/activemq-demo/pom.xml index c3352476..016b00ef 100644 --- a/09mq/activemq-demo/pom.xml +++ b/09mq/activemq-demo/pom.xml @@ -23,7 +23,7 @@ org.springframework.boot spring-boot-starter - + org.apache.activemq activemq-all diff --git a/09mq/activemq-demo/src/README.md b/09mq/activemq-demo/src/README.md new file mode 100644 index 00000000..bfaa5b87 --- /dev/null +++ b/09mq/activemq-demo/src/README.md @@ -0,0 +1,3 @@ +# 项目目的 +1. 演示activemq +2. 演示activemq使用JMS作为应用层协议 \ No newline at end of file diff --git a/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java b/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java index 834f015f..4db8ad35 100644 --- a/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java +++ b/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java @@ -16,26 +16,75 @@ public class ActivemqApplication { public static void main(String[] args) { - // 定义Destination + // 定义Destination ,topic(destination里面有topic和queue) Destination destination = new ActiveMQTopic("test.topic"); - // Destination destination = new ActiveMQQueue("test.queue"); + // queue + Destination destinationQueue = new ActiveMQQueue("test.queue"); testDestination(destination); - + testDestinationQueue(destinationQueue); //SpringApplication.run(ActivemqApplication.class, args); } + /** + * 对于queue的消息生产和消费 + * + * @param + * @return + * @date 2022/7/21 + */ + private static void testDestinationQueue(Destination destinationQueue) { + try { + //创建连接 + ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory("tcp://47.115.148.27:61616"); + Connection connection = activeMQConnectionFactory.createConnection(); + connection.start(); + //创建会话 + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + //创建消费者 + MessageConsumer consumer = session.createConsumer(destinationQueue); + MessageListener messageListener = new MessageListener() { + @Override + public void onMessage(Message message) { + try { + // 打印所有的消息内容 + // Thread.sleep(); + System.out.println(" => receive from " + destinationQueue.toString() + ": " + message); + // message.acknowledge(); // 前面所有未被确认的消息全部都确认。 + + } catch (Exception e) { + e.printStackTrace(); // 不要吞任何这里的异常, + } + } + }; + // 其实就是设置消费者收到消息之后要做什么(监听器) + consumer.setMessageListener(messageListener); + //创建生产者 + MessageProducer producer = session.createProducer(destinationQueue); + Message message = session.createTextMessage("hello"); + producer.send(message); + + //关闭资源 + session.close(); + connection.close(); + } catch (Exception e) { + System.out.println(e); + } + } + public static void testDestination(Destination destination) { try { // 创建连接和会话 - ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616"); + ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://47.115.148.27:61616"); ActiveMQConnection conn = (ActiveMQConnection) factory.createConnection(); conn.start(); + // Session.AUTO_ACKNOWLEDGE 自动确认 Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); // 创建消费者 - MessageConsumer consumer = session.createConsumer( destination ); + MessageConsumer consumer = session.createConsumer(destination); final AtomicInteger count = new AtomicInteger(0); + // JMS 监听器 MessageListener listener = new MessageListener() { public void onMessage(Message message) { try { @@ -61,12 +110,10 @@ public void onMessage(Message message) { TextMessage message = session.createTextMessage(index + " message."); producer.send(message); } - + // TODO_Joly: 是为了等消费者可以把所有消息都消费完吗 Thread.sleep(20000); session.close(); conn.close(); - - } catch (Exception e) { e.printStackTrace(); } diff --git a/09mq/kafka-demo/README2.md b/09mq/kafka-demo/README2.md new file mode 100644 index 00000000..c0127f7a --- /dev/null +++ b/09mq/kafka-demo/README2.md @@ -0,0 +1,3 @@ +# 项目目的 +1. 演示在 Java 中使用 Kafka 发送接受消息 + * 我的理解是,在Java中使用Kafaka,那么就是Java作为客户端 \ No newline at end of file diff --git a/09mq/kafka-demo/pom.xml b/09mq/kafka-demo/pom.xml index 87efa723..ffc3a355 100644 --- a/09mq/kafka-demo/pom.xml +++ b/09mq/kafka-demo/pom.xml @@ -34,19 +34,31 @@ org.projectlombok lombok - + org.apache.kafka - kafka_2.12 - 2.6.0 + kafka_2.13 + 2.8.0 + + + + + + org.apache.kafka kafka-clients - 2.6.0 + 2.8.0 + + + + + + com.alibaba fastjson diff --git a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/Order.java b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/Order.java index 43af1c02..e669b50e 100644 --- a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/Order.java +++ b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/Order.java @@ -5,6 +5,12 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * 就是个Order实体类 + * + * @author Joly + * @date 2022/7/23 + */ @NoArgsConstructor @AllArgsConstructor diff --git a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ConsumerImpl.java b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ConsumerImpl.java index 611c4de2..7db3a052 100644 --- a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ConsumerImpl.java +++ b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ConsumerImpl.java @@ -21,6 +21,7 @@ public ConsumerImpl() { // properties.put("enable.auto.commit", false); // properties.put("isolation.level", "read_committed"); // properties.put("auto.offset.reset", "latest"); +// 消费者组:多个消费者一起来消费这个消费者组可以消费的消息 properties.put("group.id", "java1-kimmking"); properties.put("bootstrap.servers", "localhost:9092"); properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); @@ -30,11 +31,12 @@ public ConsumerImpl() { @Override public void consumeOrder() { - + // 订阅topic consumer.subscribe(Collections.singletonList(topic)); try { while (true) { //拉取数据 + // 每次拉取到的是一批消息 ConsumerRecords poll = consumer.poll(Duration.ofSeconds(1)); for (ConsumerRecord o : poll) { @@ -58,6 +60,7 @@ public void consumeOrder() { e.printStackTrace(); } finally { try { + // 同步消费者信息,消费的位置 consumer.commitSync();//currentOffsets); } catch (Exception e) { consumer.close(); diff --git a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/Producer.java b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/Producer.java index 2bf2d937..a3d72f6b 100644 --- a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/Producer.java +++ b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/Producer.java @@ -1,7 +1,7 @@ package io.kimmking.javacourse.kafka.kimmking; import io.kimmking.javacourse.kafka.Order; - +// TODO_Joly: 为什么还要定义 Producer public interface Producer { void send(Order order); diff --git a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ProducerImpl.java b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ProducerImpl.java index 1c069263..30f8a089 100644 --- a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ProducerImpl.java +++ b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/kimmking/ProducerImpl.java @@ -14,6 +14,13 @@ public class ProducerImpl implements Producer { private KafkaProducer producer; private final String topic = "order-test1"; + /** + * 配置参数,设置发送给哪个消息中间件的哪个destination(topic) + * + * @param + * @return + * @date 2022/7/23 + */ public ProducerImpl() { properties = new Properties(); properties.put("bootstrap.servers", "localhost:9092"); @@ -29,17 +36,28 @@ public ProducerImpl() { //producer.initTransactions(); } + /** + * 用户定义了 消息发送的事务、消息失败等情况 + * + * @param + * @return + * @date 2022/7/23 + */ @Override public void send(Order order) { try { + // 这是消息的事务,开启 //producer.beginTransaction(); + // 指定发送给哪个 topic (destination) ProducerRecord record = new ProducerRecord(topic, order.getId().toString(), JSON.toJSONString(order)); producer.send(record, (metadata, exception) -> { +// 这里应该是异常处理,如果消息发送失败了之类的 // if (exception != null) { // producer.abortTransaction(); // throw new KafkaException(exception.getMessage() + " , data: " + record); // } }); + // 这是消息的事务,提交 //producer.commitTransaction(); } catch (Throwable e) { diff --git a/09mq/kmq-core/README.md b/09mq/kmq-core/README.md index 5af5a6fd..2ea71d3e 100644 --- a/09mq/kmq-core/README.md +++ b/09mq/kmq-core/README.md @@ -1,4 +1,5 @@ -## 说明 +## 说明(动手实现 MQ) + 第一个版本,完全基于内存queue的消息队列,实现了最基础的三个功能: diff --git a/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/Kmq.java b/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/Kmq.java index ebf03192..f52429a1 100644 --- a/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/Kmq.java +++ b/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/Kmq.java @@ -6,7 +6,12 @@ import java.util.concurrent.TimeUnit; public final class Kmq { - + /** + * 包装了 LinkedBlockingQueue(一个 Topic 对应了一个 LinkedBlockingQueue) + * @date 2022/7/31 + * @param + * @return + */ public Kmq(String topic, int capacity) { this.topic = topic; this.capacity = capacity; diff --git a/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/KmqBroker.java b/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/KmqBroker.java index 672557db..eacdc6b0 100644 --- a/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/KmqBroker.java +++ b/09mq/kmq-core/src/main/java/io/kimmking/kmq/core/KmqBroker.java @@ -3,14 +3,20 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +/** + * 数据存储 + * + * @author Joly + * @date 2022/7/31 + */ public final class KmqBroker { // Broker+Connection public static final int CAPACITY = 10000; private final Map kmqMap = new ConcurrentHashMap<>(64); - public void createTopic(String name){ - kmqMap.putIfAbsent(name, new Kmq(name,CAPACITY)); + public void createTopic(String name) { + kmqMap.putIfAbsent(name, new Kmq(name, CAPACITY)); } public Kmq findKmq(String topic) { diff --git a/09mq/pulsar/pom.xml b/09mq/pulsar/pom.xml index 6382a1b4..4b7ba2a5 100644 --- a/09mq/pulsar/pom.xml +++ b/09mq/pulsar/pom.xml @@ -23,21 +23,22 @@ org.springframework.boot spring-boot-starter - + + org.apache.pulsar pulsar-client 2.7.0 - - - - - - - + + + + + + + org.projectlombok diff --git a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/Config.java b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/Config.java index 7d62c9c3..424784da 100644 --- a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/Config.java +++ b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/Config.java @@ -4,7 +4,12 @@ import org.apache.pulsar.client.api.PulsarClient; public class Config { - + /** + * 创建 Pulsar client + * @date 2022/7/31 + * @param + * @return + */ @SneakyThrows public static PulsarClient createClient() { return PulsarClient.builder() diff --git a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ConsumerDemo.java b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ConsumerDemo.java index 7a1ac56d..92b4aee4 100644 --- a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ConsumerDemo.java +++ b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ConsumerDemo.java @@ -13,7 +13,7 @@ public void consume() { Consumer consumer = Config.createClient().newConsumer() .topic("my-kk") - .subscriptionName("my-subscription") + .subscriptionName("my-subscription") // DONE_Joly:subscription 是什么--->消费者组 .subscribe(); while (true) { @@ -24,14 +24,14 @@ public void consume() { // Do something with the message System.out.printf("Message received from pulsar: %s \n", new String(msg.getData())); - // Acknowledge the message so that it can be deleted by the message broker + // Acknowledge the message so that it can be deleted by the message broker 确认机制(业务决定是否消费成功) consumer.acknowledge(msg); } catch (Exception e) { - // Message failed to process, redeliver later + // Message failed to process, redeliver later 确认机制(业务决定是否消费成功) consumer.negativeAcknowledge(msg); } } - +//以下为各种消费者的配置模式 // // client.newConsumer() // .deadLetterPolicy(DeadLetterPolicy.builder().maxRedeliverCount(10) diff --git a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java index 9c1c6bf4..983f844e 100644 --- a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java +++ b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java @@ -10,20 +10,20 @@ public class ProducerDemo { Producer stringProducer; @SneakyThrows - public ProducerDemo(){ + public ProducerDemo() { stringProducer = Config.createClient().newProducer(Schema.STRING) .topic("my-kk") .create(); } - @SneakyThrows + @SneakyThrows // 这玩意允许我不处理检查异常 public void sendMessage() { for (int i = 0; i < 1000; i++) { stringProducer.send(i + " message from pulsar."); } } - +//以下为生产者的各种生成模式 // //关闭操作也可以是异步的: // // producer.closeAsync() @@ -50,7 +50,7 @@ public void sendMessage() { // 添加参数 // producer.newMessage() -// .key("my-message-key") +// .key("my-message-key") // 用key来share,Kafka 里面也有一个类似的 key // .value("my-async-message".getBytes()) // .property("my-key", "my-value") // .property("my-other-key", "my-other-value") diff --git a/09mq/pulsar/src/main/resources/application.properties b/09mq/pulsar/src/main/resources/application.properties index 8b137891..e69de29b 100644 --- a/09mq/pulsar/src/main/resources/application.properties +++ b/09mq/pulsar/src/main/resources/application.properties @@ -1 +0,0 @@ - diff --git a/09mq/rabbit/README.md b/09mq/rabbit/README.md new file mode 100644 index 00000000..ce246d65 --- /dev/null +++ b/09mq/rabbit/README.md @@ -0,0 +1,2 @@ +# 项目内容 +1. 演示 Spring 结合 RabbitMQ (配合 RabbitMQ 的控制台一起看,ip:15672,docker拉版本的时候记得是 rabbitmq:management, 不然没有控制台) \ No newline at end of file diff --git a/09mq/rabbit/pom.xml b/09mq/rabbit/pom.xml index ae17ee14..f9bfc92f 100644 --- a/09mq/rabbit/pom.xml +++ b/09mq/rabbit/pom.xml @@ -19,37 +19,40 @@ - - - - + + + + + + org.springframework.boot spring-boot-starter-amqp - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + org.projectlombok lombok true + org.springframework.boot spring-boot-starter-test diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageProducer.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageProducer.java index 2480046b..b3e710ea 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageProducer.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageProducer.java @@ -7,12 +7,17 @@ import org.springframework.stereotype.Component; import java.util.UUID; - +/** + * 消息生产者 + * @author Joly + * @date 2022/7/26 + */ @Component @Slf4j public class MessageProducer implements RabbitTemplate.ConfirmCallback { //由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自动注入 + // 因为 向单例的MessageProducer 中注入原型RabbitTemplate的话,就不会是原型了,因为只注入一次,所以RabbitTemplate也只会有一个 private RabbitTemplate rabbitTemplate; /** * 构造方法注入rabbitTemplate @@ -25,11 +30,12 @@ public MessageProducer(RabbitTemplate rabbitTemplate) { public void sendMessage(String content) { CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString()); - //把消息放入ROUTINGKEY_A对应的队列当中去,对应的是队列A + // mq 自动把 EXCHANGE A 给创建了 + //把消息放入ROUTINGKEY_B对应的队列当中去,对应的是队列B【看的是ROUTINGKEY】 rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_A, RabbitConfig.ROUTINGKEY_B, content, correlationId); } /** - * 回调 + * 回调(消息发送出去后,会回调生产者,来通知生产者,消费情况) */ @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverA.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverA.java index 6cea0d3a..5f4bafaf 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverA.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverA.java @@ -4,7 +4,11 @@ import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; - +/** + * 消费者A + * @author Joly + * @date 2022/7/26 + */ @Component @RabbitListener(queues = RabbitConfig.QUEUE_A) @Slf4j diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverB.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverB.java index 7b0e81db..fdbe9372 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverB.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverB.java @@ -4,9 +4,13 @@ import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; - +/** + * 消费者B + * @author Joly + * @date 2022/7/26 + */ @Component -@RabbitListener(queues = RabbitConfig.QUEUE_B) +@RabbitListener(queues = RabbitConfig.QUEUE_B) // 设定消费者要消费的队列 @Slf4j public class MessageReceiverB { diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java index 440db166..e16e3cfc 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java @@ -12,7 +12,11 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; - +/** + * 配置 RabbitMQ的相关信息,以及配置 exchange 和 routingkey + * @author Joly + * @date 2022/7/26 + */ @Configuration public class RabbitConfig { @@ -72,7 +76,7 @@ public RabbitTemplate rabbitTemplate() { public DirectExchange defaultExchange() { return new DirectExchange(EXCHANGE_A); } - + // mq 会自动根据这里的配置来创建 队列A、B、C @Bean public Queue queueA() { return new Queue(QUEUE_A, true); //队列持久 diff --git a/09mq/rabbit/src/main/resources/application.yaml b/09mq/rabbit/src/main/resources/application.yaml index 48574487..50540611 100644 --- a/09mq/rabbit/src/main/resources/application.yaml +++ b/09mq/rabbit/src/main/resources/application.yaml @@ -1,7 +1,6 @@ spring: rabbitmq: - host: localhost + host: 47.115.148.27 username: admin password: admin - port: 5672 - + port: 25672 \ No newline at end of file diff --git a/09mq/rocket/README.md b/09mq/rocket/README.md new file mode 100644 index 00000000..24d348fe --- /dev/null +++ b/09mq/rocket/README.md @@ -0,0 +1,6 @@ +## ĿĿ +1. Spring ṩ Rocket MQ ʹ +2. Spring Boot Ŀ +## Ŀ +* Orderʵ +* RocketApplication \ No newline at end of file diff --git a/09mq/rocket/pom.xml b/09mq/rocket/pom.xml index d2931a7e..58a7ef47 100644 --- a/09mq/rocket/pom.xml +++ b/09mq/rocket/pom.xml @@ -23,7 +23,7 @@ - + org.apache.rocketmq rocketmq-spring-boot-starter diff --git a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/Order.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/Order.java index 02aec9f7..f327dbb1 100644 --- a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/Order.java +++ b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/Order.java @@ -3,7 +3,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; - +/** + * 就是个实体类 + * @author Joly + * @date 2022/7/29 + */ @Data @NoArgsConstructor @AllArgsConstructor diff --git a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java index 2c4ba4ed..2a1fb622 100644 --- a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java +++ b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java @@ -5,10 +5,13 @@ import org.apache.rocketmq.spring.core.RocketMQReplyListener; import org.springframework.stereotype.Component; +/** + * @author Joly + */ @Component @RocketMQMessageListener(consumerGroup = "test2", topic = "test-k2") -public class OrderConsumerDemo implements RocketMQReplyListener { - +public class OrderConsumerDemo implements RocketMQReplyListener { // 这里的 Order 是确认了泛型,这个泛型要和 onMessage()的参数类型一样 + // 消费完了以后,返回个 String 【这里实现的是 RocketMQReplyListener 】 @Override public String onMessage(Order order) { // request-response System.out.println(this.getClass().getName() + " -> " + order); diff --git a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java index 13d6c89c..7d725ece 100644 --- a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java +++ b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java @@ -14,6 +14,13 @@ import java.math.BigDecimal; import java.util.List; +/** + * 生产者 + * + * @author jrl + * @date 2022/12/9 + */ +// CommandLineRunner 和 ApplicationRunner 的作用是一样的,可以运行 run () 方法 @SpringBootApplication public class RocketApplication implements CommandLineRunner { @@ -21,6 +28,7 @@ public static void main(String[] args) { SpringApplication.run(RocketApplication.class, args); } + /*Spring Boot 直接给配好了 Template*/ @Resource private RocketMQTemplate rocketMQTemplate; @@ -28,31 +36,33 @@ public static void main(String[] args) { public void run(String... args) throws Exception { String topic = "test-k1"; + // 1. 同步发送消息 + // 简单版 SendResult sendResult = rocketMQTemplate.syncSend(topic, "Hello, World!" + System.currentTimeMillis()); System.out.printf("syncSend1 to topic %s sendResult=%s %n", topic, sendResult); - + // 复杂版(使用 MessageBuilder 来封装消息,可以在里面设置消息头:消息的格式等) sendResult = rocketMQTemplate.syncSend(topic, MessageBuilder.withPayload( - new Order(System.currentTimeMillis(),"CNY2USD", 0.1501d)) + new Order(System.currentTimeMillis(), "CNY2USD", 0.1501d)) .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); System.out.printf("syncSend1 to topic %s sendResult=%s %n", topic, sendResult); String topic1 = "test-k2"; - - String result = rocketMQTemplate.sendAndReceive(topic1, new Order(System.currentTimeMillis(),"CNY2USD", 0.1502d), String.class); + //2. 版本一:异步发送并且接受消息结果 + String result = rocketMQTemplate.sendAndReceive(topic1, new Order(System.currentTimeMillis(), "CNY2USD", 0.1502d), String.class); System.out.println(" consumer result => " + result); + //版本二:异步发送消息,需要设置callback来处理消息发送情况的结果(回调处理) + rocketMQTemplate.asyncSend(topic1, new Order(System.currentTimeMillis(), "CNY2USD", 0.1502d), new SendCallback() { + @Override + public void onSuccess(SendResult result) { + System.out.printf("async onSucess SendResult=%s %n", result); + } + + @Override + public void onException(Throwable throwable) { + System.out.printf("async onException Throwable=%s %n", throwable); + } -// rocketMQTemplate.asyncSend(topic1, new Order(System.currentTimeMillis(),"CNY2USD", 0.1502d), new SendCallback() { -// @Override -// public void onSuccess(SendResult result) { -// System.out.printf("async onSucess SendResult=%s %n", result); -// } -// -// @Override -// public void onException(Throwable throwable) { -// System.out.printf("async onException Throwable=%s %n", throwable); -// } -// -// }); + }); } diff --git a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java index f2534bdb..eaa33d0a 100644 --- a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java +++ b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java @@ -4,10 +4,16 @@ import org.apache.rocketmq.spring.core.RocketMQListener; import org.springframework.stereotype.Component; +/** + * 消费者 + * + * @author Joly + * @date 2022/7/29 + */ @Component -@RocketMQMessageListener(consumerGroup = "test1", topic = "test-k1") -public class StringConsumerDemo implements RocketMQListener { - +@RocketMQMessageListener(consumerGroup = "test1", topic = "test-k1") // 制定了消费者组和要接受的topic +public class StringConsumerDemo implements RocketMQListener { // 这里的 String 是确认了泛型,这个泛型要和 onMessage()的参数类型一样 + // 没有返回值,所以这个消息是消费掉了就结束了 【这里实现的是 RocketMQListener】 @Override public void onMessage(String message) { // one way System.out.println(this.getClass().getName() + " -> " + message); diff --git a/09mq/rocket/src/main/resources/application.properties b/09mq/rocket/src/main/resources/application.properties index 513b78b4..d6c902a0 100644 --- a/09mq/rocket/src/main/resources/application.properties +++ b/09mq/rocket/src/main/resources/application.properties @@ -1,5 +1,6 @@ -rocketmq.name-server=localhost:9876 +rocketmq.name-server=47.115.148.27:9876 +#TODO rocketmq.producer.group=my-group1 rocketmq.producer.sendMessageTimeout=300000 diff --git a/09mq/spring-kafka-demo/src/main/java/io/kimmking/javacourse/kafkademo/KafkaDemoApplication.java b/09mq/spring-kafka-demo/src/main/java/io/kimmking/javacourse/kafkademo/KafkaDemoApplication.java index 738ba47c..9d5d3b80 100644 --- a/09mq/spring-kafka-demo/src/main/java/io/kimmking/javacourse/kafkademo/KafkaDemoApplication.java +++ b/09mq/spring-kafka-demo/src/main/java/io/kimmking/javacourse/kafkademo/KafkaDemoApplication.java @@ -1,5 +1,6 @@ package io.kimmking.javacourse.kafkademo; +import org.apache.kafka.clients.producer.KafkaProducer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -8,6 +9,8 @@ public class KafkaDemoApplication { public static void main(String[] args) { SpringApplication.run(KafkaDemoApplication.class, args); + KafkaProducer kafkaProducer = new KafkaProducer<>(); + kafkaProducer.flush(); } } diff --git a/app/.mvn/wrapper/MavenWrapperDownloader.java b/app/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index a45eb6ba..00000000 --- a/app/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2007-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/app/.mvn/wrapper/maven-wrapper.jar b/app/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a5..00000000 Binary files a/app/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/app/.mvn/wrapper/maven-wrapper.properties b/app/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572c..00000000 --- a/app/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/javase_joly/src/Basic/EqualsAnd.java b/javase_joly/src/Basic/EqualsAnd.java new file mode 100644 index 00000000..3a0cef9e --- /dev/null +++ b/javase_joly/src/Basic/EqualsAnd.java @@ -0,0 +1,55 @@ +package Basic; + +import static java.lang.Integer.parseInt; + +/** + * 关于== + * + * @author jrl + * @date Create in 15:07 2021-12-29 + */ +public class EqualsAnd { + + + public static void main(String[] args) { + + Integer a = 127; //Integer.valueOf(127) + Integer b = 127; //Integer.valueOf(127) + System.out.println("\nInteger a = 127;\n" + + "Integer b = 127;\n" + + "a == b ? {}" + (a == b)); // true + + Integer c = 128; //Integer.valueOf(128) + Integer d = 128; //Integer.valueOf(128) + System.out.println("\nInteger c = 128;\n" + + "Integer d = 128;\n" + + "c == d ? {}" + (c == d)); //false + + Integer e = 127; //Integer.valueOf(127) + Integer f = new Integer(127); //new instance + System.out.println("\nInteger e = 127;\n" + + "Integer f = new Integer(127));\n" + + "e == f ? {}" + (e == f)); //false + + Integer g = new Integer(127); //new instance + Integer h = new Integer(127); //new instance + System.out.println("\nInteger g = new Integer(127));\n" + + "Integer h = new Integer(127));\n" + + "g == h ? {}" + (g == h)); //false + + Integer i = 128; //unbox + int j = 128; + System.out.println("\nInteger i = 128;\n" + + "int j = 128;\n" + + "i == j ? {}" + (i == j)); //true + assert 128 >= 127; + // intern()方法,对字符串进行驻留 + String a1 = new String("a").intern(); + boolean b1 = a1 == "a"; + String b2 = new String("b"); + System.out.println(b1); + System.out.println(b2 == "b"); + } + + +} diff --git a/javase_joly/src/Basic/IntegerLearn.java b/javase_joly/src/Basic/IntegerLearn.java new file mode 100644 index 00000000..b721925a --- /dev/null +++ b/javase_joly/src/Basic/IntegerLearn.java @@ -0,0 +1,13 @@ +package Basic; + +/** + * @author jrl + * @date Create in 18:49 2021-12-17 + */ +public class IntegerLearn { + public static void main(String[] args) { + Integer a = 127; + Integer b = 127; + System.out.println(a.equals(b)); + } +} diff --git a/javase_joly/src/Basic/ShortLearn.java b/javase_joly/src/Basic/ShortLearn.java new file mode 100644 index 00000000..ec095077 --- /dev/null +++ b/javase_joly/src/Basic/ShortLearn.java @@ -0,0 +1,15 @@ +package Basic; + +/** + * @author jrl + * @date Create in 11:53 2021-12-29 + */ +public class ShortLearn { + public static void main(String[] args) { + Short s = new Short("1"); + boolean equals = s.equals("1"); + short aa = (short) 1; + s.equals(1); + System.out.println(equals); + } +} diff --git a/javase_joly/src/Basic/StringLearn.java b/javase_joly/src/Basic/StringLearn.java new file mode 100644 index 00000000..623bca3e --- /dev/null +++ b/javase_joly/src/Basic/StringLearn.java @@ -0,0 +1,16 @@ +package Basic; + +/** + * @author jrl + * @date Create in 17:16 2021-12-28 + */ +public class StringLearn { + public static void main(String[] args) { + String s = null; +// s.substring(0,2); + String s2 = "1"; + + String substring = s2.substring(0, s2.length()); + System.out.println(substring); + } +} diff --git a/javase_joly/src/BigDecimal/BigDecimalBasic.java b/javase_joly/src/BigDecimal/BigDecimalBasic.java new file mode 100644 index 00000000..28a3b73c --- /dev/null +++ b/javase_joly/src/BigDecimal/BigDecimalBasic.java @@ -0,0 +1,16 @@ +package BigDecimal; + +import java.math.BigDecimal; + +/** + * @author jrl + * @date Create in 14:37 2021-11-22 + */ +public class BigDecimalBasic { + public static void main(String[] args) { + BigDecimal b = new BigDecimal("1.111"); + BigDecimal divide = b.divide(new BigDecimal("100")); + System.out.println(divide+" "+b); + b.toString(); + } +} diff --git a/javase_joly/src/Collection/List/ArrayListLearn.java b/javase_joly/src/Collection/List/ArrayListLearn.java new file mode 100644 index 00000000..c12bb83c --- /dev/null +++ b/javase_joly/src/Collection/List/ArrayListLearn.java @@ -0,0 +1,11 @@ +package Collection.List; + +/** + * @author jrl + * @date Create in 16:11 2021-11-22 + */ +public class ArrayListLearn { + public static void main(String[] args) { + + } +} diff --git a/javase_joly/src/Collection/List/Practice100.java b/javase_joly/src/Collection/List/Practice100.java new file mode 100644 index 00000000..3ddbbe55 --- /dev/null +++ b/javase_joly/src/Collection/List/Practice100.java @@ -0,0 +1,28 @@ +package Collection.List; + +import java.util.Arrays; +import java.util.List; + +/** + * @author jrl + * @date Create in 14:03 2021-11-17 + */ +public class Practice100 { + public static void main(String[] args) { + Practice100 p_100 = new Practice100(); + p_100.arrayToList(); + } + + /** + * @param + * @return + * @date 2021-11-17 + */ + private void arrayToList() { + Integer[] arr = {1, 2, 3}; + List list = Arrays.asList(arr); + for (int i = 0; i < list.size(); i++) { + System.out.println(list.get(i)); + } + } +} diff --git a/javase_joly/src/Collection/Map/HashMapLearn.java b/javase_joly/src/Collection/Map/HashMapLearn.java new file mode 100644 index 00000000..d901a065 --- /dev/null +++ b/javase_joly/src/Collection/Map/HashMapLearn.java @@ -0,0 +1,15 @@ +package Collection.Map; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author jrl + * @date Create in 15:20 2021-11-20 + */ +public class HashMapLearn { + public static void main(String[] args) { + Map map = new HashMap<>(); + System.out.println(map.get("q")); + } +} diff --git a/javase_joly/src/Exception/ExceptionLearn.java b/javase_joly/src/Exception/ExceptionLearn.java new file mode 100644 index 00000000..aa28daec --- /dev/null +++ b/javase_joly/src/Exception/ExceptionLearn.java @@ -0,0 +1,43 @@ +package Exception; + +/** + * @author jrl + * @date Create in 14:32 2021-11-20 + */ +public class ExceptionLearn { + public static void main(String[] args) { + ExceptionLearn exceptionLearn = new ExceptionLearn(); +// exceptionLearn.子方法异常未做任何处理(); + exceptionLearn.处理异常信息(); + } + + private void basic() { + + try { + System.out.println("A执行"); + new ExceptionLearnB().a(); + System.out.println("B无异常则A继续执行"); + } catch (Exception e) { + System.out.println("A检测到B抛出的异常"); + } + } + + private void 子方法异常未做任何处理() { + try { + new ExceptionLearnB().对自身异常未做任何处理(); + System.out.println("子方法异常,执行失败,所以执行不到这行代码"); + } catch (Exception e) { + System.out.println("捕获到子方法的异常"); + } + } + + private void 处理异常信息() { + try { + new ExceptionLearnB().处理异常信息(); + } catch (Exception e) { +// String message = e.getMessage(); +// System.out.println("message:" + message); + e.printStackTrace(); + } + } +} diff --git a/javase_joly/src/Exception/ExceptionLearnB.java b/javase_joly/src/Exception/ExceptionLearnB.java new file mode 100644 index 00000000..2b3aeca5 --- /dev/null +++ b/javase_joly/src/Exception/ExceptionLearnB.java @@ -0,0 +1,42 @@ +package Exception; + +import java.rmi.UnexpectedException; + +/** + * @author jrl + * @date Create in 14:33 2021-11-20 + */ +public class ExceptionLearnB { + public void a() { + try { + try { + int a = 1 / 0; + System.out.println("B内部不会继续执行"); + } catch (Exception e) { + System.out.println("B-->a内部有异常"); + } + System.out.println("B外部继续执行"); + int a = 1 / 0; + } catch (ClassCastException e) { + System.out.println("B--->a外部有异常"); + System.out.println(e.getLocalizedMessage()); + System.out.println(e.getMessage()); +// e.printStackTrace(); + throw e; + } + + + } + + public void 对自身异常未做任何处理() { + int a = 1 / 0; + } + + public void 处理异常信息() { + try { + int a = 1 / 0; + } catch (Exception e) { + throw e; + } + } +} diff --git a/javase_joly/src/flow/SwitchLearn.java b/javase_joly/src/flow/SwitchLearn.java new file mode 100644 index 00000000..2da5de40 --- /dev/null +++ b/javase_joly/src/flow/SwitchLearn.java @@ -0,0 +1,22 @@ +package flow; + +/** + * @author jrl + * @date Create in 10:44 2021-11-22 + */ +public class SwitchLearn { + public static void main(String[] args) { + int a = 1; + switch (a) { + default: + /** knowledge point: defalut是不中才执行的,就算放在第一个也不会是默认执行的*/ + System.out.println("comes form default"); + case 1: + a = 3; + System.out.println("comes from 1"); + case 2: + System.out.println("comes from 2"); + + } + } +} diff --git a/javase_joly/src/someUtil/ForGgtype.java b/javase_joly/src/someUtil/ForGgtype.java new file mode 100644 index 00000000..0c39bade --- /dev/null +++ b/javase_joly/src/someUtil/ForGgtype.java @@ -0,0 +1,137 @@ +package someUtil; + +/** + * @author jrl + * @date Create in 2021-12-15 + */ +public class ForGgtype { + /** + * DangerCodeF + * fnof + * ClassificationX + * ClassificationB + *

+ * aaa + * bbb + * ---> + * 'aaa' ',bbb' + * 手动ctrl+r吧 + * @param + * @return + * @date 2021-12-15 + */ + public static void main(String[] args) { + String originalStr = + "'CustomerType',"+ + "'FDangerCode',"+ + "'policyStatus',"+ + "'ClassCodeF',"+ + "'RiskCodeF',"+ + "'DangerCodeF',"+ + "'fnof',"+ + "'ClassificationX',"+ + "'ClassificationB',"+ + "'yesOrNo',"+ + "'yesOrNo',"+ + "'ReinsuranceRiskLevel',"+ + "'yesOrNo',"+ + "'yesOrNo',"+ + "'CustomerType',"+ + "'CustomerType',"+ + "'CardTypeZ',"+ + "'Deductible',"+ + "'DSM',"+ + "'yesOrNo',"+ + "'noGuarantee',"+ + "'yesOrNo',"+ + "'ChargeMethod',"+ + "'RiskType',"+ + "'Jurisdiction',"+ + "'CDR',"+ + "'IfAgriculture',"+ + "'SubsidyNature',"+ + "'yesOrNo',"+ + "'ChannelName',"+ + "'ChannelType',"+ + "'yesOrNo',"+ + "'yesOrNo',"+ + "'PremiumCalculationMethod',"+ + "'PremiumChargeMethod',"+ + "'PaymentMethodProject',"+ + "'ReceivingDate',"+ + "'policyStatus',"+ + "'CustomerType',"+ + "'CardTypeZ',"+ + "'PolicyType',"+ + "'BusinessType',"+ + "'yesOrNo',"+ + "'yesOrNo',"+ + "'yesOrNo',"+ + "'yesOrNo',"+ + "'GProjectType',"+ + "'yesOrNo',"+ + "'yesOrNo',"+ + "'GuaranteeType',"+ + "'GProjectTypeTwo',"+ + "'ChargeMethod',"+ + "'PerformanceType',"+ + "'Completed',"+ + "'NatureOfLoan',"+ + "'LoanMethod',"+ + "'Repayment',"+ + "'TypeOfLoan',"+ + "'CreditType',"+ + "'LoanPurpose',"+ + "'noGuarantee',"+ + "'RepayAccountType',"+ + "'MasterOrSlave',"+ + "'MutualInsuranceType',"+ + "'IsItEffective',"+ + "'MonitoringLocation',"+ + "'LimitControlMethod',"+ + "'PremiumLimitMethod',"+ + "'OperatingCost',"+ + "'PremiumRatio',"+ + "'CollectionMethod',"+ + "'Dimension',"+ + "'ProjectStatusF',"+ + "'PremiumCalculationMethod',"+ + "'PremiumChargeMethod',"+ + "'PaymentMethodProject',"+ + "'ReceivingDate',"+ + "'ChargeDate',"+ + "'MarginWithdrawalMethod',"+ + "'CustomerType',"+ + "'CardTypeZ',"+ + "'Deductible',"+ + "'DSM',"+ + "'yesOrNo',"+ + "'noGuarantee',"+ + "'yesOrNo',"+ + "'ChargeMethod',"+ + "'RiskType',"+ + "'Jurisdiction',"+ + "'CDR',"+ + "'yesOrNo',"+ + "'ChannelName',"+ + "'ChannelType',"+ + "'NatureOfLoan',"+ + "'LoanMethod',"+ + "'Repayment',"+ + "'noGuarantee',"+ + "'TypeOfLoan',"+ + "'LoanPurpose',"+ + "'CreditType',"+ + "'MasterOrSlave',"+ + "'MutualInsuranceType',"+ + + "'IsItEffective',"+ + "'PerformanceType',"+ + + "'FDangerCode ',"; + System.out.println(originalStr); + String trim = originalStr.trim(); + System.out.println(trim); + + } +} diff --git a/javase_joly/src/someUtil/fastjson.java b/javase_joly/src/someUtil/fastjson.java new file mode 100644 index 00000000..57df620e --- /dev/null +++ b/javase_joly/src/someUtil/fastjson.java @@ -0,0 +1,13 @@ +package someUtil; + +/** + * fastjson + * + * @author jrl + * @date Create in 18:46 2021-11-23 + */ +public class fastjson { + public static void main(String[] args) { + + } +} diff --git a/production/01jvm/README.md b/production/01jvm/README.md new file mode 100644 index 00000000..f9021845 --- /dev/null +++ b/production/01jvm/README.md @@ -0,0 +1,119 @@ +# 第1周作业 + + +参见 我的教室 -> 本周作业 + +## 作业内容 + + +> Week01 作业题目: + +1.(选做)自己写一个简单的 Hello.java,里面需要涉及基本类型,四则运行,if 和 for,然后自己分析一下对应的字节码,有问题群里讨论。 + +2.(必做)自定义一个 Classloader,加载一个 Hello.xlass 文件,执行 hello 方法,此文件内容是一个 Hello.class 文件所有字节(x=255-x)处理后的文件。文件群里提供。 + +3.(必做)画一张图,展示 Xmx、Xms、Xmn、Meta、DirectMemory、Xss 这些内存参数的关系。 + +4.(选做)检查一下自己维护的业务系统的 JVM 参数配置,用 jstat 和 jstack、jmap 查看一下详情,并且自己独立分析一下大概情况,思考有没有不合理的地方,如何改进。 + +注意:如果没有线上系统,可以自己 run 一个 web/java 项目。 + +5.(选做)本机使用 G1 GC 启动一个程序,仿照课上案例分析一下 JVM 情况。 + + + +## 操作步骤 + + +### 作业1(选做) + +1. 编写代码, 根据自己的意愿随意编写, 可参考: [Hello.java](./Hello.java) +2. 编译代码, 执行命令: `javac -g Hello.java` +3. 查看反编译的代码。 + - 3.1 可以安装并使用idea的jclasslib插件, 选中 [Hello.java](./Hello.java) 文件, 选择 `View --> Show Bytecode With jclasslib` 即可。 + - 3.2 或者直接通过命令行工具 javap, 执行命令: `javap -v Hello.class` +4. 分析相关的字节码。【此步骤需要各位同学自己进行分析】 + + +### 作业2(必做) + +1. 打开 Spring 官网: https://spring.io/ +2. 找到 Projects --> Spring Initializr: https://start.spring.io/ +3. 填写项目信息, 生成 maven 项目; 下载并解压。 +4. Idea或者Eclipse从已有的Source导入Maven项目。 +5. 从课件资料中找到资源 Hello.xlass 文件并复制到 src/main/resources 目录。 +6. 编写代码,实现 findClass 方法,以及对应的解码方法 +7. 编写main方法,调用 loadClass 方法; +8. 创建实例,以及调用方法 +9. 执行. + +具体代码可参考: [XlassLoader.java](./XlassLoader.java) + + +### 作业3(必做) + +对应的图片需要各位同学自己绘制,可以部分参考PPT课件。 + +提示: + +- Xms 设置堆内存的初始值 +- Xmx 设置堆内存的最大值 +- Xmn 设置堆内存中的年轻代的最大值 +- Meta 区不属于堆内存, 归属为非堆 +- DirectMemory 直接内存, 属于 JVM 内存中开辟出来的本地内存空间。 +- Xss设置的是单个线程栈的最大空间; + +JVM进程空间中的内存一般来说包括以下这些部分: + +- 堆内存(Xms ~ Xmx) = 年轻代(~Xmn) + 老年代 +- 非堆 = Meta + CodeCache + ... +- Native内存 = 直接内存 + Native + ... +- 栈内存 = n * Xss + +另外,注意区分规范与实现的区别, 需要根据具体实现以及版本, 才能确定。 一般来说,我们的目的是为了排查故障和诊断问题,大致弄清楚这些参数和空间的关系即可。 具体设置时还需要留一些冗余量。 + + +### 4.(选做) + +这个是具体案例分析, 请各位同学自己分析。 + +比如我们一个生产系统应用的启动参数为: + +``` +JAVA_OPTS=-Xmx200g -Xms200g -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZCollectionInterval=30 -XX:ZAllocationSpikeTolerance=5 -XX:ReservedCodeCacheSize=2g -XX:InitialCodeCacheSize=2g -XX:ConcGCThreads=8 -XX:ParallelGCThreads=16 +``` + +另一个系统的启动参数为: + +``` +JAVA_OPTS=-Xmx4g -Xms4g -XX:+UseG1GC -XX:MaxGCPauseMillis=50 +``` + +具体如何设置, 需要考虑的因素包括: + +- 系统容量: 业务规模, 并发, 成本预算; 需要兼顾性能与成本; +- 延迟要求: 最坏情况下能接受多少时间的延迟尖刺。 +- 吞吐量: 根据业务特征来确定, 比如, 网关, 大数据底层平台, 批处理作业系统, 在线实时应用, 他们最重要的需求不一样。 +- 系统架构: 比如拆分为小内存更多节点, 还是大内存少量节点。 +- 其他... + + +### 5.(选做) + +例如使用以下命令: + +``` +# 编译 +javac -g GCLogAnalysis.java +# JDK8 启动程序 +java -Xmx2g -Xms2g -XX:+UseG1GC -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:gc.log GCLogAnalysis +``` + +尝试使用课程中介绍的各种工具JDK命令行和图形工具来进行分析。 + +其中 [GCLogAnalysis.java](./GCLogAnalysis.java) 文件也可以从课件资料zip中找到. + +## 更多资料 + +更多中英文的技术文章和参考资料: + diff --git a/production/01jvm/out/production/01jvm/README.md b/production/01jvm/out/production/01jvm/README.md new file mode 100644 index 00000000..d74bbed1 --- /dev/null +++ b/production/01jvm/out/production/01jvm/README.md @@ -0,0 +1,41 @@ +# 第1周作业 + + +参见 我的教室 -> 本周作业 + +## 作业内容 + + +> Week01 作业题目(周四): + +1.(选做)自己写一个简单的 Hello.java,里面需要涉及基本类型,四则运行,if 和 for,然后自己分析一下对应的字节码,有问题群里讨论。 + +2.(必做)自定义一个 Classloader,加载一个 Hello.xlass 文件,执行 hello 方法,此文件内容是一个 Hello.class 文件所有字节(x=255-x)处理后的文件。文件群里提供。 + +3.(必做)画一张图,展示 Xmx、Xms、Xmn、Meta、DirectMemory、Xss 这些内存参数的关系。 + +4.(选做)检查一下自己维护的业务系统的 JVM 参数配置,用 jstat 和 jstack、jmap 查看一下详情,并且自己独立分析一下大概情况,思考有没有不合理的地方,如何改进。 + +注意:如果没有线上系统,可以自己 run 一个 web/java 项目。 + +> Week01 作业题目(周六): + +1.(选做)本机使用 G1 GC 启动一个程序,仿照课上案例分析一下 JVM 情况。 + + +## 操作步骤 + + +### 作业2 + +1. 打开 Spring 官网: https://spring.io/ +2. 找到 Projects --> Spring Initializr: https://start.spring.io/ +3. 填写项目信息, 生成 maven 项目; 下载并解压。 +4. Idea或者Eclipse从已有的Source导入Maven项目。 +5. 增加课程资源 Hello.xlass 文件到 src/main/resources 目录。 +6. 编写代码,实现 findClass 方法,解码方法 +7. 编写main方法,调用 loadClass 方法; +8. 创建实例,以及调用方法 +9. 执行. + +具体的参见: [https://github.com/renfufei/JAVA-000/blob/main/Week_01/homework01/src/main/java/com/renfufei/homework01/XlassLoader.java](XlassLoader.java) diff --git "a/production/01jvm/out/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" "b/production/01jvm/out/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" new file mode 100644 index 00000000..8fcc7d21 --- /dev/null +++ "b/production/01jvm/out/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" @@ -0,0 +1,38 @@ + + +## Windows + +1.管理员身份打开powershell + +2.运行 +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + +3.执行choco install superbenchmarker + +4.输入 sb + +执行 sb -u http://localhost:8088/api/hello -c 20 -N 60 + +## Mac + +1.执行brew install wrk +如果显式brew update很慢,可以ctrl+C打断更新 + +2.输入 wrk + +执行 wrk -t8 -c40 -d60s http://localhost:8088/api/hello + +## 压测程序 + +1.可以从github获取 +git clone https://github.com/kimmking/atlantis +cd atlantis\gateway-server +mvn clean package +然后在target目录可以找到gateway-server-0.0.1-SNAPSHOT.jar + +2.也可以从此处下载已经编译好的: +链接:https://pan.baidu.com/s/1NbpYX4M3YKLYM1JJeIzgSQ +提取码:sp85 + +java -jar -Xmx512m -Xms512m gateway-server-0.0.1-SNAPSHOT.jar + diff --git "a/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" "b/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" new file mode 100644 index 00000000..361ed5c2 --- /dev/null +++ "b/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" @@ -0,0 +1,38 @@ + + +## Windows + +1.管理员身份打开powershell + +2.运行 +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + +3.执行choco install superbenchmarker + +4.输入 sb + +执行 sb -u http://localhost:8088/api/hello -c 20 -N 60 + +## Mac + +1.执行brew install wrk +如果显式brew update很慢,可以ctrl+C打断更新 + +2.输入 wrk + +执行 wrk -t8 -c40 -d60s http://localhost:8088/api/hello + +## 压测程序 + +1.可以从github获取 +git clone https://github.com/kimmking/atlantis +cd atlantis\gateway-server +mvn clean package +然后在target目录可以找到gateway-server-0.0.1-SNAPSHOT.jar + +2.也可以从此处下载已经编译好的: +链接:https://pan.baidu.com/s/1NbpYX4M3YKLYM1JJeIzgSQ +提取码:sp85 + +java -jar -Xmx512m -Xms512 gateway-server-0.0.1-SNAPSHOT.jar +