From 616857e3019fa5b60f11d966225893123121c120 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Thu, 23 Sep 2021 14:45:02 +0800 Subject: [PATCH 01/64] netty 1 --- .../java/java0/nio01/netty/HttpHandler.java | 21 +++++++++++--- .../java0/nio01/netty/HttpInitializer.java | 28 +++++++++++++------ .../java0/nio01/netty/NettyHttpServer.java | 10 +++++-- 3 files changed, 44 insertions(+), 15 deletions(-) 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(); From f416643eeb0749f19fcbba444bec1b9a426bbdf3 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Tue, 28 Sep 2021 18:03:51 +0800 Subject: [PATCH 02/64] gateway --- 02nio/nio02/README.md | 6 +- .../gateway/NettyServerApplication.java | 19 ++++--- .../gateway/inbound/HttpInboundHandler.java | 20 +++++-- .../inbound/HttpInboundInitializer.java | 37 ++++++++----- .../gateway/inbound/HttpInboundServer.java | 46 ++++++++++++++-- .../httpclient4/HttpOutboundHandler.java | 55 +++++++++++-------- .../gateway/router/HttpEndpointRouter.java | 14 ++++- .../router/RandomHttpEndpointRouter.java | 5 +- 8 files changed, 142 insertions(+), 60 deletions(-) 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..541ebf49 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,17 @@ import java.util.Arrays; +/** + * @author 小虫子的小日常 + */ 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"); @@ -22,14 +25,16 @@ public static void main(String[] args) { // 这是多个后端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..."); + // todo HttpInboundServer是什么 + // todo 不应该是用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..a2ada3c3 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,28 @@ 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; + /** + * todo doubt: 这个是拿来干嘛的 + */ private HttpOutboundHandler handler; private HttpRequestFilter filter = new HeaderHttpRequestFilter(); - + public HttpInboundHandler(List proxyServer) { this.proxyServer = proxyServer; + /** todo doubt: 为什么要用outboundHandler来赋给inboundHandler */ this.handler = new HttpOutboundHandler(this.proxyServer); } - + @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); @@ -39,10 +49,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..2a1b6612 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..6cf9dcd5 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 @@ -33,7 +33,7 @@ import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; public class HttpOutboundHandler { - + private CloseableHttpAsyncClient httpclient; private ExecutorService proxyService; private List backendUrls; @@ -42,43 +42,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,为什么要启动它*/ 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 +104,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 +128,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 +162,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) { From 1f173c2663e256fb00c0f11db15af7faf61b7d35 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Mon, 11 Oct 2021 18:25:38 +0800 Subject: [PATCH 03/64] gateway --- .../kimmking/gateway/NettyServerApplication.java | 12 ++++++++---- .../kimmking/gateway/inbound/HttpInboundHandler.java | 4 ---- .../kimmking/gateway/inbound/HttpInboundServer.java | 2 +- .../outbound/httpclient4/HttpOutboundHandler.java | 5 ++++- 4 files changed, 13 insertions(+), 10 deletions(-) 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 541ebf49..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 @@ -6,7 +6,11 @@ import java.util.Arrays; /** - * @author 小虫子的小日常 + * knowledge point: + * 个人认为:用netty实现gateway需要实现的功能点是: + * 1.设置好gateway的端口和要代理的服务的端口 + * 2.把客户端的请求准确的传递到被代理的服务中 + * 3.做一些过滤器和路由的附加操作 */ public class NettyServerApplication { @@ -23,13 +27,13 @@ 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"); int port = Integer.parseInt(proxyPort); System.out.println(GATEWAY_NAME + " " + GATEWAY_VERSION + " starting..."); - // todo HttpInboundServer是什么 - // todo 不应该是用netty写的什么server吗,那么这个httpInboundServer就是用netty框架写的nio的服务是吗 + // 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()); try { 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 a2ada3c3..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 @@ -22,15 +22,11 @@ public class HttpInboundHandler extends ChannelInboundHandlerAdapter { private static Logger logger = LoggerFactory.getLogger(HttpInboundHandler.class); private final List proxyServer; - /** - * todo doubt: 这个是拿来干嘛的 - */ private HttpOutboundHandler handler; private HttpRequestFilter filter = new HeaderHttpRequestFilter(); public HttpInboundHandler(List proxyServer) { this.proxyServer = proxyServer; - /** todo doubt: 为什么要用outboundHandler来赋给inboundHandler */ this.handler = new HttpOutboundHandler(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 2a1b6612..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 @@ -48,7 +48,7 @@ public HttpInboundServer(int port, List proxyServers) { } /** - * 这是被执行的主体方法 + * 这是整个服务真正核心被执行的方法 * Netty实现了Reactor的主从模型 * * @param 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 6cf9dcd5..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,6 +32,9 @@ 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; @@ -60,7 +63,7 @@ public HttpOutboundHandler(List backends) { .setIoThreadCount(cores) .setRcvBufSize(32 * 1024) .build(); - /** todo doubt: 什么是httpclient,为什么要启动它*/ + /** todo doubt: 这是啥*/ httpclient = HttpAsyncClients.custom().setMaxConnTotal(40) .setMaxConnPerRoute(8) .setDefaultIOReactorConfig(ioConfig) From ff1023839d151ddef67170d1572c11ea859aff87 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Wed, 13 Oct 2021 15:12:35 +0800 Subject: [PATCH 04/64] thread --- .../java/java0/conc0301/jrl/ThreadJoin.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 03concurrency/0301/src/main/java/java0/conc0301/jrl/ThreadJoin.java diff --git a/03concurrency/0301/src/main/java/java0/conc0301/jrl/ThreadJoin.java b/03concurrency/0301/src/main/java/java0/conc0301/jrl/ThreadJoin.java new file mode 100644 index 00000000..e5ab9362 --- /dev/null +++ b/03concurrency/0301/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线程结束"); + } +} From 00177da6220ee5d937d327a43b07c8e5f1cfc457 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Tue, 26 Oct 2021 17:52:50 +0800 Subject: [PATCH 05/64] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E5=91=A8=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=90=8E=E8=BF=90=E8=A1=8C=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/java0/conc0301/DaemonThread.java | 1 + .../main/java/java0/conc0301/RunnerMain.java | 4 ++-- .../src/main/java/java0/conc0301/op/Join.java | 5 +++-- .../java/java0/conc0301/op/WaitAndNotify.java | 22 +++++++++---------- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java b/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java index acaea31e..cc842448 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java @@ -14,6 +14,7 @@ public static void main(String[] args) throws InterruptedException { }; Thread thread = new Thread(task); thread.setName("test-thread-1"); + /** knowledge point: setDaemon()需要在start()之前,否则会抛运行时异常*/ thread.setDaemon(true); thread.start(); diff --git a/03concurrency/0301/src/main/java/java0/conc0301/RunnerMain.java b/03concurrency/0301/src/main/java/java0/conc0301/RunnerMain.java index 626f2d38..695ab680 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/RunnerMain.java +++ b/03concurrency/0301/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/op/Join.java b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java index 1cbf6a5a..a101a232 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java @@ -14,8 +14,9 @@ public static void main(String[] args) { for (int i = 0; i < 100; i++) { if (i == 20) { try { - oo.wait(0); - //thread1.join(); +// oo.wait(); + // todo 傻逼 回去再看一遍 join 和 wait + thread1.join(); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java b/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java index e3956c10..61660faf 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java @@ -19,17 +19,17 @@ 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(); } } @@ -43,7 +43,7 @@ class MethodClass { 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("货舱已满,,.不必再生产"); @@ -59,7 +59,7 @@ public synchronized void product() throws InterruptedException { 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(); From a135b298b95b4ca81ebae4832096ad1d76bbb2cd Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Wed, 27 Oct 2021 10:50:57 +0800 Subject: [PATCH 06/64] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E5=91=A8=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=90=8E=E8=BF=90=E8=A1=8C=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/java0/conc0301/op/Join.java | 43 ++++++++++++------- .../conc0302/lock/jrl/LockProperties.java | 38 ++++++++++++++++ 2 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 03concurrency/0301/src/main/java/java0/conc0302/lock/jrl/LockProperties.java diff --git a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java index a101a232..6ddc59e2 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java @@ -1,22 +1,25 @@ package java0.conc0301.op; public class Join { - - public static void main(String[] args) { + + 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()); synchronized (oo) { // 这里用oo或thread1/this - for (int i = 0; i < 100; i++) { - if (i == 20) { + for (int i = 0; i < 10; i++) { + if (i == 2) { try { -// oo.wait(); - // todo 傻逼 回去再看一遍 join 和 wait - thread1.join(); + oo.wait(); +// System.out.println("main before join----" + Thread.holdsLock(oo)); + /** knowledge point: 对呀,join是不会释放锁的*/ +// thread1.join(); +// System.out.println("main after join----" + Thread.holdsLock(oo)); } catch (InterruptedException e) { e.printStackTrace(); } @@ -25,29 +28,37 @@ public static void main(String[] args) { } } } - + } 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() { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("thread1 Lock:" + oo.toString()); + System.out.println("thread1----" + Thread.holdsLock(oo)); synchronized (oo) { // 这里用oo或this,效果不同 - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 10; i++) { System.out.println(name + i); } + oo.notify(); } } - + } \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/jrl/LockProperties.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/jrl/LockProperties.java new file mode 100644 index 00000000..798dce59 --- /dev/null +++ b/03concurrency/0301/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 From 08fe4aeac57121995c963d05cae4afc8fe9aadba Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Wed, 3 Nov 2021 17:59:22 +0800 Subject: [PATCH 07/64] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E5=91=A8=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=90=8E=E8=BF=90=E8=A1=8C=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/java0/conc0301/op/Join.java | 18 ++++++++++----- .../java/java0/conc0301/sync/Thread2.java | 11 ++++++---- .../conc0302/threadpool/ExceptionDemo.java | 22 +++++++++++++------ .../threadpool/ExecutorServiceDemo.java | 7 ++++++ 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java index 6ddc59e2..362380d5 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java @@ -1,24 +1,30 @@ package java0.conc0301.op; -public class Join { +public class Join { public static void main(String[] args) throws InterruptedException { Object oo = new Object(); MyThread thread1 = new MyThread("thread1 -- "); - //oo = 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(); +// oo.wait(); // System.out.println("main before join----" + Thread.holdsLock(oo)); - /** knowledge point: 对呀,join是不会释放锁的*/ -// thread1.join(); + /** knowledge point: 对呀,join是不会释放对象锁的,但是会释放对象为线程的锁,这里就是对thread1的锁会被main释放掉*/ + thread1.join(); // System.out.println("main after join----" + Thread.holdsLock(oo)); } catch (InterruptedException e) { e.printStackTrace(); @@ -57,7 +63,7 @@ public void run() { for (int i = 0; i < 10; i++) { System.out.println(name + i); } - oo.notify(); +// oo.notify(); } } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java b/03concurrency/0301/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/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/conc0302/threadpool/ExceptionDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java index 22240c51..c014872d 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java @@ -4,19 +4,26 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; +/** + * knowledge point: + * 1.当子线程(异步)抛出异常后会影响主线程吗?--->在同一个try里的代码会被影响,其他的不会 + * 2.Future能够拿到子线程的异常,那么具体都有什么内容呢?--->可以直接catch拿到子线程抛出来的异常 + * 3.子线程异常了以后,在主线程中shutdown子线程,会抛异常吗?--->不会,就正常执行。 + * 甚至子线程当前还有任务正在执行的话,不会强行关闭,而是等执行完了当前任务,再关闭子线程,也就是所谓的优雅停机。 + */ 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 +38,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/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/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() { From 6b277883f6f38d10dcf76dc77322d34737797ff4 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Sat, 20 Nov 2021 18:13:47 +0800 Subject: [PATCH 08/64] exception --- javase/src/Collection/List/Practice100.java | 28 +++++++++++++++++++ javase/src/Collection/Map/HashMapLearn.java | 15 +++++++++++ javase/src/Exception/ExceptionLearn.java | 17 ++++++++++++ javase/src/Exception/ExceptionLearnB.java | 30 +++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 javase/src/Collection/List/Practice100.java create mode 100644 javase/src/Collection/Map/HashMapLearn.java create mode 100644 javase/src/Exception/ExceptionLearn.java create mode 100644 javase/src/Exception/ExceptionLearnB.java diff --git a/javase/src/Collection/List/Practice100.java b/javase/src/Collection/List/Practice100.java new file mode 100644 index 00000000..3ddbbe55 --- /dev/null +++ b/javase/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/src/Collection/Map/HashMapLearn.java b/javase/src/Collection/Map/HashMapLearn.java new file mode 100644 index 00000000..d901a065 --- /dev/null +++ b/javase/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/src/Exception/ExceptionLearn.java b/javase/src/Exception/ExceptionLearn.java new file mode 100644 index 00000000..c9a932f6 --- /dev/null +++ b/javase/src/Exception/ExceptionLearn.java @@ -0,0 +1,17 @@ +package Exception; + +/** + * @author jrl + * @date Create in 14:32 2021-11-20 + */ +public class ExceptionLearn { + public static void main(String[] args) { + try { + System.out.println("A执行"); + new ExceptionLearnB().a(); + System.out.println("B无异常则A继续执行"); + } catch (Exception e) { + System.out.println("A检测到B抛出的异常"); + } + } +} diff --git a/javase/src/Exception/ExceptionLearnB.java b/javase/src/Exception/ExceptionLearnB.java new file mode 100644 index 00000000..db4f0982 --- /dev/null +++ b/javase/src/Exception/ExceptionLearnB.java @@ -0,0 +1,30 @@ +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; + } + + + } +} From 20fd301b6954fdd11552234598170ae2e21b80b6 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Tue, 23 Nov 2021 18:13:13 +0800 Subject: [PATCH 09/64] exception --- javase/src/BigDecimal/BigDecimalBasic.java | 16 ++++++++++++++ .../src/Collection/List/ArrayListLearn.java | 11 ++++++++++ javase/src/Exception/ExceptionLearn.java | 15 +++++++++++++ javase/src/Exception/ExceptionLearnB.java | 4 ++++ javase/src/flow/SwitchLearn.java | 22 +++++++++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 javase/src/BigDecimal/BigDecimalBasic.java create mode 100644 javase/src/Collection/List/ArrayListLearn.java create mode 100644 javase/src/flow/SwitchLearn.java diff --git a/javase/src/BigDecimal/BigDecimalBasic.java b/javase/src/BigDecimal/BigDecimalBasic.java new file mode 100644 index 00000000..28a3b73c --- /dev/null +++ b/javase/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/src/Collection/List/ArrayListLearn.java b/javase/src/Collection/List/ArrayListLearn.java new file mode 100644 index 00000000..c12bb83c --- /dev/null +++ b/javase/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/src/Exception/ExceptionLearn.java b/javase/src/Exception/ExceptionLearn.java index c9a932f6..5e88902b 100644 --- a/javase/src/Exception/ExceptionLearn.java +++ b/javase/src/Exception/ExceptionLearn.java @@ -6,6 +6,12 @@ */ public class ExceptionLearn { public static void main(String[] args) { + ExceptionLearn exceptionLearn = new ExceptionLearn(); + exceptionLearn.子方法异常未做任何处理(); + } + + private void basic() { + try { System.out.println("A执行"); new ExceptionLearnB().a(); @@ -14,4 +20,13 @@ public static void main(String[] args) { System.out.println("A检测到B抛出的异常"); } } + + private void 子方法异常未做任何处理() { + try { + new ExceptionLearnB().对自身异常未做任何处理(); + System.out.println("子方法异常,执行失败,所以执行不到这行代码"); + } catch (Exception e) { + System.out.println("捕获到子方法的异常"); + } + } } diff --git a/javase/src/Exception/ExceptionLearnB.java b/javase/src/Exception/ExceptionLearnB.java index db4f0982..4f4097a9 100644 --- a/javase/src/Exception/ExceptionLearnB.java +++ b/javase/src/Exception/ExceptionLearnB.java @@ -27,4 +27,8 @@ public void a() { } + + public void 对自身异常未做任何处理() { + int a = 1 / 0; + } } diff --git a/javase/src/flow/SwitchLearn.java b/javase/src/flow/SwitchLearn.java new file mode 100644 index 00000000..2da5de40 --- /dev/null +++ b/javase/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"); + + } + } +} From 380c3d8a41b25c8c09872e794413136a6ac689c5 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Mon, 29 Nov 2021 18:02:12 +0800 Subject: [PATCH 10/64] exception+fastjson --- .../main/java/io/kimmking/utilsJ/Person.java | 31 +++++++++++++++++++ .../java/io/kimmking/utilsJ/fastjson.java | 30 ++++++++++++++++++ javase/src/Exception/ExceptionLearn.java | 13 +++++++- javase/src/Exception/ExceptionLearnB.java | 8 +++++ javase/src/someUtil/fastjson.java | 13 ++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java create mode 100644 javase/src/someUtil/fastjson.java 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..abc3a198 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java @@ -0,0 +1,31 @@ +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 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..c65294ae --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java @@ -0,0 +1,30 @@ +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); + } +} diff --git a/javase/src/Exception/ExceptionLearn.java b/javase/src/Exception/ExceptionLearn.java index 5e88902b..aa28daec 100644 --- a/javase/src/Exception/ExceptionLearn.java +++ b/javase/src/Exception/ExceptionLearn.java @@ -7,7 +7,8 @@ public class ExceptionLearn { public static void main(String[] args) { ExceptionLearn exceptionLearn = new ExceptionLearn(); - exceptionLearn.子方法异常未做任何处理(); +// exceptionLearn.子方法异常未做任何处理(); + exceptionLearn.处理异常信息(); } private void basic() { @@ -29,4 +30,14 @@ private void basic() { 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/src/Exception/ExceptionLearnB.java b/javase/src/Exception/ExceptionLearnB.java index 4f4097a9..2b3aeca5 100644 --- a/javase/src/Exception/ExceptionLearnB.java +++ b/javase/src/Exception/ExceptionLearnB.java @@ -31,4 +31,12 @@ public void a() { public void 对自身异常未做任何处理() { int a = 1 / 0; } + + public void 处理异常信息() { + try { + int a = 1 / 0; + } catch (Exception e) { + throw e; + } + } } diff --git a/javase/src/someUtil/fastjson.java b/javase/src/someUtil/fastjson.java new file mode 100644 index 00000000..57df620e --- /dev/null +++ b/javase/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) { + + } +} From 7ceec933f6fbed801c19f3d2f153db35f515d8bd Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 5 Dec 2021 21:26:50 +0800 Subject: [PATCH 11/64] oo --- .../java/java0/conc0301/DaemonThread.java | 31 ++++++--- .../java0/conc0301/jrl/HighConcurrency.java | 30 +++++++++ .../src/main/java/java0/conc0301/op/Join.java | 28 +++----- .../java/java0/conc0301/sync/Counter.java | 21 ++++-- .../src/main/java/jrl/ClassLoaderLearn.java | 28 ++++++++ .../src/main/java/io/kimmking/jrl/inter.java | 16 +++++ .../java/io/kimmking/spring01/Student.java | 8 +-- .../main/java/io/kimmking/spring02/Aop1.java | 40 ++++++------ .../main/java/io/kimmking/spring02/Aop2.java | 26 ++++---- .../main/java/io/kimmking/spring02/Klass.java | 10 +-- .../java/io/kimmking/spring02/School.java | 16 ++--- .../io/kimmking/spring02/SpringDemo01.java | 30 ++++----- .../src/main/resources/applicationContext.xml | 64 +++++++++---------- 13 files changed, 218 insertions(+), 130 deletions(-) create mode 100644 03concurrency/0301/src/main/java/java0/conc0301/jrl/HighConcurrency.java create mode 100644 04fx/java8/src/main/java/jrl/ClassLoaderLearn.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/inter.java diff --git a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java b/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java index cc842448..d1fa53a8 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java @@ -1,24 +1,39 @@ 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); + try { + Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } - Thread t = Thread.currentThread(); - System.out.println("当前线程:" + t.getName()); + Thread t = Thread.currentThread(); + System.out.println("当前线程:" + t.getName()); }; Thread thread = new Thread(task); thread.setName("test-thread-1"); - /** knowledge point: setDaemon()需要在start()之前,否则会抛运行时异常*/ + /** knowledge point: + * 设置该线程为守护线程 + * setDaemon()需要在start()之前,否则会抛运行时异常 + */ thread.setDaemon(true); thread.start(); - - //Thread.sleep(5500); + /** knowledge point: + * 可以通过增加main线程的执行时间,来让守护线程被执行(因为守护线程需要大概五秒) + */ + Thread.sleep(5500); } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/jrl/HighConcurrency.java b/03concurrency/0301/src/main/java/java0/conc0301/jrl/HighConcurrency.java new file mode 100644 index 00000000..9af26bce --- /dev/null +++ b/03concurrency/0301/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/src/main/java/java0/conc0301/op/Join.java b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java index 362380d5..41c7ea7c 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java @@ -1,8 +1,8 @@ package java0.conc0301.op; -public class Join { - - public static void main(String[] args) throws InterruptedException { +public class Join { + + public static void main(String[] args) { Object oo = new Object(); MyThread thread1 = new MyThread("thread1 -- "); @@ -34,37 +34,29 @@ public static void main(String[] args) throws InterruptedException { } } } - + } 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() { - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("thread1 Lock:" + oo.toString()); - System.out.println("thread1----" + Thread.holdsLock(oo)); synchronized (oo) { // 这里用oo或this,效果不同 - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 100; i++) { System.out.println(name + i); } -// oo.notify(); } } - + } \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java b/03concurrency/0301/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/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/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/spring01/src/main/java/io/kimmking/jrl/inter.java b/04fx/spring01/src/main/java/io/kimmking/jrl/inter.java new file mode 100644 index 00000000..fc6dcc63 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/inter.java @@ -0,0 +1,16 @@ +package io.kimmking.jrl; + +public interface inter { + public static final int A = 1; + + public default void me() { + + } + + public static void me2() { + + } + + + public void me3(); +} 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..484a840d 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -26,12 +26,12 @@ public class Student implements Serializable, BeanNameAware, ApplicationContextA private String beanName; private ApplicationContext applicationContext; - public void init(){ + 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(102, "KK102", null, null); } public void print() { 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..48d3936f 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java @@ -3,24 +3,24 @@ import org.aspectj.lang.ProceedingJoinPoint; 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 + } + + //环绕通知 + public void around(ProceedingJoinPoint joinPoint) throws Throwable { + System.out.println(" ====>around begin ding"); //1 + //调用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..2ad2d1ed 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java @@ -10,28 +10,28 @@ @Aspect public class Aop2 { - - @Pointcut(value="execution(* io.kimmking.*.Klass.*dong(..))") - public void point(){ - + + @Pointcut(value = "execution(* io.kimmking.*.Klass.*dong(..))") + public void point() { + } - - @Before(value="point()") - public void before(){ + + @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"); joinPoint.proceed(); System.out.println("========>around after klass dong //3"); - + } - + } 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..8c1d91bd 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java @@ -6,12 +6,12 @@ import java.util.List; @Data -public class Klass { - +public class Klass { + List students; - - public void dong(){ + + public void dong() { System.out.println(this.getStudents()); } - + } 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..99a943a6 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/School.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/School.java @@ -9,19 +9,19 @@ @Data public class School implements ISchool { - + // 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..cae24f1b 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java @@ -6,40 +6,40 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringDemo01 { - + public static void main(String[] args) { - + ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // Student student123 = context.getBean(Student.class); - + Student student123 = (Student) context.getBean("student123"); System.out.println(student123.toString()); student123.print(); - + Student student100 = (Student) context.getBean("student100"); System.out.println(student100.toString()); 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()); + 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())); + + System.out.println(" context.getBeanDefinitionNames() ===>> " + String.join(",", context.getBeanDefinitionNames())); Student s101 = (Student) context.getBean("s101"); if (s101 != null) { diff --git a/04fx/spring01/src/main/resources/applicationContext.xml b/04fx/spring01/src/main/resources/applicationContext.xml index 681cf409..6d09cd3c 100644 --- a/04fx/spring01/src/main/resources/applicationContext.xml +++ b/04fx/spring01/src/main/resources/applicationContext.xml @@ -7,55 +7,55 @@ http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context 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 From 011481dfb72dba122e245d38f5bd1f044253db15 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 5 Dec 2021 21:58:49 +0800 Subject: [PATCH 12/64] =?UTF-8?q?=E7=B1=BB=E5=8A=A0=E8=BD=BD--->=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04fx/java8/src/main/java/jrl/ConstClass.java | 9 ++++ .../src/main/java/jrl/NotInitialization.java | 43 +++++++++++++++++++ 04fx/java8/src/main/java/jrl/SubClass.java | 7 +++ 04fx/java8/src/main/java/jrl/SuperClass.java | 9 ++++ 4 files changed, 68 insertions(+) create mode 100644 04fx/java8/src/main/java/jrl/ConstClass.java create mode 100644 04fx/java8/src/main/java/jrl/NotInitialization.java create mode 100644 04fx/java8/src/main/java/jrl/SubClass.java create mode 100644 04fx/java8/src/main/java/jrl/SuperClass.java 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/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/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; +} From 3a1d40193a2307147a14d97982693da09fa7ec30 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Mon, 6 Dec 2021 10:24:01 +0800 Subject: [PATCH 13/64] fastjson --- 04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java | 5 +++++ 04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java | 3 +++ 2 files changed, 8 insertions(+) diff --git a/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java b/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java index abc3a198..97f9218c 100644 --- a/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java +++ b/04fx/spring01/src/main/java/io/kimmking/utilsJ/Person.java @@ -13,6 +13,11 @@ public Person(int age, String name) { this.name = name; } + public Person(int age) { + this.age = age; + + } + public int getAge() { return age; } diff --git a/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java b/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java index c65294ae..7e4718ac 100644 --- a/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java +++ b/04fx/spring01/src/main/java/io/kimmking/utilsJ/fastjson.java @@ -26,5 +26,8 @@ public static void main(String[] args) { //将对象转为json形式的字符串 String s = JSON.toJSONString(p); System.out.println(s); + //如果java对象的属性没有赋值,则输出的json字符串对应的属性直接不展示 + Person p1 = new Person(12); + System.out.println(JSON.toJSONString(p1)); } } From 8566bba5ec47c90e0a3587bc6948ea2f71b7ab0a Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Mon, 20 Dec 2021 09:33:57 +0800 Subject: [PATCH 14/64] others --- .../springboot01/Springboot01Application.java | 6 +- app/src/main/java/com/example/app/App.java | 6 +- .../com/example/app/WebAutoConfiguration.java | 7 +- .../com/example/app/WebConfiguration.java | 3 + javase/src/Basic/IntegerLearn.java | 13 ++ javase/src/someUtil/ForGgtype.java | 137 ++++++++++++++++++ 6 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 javase/src/Basic/IntegerLearn.java create mode 100644 javase/src/someUtil/ForGgtype.java 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/app/src/main/java/com/example/app/App.java b/app/src/main/java/com/example/app/App.java index bcd641a1..9a70eccc 100644 --- a/app/src/main/java/com/example/app/App.java +++ b/app/src/main/java/com/example/app/App.java @@ -5,6 +5,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +/** + * knowledge point: springboot 的入口点 + */ @SpringBootApplication public class App { @@ -13,13 +16,12 @@ public static void main(String[] args) { } - // ==== 测试自动配置 ==== @Autowired WebInfo info; @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/app/src/main/java/com/example/app/WebAutoConfiguration.java index e63d295f..e74c3e73 100644 --- a/app/src/main/java/com/example/app/WebAutoConfiguration.java +++ b/app/src/main/java/com/example/app/WebAutoConfiguration.java @@ -6,6 +6,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +/** + * knowledge point: @Import 用来当前类是用来自动装配被引入的那个类的 + */ @Configuration @Import(WebConfiguration.class) @EnableConfigurationProperties(WebProperties.class) @@ -18,8 +21,8 @@ public class WebAutoConfiguration { 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/app/src/main/java/com/example/app/WebConfiguration.java index d645d77b..6ea3b6c5 100644 --- a/app/src/main/java/com/example/app/WebConfiguration.java +++ b/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/javase/src/Basic/IntegerLearn.java b/javase/src/Basic/IntegerLearn.java new file mode 100644 index 00000000..b721925a --- /dev/null +++ b/javase/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/src/someUtil/ForGgtype.java b/javase/src/someUtil/ForGgtype.java new file mode 100644 index 00000000..0c39bade --- /dev/null +++ b/javase/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); + + } +} From a03904cee7ac07b7f5aa0620cc546fcbf6b43d77 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Mon, 20 Dec 2021 20:22:12 +0800 Subject: [PATCH 15/64] others --- {javase => javase_joly}/src/Basic/IntegerLearn.java | 0 {javase => javase_joly}/src/BigDecimal/BigDecimalBasic.java | 0 {javase => javase_joly}/src/Collection/List/ArrayListLearn.java | 0 {javase => javase_joly}/src/Collection/List/Practice100.java | 0 {javase => javase_joly}/src/Collection/Map/HashMapLearn.java | 0 {javase => javase_joly}/src/Exception/ExceptionLearn.java | 0 {javase => javase_joly}/src/Exception/ExceptionLearnB.java | 0 {javase => javase_joly}/src/flow/SwitchLearn.java | 0 {javase => javase_joly}/src/someUtil/ForGgtype.java | 0 {javase => javase_joly}/src/someUtil/fastjson.java | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename {javase => javase_joly}/src/Basic/IntegerLearn.java (100%) rename {javase => javase_joly}/src/BigDecimal/BigDecimalBasic.java (100%) rename {javase => javase_joly}/src/Collection/List/ArrayListLearn.java (100%) rename {javase => javase_joly}/src/Collection/List/Practice100.java (100%) rename {javase => javase_joly}/src/Collection/Map/HashMapLearn.java (100%) rename {javase => javase_joly}/src/Exception/ExceptionLearn.java (100%) rename {javase => javase_joly}/src/Exception/ExceptionLearnB.java (100%) rename {javase => javase_joly}/src/flow/SwitchLearn.java (100%) rename {javase => javase_joly}/src/someUtil/ForGgtype.java (100%) rename {javase => javase_joly}/src/someUtil/fastjson.java (100%) diff --git a/javase/src/Basic/IntegerLearn.java b/javase_joly/src/Basic/IntegerLearn.java similarity index 100% rename from javase/src/Basic/IntegerLearn.java rename to javase_joly/src/Basic/IntegerLearn.java diff --git a/javase/src/BigDecimal/BigDecimalBasic.java b/javase_joly/src/BigDecimal/BigDecimalBasic.java similarity index 100% rename from javase/src/BigDecimal/BigDecimalBasic.java rename to javase_joly/src/BigDecimal/BigDecimalBasic.java diff --git a/javase/src/Collection/List/ArrayListLearn.java b/javase_joly/src/Collection/List/ArrayListLearn.java similarity index 100% rename from javase/src/Collection/List/ArrayListLearn.java rename to javase_joly/src/Collection/List/ArrayListLearn.java diff --git a/javase/src/Collection/List/Practice100.java b/javase_joly/src/Collection/List/Practice100.java similarity index 100% rename from javase/src/Collection/List/Practice100.java rename to javase_joly/src/Collection/List/Practice100.java diff --git a/javase/src/Collection/Map/HashMapLearn.java b/javase_joly/src/Collection/Map/HashMapLearn.java similarity index 100% rename from javase/src/Collection/Map/HashMapLearn.java rename to javase_joly/src/Collection/Map/HashMapLearn.java diff --git a/javase/src/Exception/ExceptionLearn.java b/javase_joly/src/Exception/ExceptionLearn.java similarity index 100% rename from javase/src/Exception/ExceptionLearn.java rename to javase_joly/src/Exception/ExceptionLearn.java diff --git a/javase/src/Exception/ExceptionLearnB.java b/javase_joly/src/Exception/ExceptionLearnB.java similarity index 100% rename from javase/src/Exception/ExceptionLearnB.java rename to javase_joly/src/Exception/ExceptionLearnB.java diff --git a/javase/src/flow/SwitchLearn.java b/javase_joly/src/flow/SwitchLearn.java similarity index 100% rename from javase/src/flow/SwitchLearn.java rename to javase_joly/src/flow/SwitchLearn.java diff --git a/javase/src/someUtil/ForGgtype.java b/javase_joly/src/someUtil/ForGgtype.java similarity index 100% rename from javase/src/someUtil/ForGgtype.java rename to javase_joly/src/someUtil/ForGgtype.java diff --git a/javase/src/someUtil/fastjson.java b/javase_joly/src/someUtil/fastjson.java similarity index 100% rename from javase/src/someUtil/fastjson.java rename to javase_joly/src/someUtil/fastjson.java From 6b967a197317658863a25620658ff461fd7d8273 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Wed, 29 Dec 2021 16:05:26 +0800 Subject: [PATCH 16/64] =?UTF-8?q?=E9=A1=BA=E4=BE=BF=E7=9C=8B=E4=B8=80?= =?UTF-8?q?=E4=B8=8B=E7=B1=BB=E5=8A=A0=E8=BD=BD=20=EF=BC=8C=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E5=86=85=E9=83=A8=E7=B1=BB=EF=BC=8C=E9=9D=99=E6=80=81?= =?UTF-8?q?=EF=BC=8C=E6=84=9F=E5=8F=97=E4=B8=80=E4=B8=8B=E9=A1=BA=E5=BA=8F?= =?UTF-8?q?=E3=80=82=E3=80=82=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- javase_joly/src/Basic/EqualsAnd.java | 83 ++++++++++++++++++++++++++ javase_joly/src/Basic/ShortLearn.java | 15 +++++ javase_joly/src/Basic/StringLearn.java | 16 +++++ 3 files changed, 114 insertions(+) create mode 100644 javase_joly/src/Basic/EqualsAnd.java create mode 100644 javase_joly/src/Basic/ShortLearn.java create mode 100644 javase_joly/src/Basic/StringLearn.java diff --git a/javase_joly/src/Basic/EqualsAnd.java b/javase_joly/src/Basic/EqualsAnd.java new file mode 100644 index 00000000..96412174 --- /dev/null +++ b/javase_joly/src/Basic/EqualsAnd.java @@ -0,0 +1,83 @@ +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 + int high = IntegerCache.high; + } + + private static class IntegerCache { + static final int low = -128; + static final int high; + + + static { + System.out.println("if run this code?"); + // high value may be configured by property + int h = 127; + String integerCacheHighPropValue = + sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); + if (integerCacheHighPropValue != null) { + try { + int i = parseInt(integerCacheHighPropValue); + i = Math.max(i, 127); + // Maximum array size is Integer.MAX_VALUE + h = Math.min(i, Integer.MAX_VALUE - (-low) - 1); + } catch (NumberFormatException nfe) { + // If the property cannot be parsed into an int, ignore it. + } + } + high = h; + + + Integer[] cache = new Integer[(high - low) + 1]; + int j = low; + for (int k = 0; k < cache.length; k++) { + cache[k] = new Integer(j++); + } + + + // range [-128, 127] must be interned (JLS7 5.1.7) + assert IntegerCache.high >= 127; + } + } +} 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); + } +} From 426fa7303b090ffa4d09868be5b3b288346b29b5 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Fri, 31 Dec 2021 18:19:34 +0800 Subject: [PATCH 17/64] =?UTF-8?q?=E6=AF=94=E8=BE=83=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E7=9B=B8=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- javase_joly/src/Basic/EqualsAnd.java | 42 +++++----------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/javase_joly/src/Basic/EqualsAnd.java b/javase_joly/src/Basic/EqualsAnd.java index 96412174..3a0cef9e 100644 --- a/javase_joly/src/Basic/EqualsAnd.java +++ b/javase_joly/src/Basic/EqualsAnd.java @@ -42,42 +42,14 @@ public static void main(String[] args) { System.out.println("\nInteger i = 128;\n" + "int j = 128;\n" + "i == j ? {}" + (i == j)); //true - int high = IntegerCache.high; + 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"); } - private static class IntegerCache { - static final int low = -128; - static final int high; - - static { - System.out.println("if run this code?"); - // high value may be configured by property - int h = 127; - String integerCacheHighPropValue = - sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); - if (integerCacheHighPropValue != null) { - try { - int i = parseInt(integerCacheHighPropValue); - i = Math.max(i, 127); - // Maximum array size is Integer.MAX_VALUE - h = Math.min(i, Integer.MAX_VALUE - (-low) - 1); - } catch (NumberFormatException nfe) { - // If the property cannot be parsed into an int, ignore it. - } - } - high = h; - - - Integer[] cache = new Integer[(high - low) + 1]; - int j = low; - for (int k = 0; k < cache.length; k++) { - cache[k] = new Integer(j++); - } - - - // range [-128, 127] must be interned (JLS7 5.1.7) - assert IntegerCache.high >= 127; - } - } } From 722995193246d2082a5c47d4aa69d75a18c31822 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 9 Jan 2022 21:07:47 +0800 Subject: [PATCH 18/64] =?UTF-8?q?=E7=B1=BB=E5=8A=A0=E8=BD=BD=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 01jvm/JvmClassLoaderPrintPath.java | 33 ++++++++++++++----- 01jvm/jvm/HelloClassLoader.java | 7 +++- .../main/java/jrl/ClassLoaderBasicLearn.java | 10 ++++++ 04fx/java8/src/main/java/jrl/Father.java | 5 +++ 04fx/java8/src/main/java/jrl/Son.java | 12 +++++++ 5 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 04fx/java8/src/main/java/jrl/ClassLoaderBasicLearn.java create mode 100644 04fx/java8/src/main/java/jrl/Father.java create mode 100644 04fx/java8/src/main/java/jrl/Son.java 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/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/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/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/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); + + + } +} From adcd0c6b398e15c89e39c0c513c3e5c6e9e20c13 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sat, 5 Feb 2022 21:22:56 +0800 Subject: [PATCH 19/64] Lambda --- 01jvm/clazz/ClazzA.java | 17 ++++++ 01jvm/clazz/InterfaceA.java | 8 +++ 01jvm/clazz/Person.java | 29 +++++++++ 01jvm/clazz/TwoMethodClazz.java | 36 +++++++++++ .../java/lambdasinaction/jrl/MyLambda8.java | 20 +++++++ .../jrl/MyLambdaInterface.java | 16 +++++ .../java/io/kimmking/java8/LambdaDemo.java | 60 ++++++++++--------- .../io/kimmking/java8/jrl/GenericJrl.java | 10 ++++ .../io/kimmking/java8/jrl/LambdaDemoJrl.java | 41 +++++++++++++ 9 files changed, 209 insertions(+), 28 deletions(-) create mode 100644 01jvm/clazz/ClazzA.java create mode 100644 01jvm/clazz/InterfaceA.java create mode 100644 01jvm/clazz/Person.java create mode 100644 01jvm/clazz/TwoMethodClazz.java create mode 100644 04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambda8.java create mode 100644 04fx/Java8inAction/src/main/java/lambdasinaction/jrl/MyLambdaInterface.java create mode 100644 04fx/java8/src/main/java/io/kimmking/java8/jrl/GenericJrl.java create mode 100644 04fx/java8/src/main/java/io/kimmking/java8/jrl/LambdaDemoJrl.java 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/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/java8/src/main/java/io/kimmking/java8/LambdaDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java index 94996f3b..39d68d18 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java @@ -4,58 +4,61 @@ import java.util.Arrays; import java.util.Collection; -public class LambdaDemo { - - public static void main(String args[]){ +/** + * @author Joly + */ +public class LambdaDemo { + + public static void main(String[] args) { LambdaDemo demo = new LambdaDemo(); - + MathOperation op = new MathOperation() { @Override public Integer operation(int a, int b) { return 1; } }; - + MathOperation op1 = (a, b) -> 1; 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); @@ -63,28 +66,29 @@ public Integer operation(int a, int b) { 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 ); - + 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); } - + + interface MathOperation { T operation(int a, int b); // 返回类型+函数名+参数类型的列表 } - + interface GreetingService { void sayMessage(String message); } - - private T operate(int a, int b, MathOperation mathOperation){ + + 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/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); + } + +} From 462e905ac1f35afb137fc5de8beab13be669a9e4 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Mon, 7 Feb 2022 13:25:06 +0800 Subject: [PATCH 20/64] spring aop --- .../main/java/io/kimmking/aop/ISchool.java | 13 ++++++++-- .../java/io/kimmking/spring01/Student.java | 26 ++++++++++++++++++- .../main/java/io/kimmking/spring02/Aop1.java | 19 +++++++++++++- .../main/java/io/kimmking/spring02/Aop2.java | 19 ++++++++++++++ .../main/java/io/kimmking/spring02/Klass.java | 12 +++++++++ .../java/io/kimmking/spring02/School.java | 13 +++++++++- .../io/kimmking/spring02/SpringDemo01.java | 14 +++++++--- .../src/main/resources/applicationContext.xml | 18 +++++++++---- 8 files changed, 120 insertions(+), 14 deletions(-) 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/spring01/Student.java b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java index 484a840d..310eabbf 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -13,6 +13,19 @@ import java.io.Serializable; +/** + * pojo: + * 1.aop使用 + *

+ * bean 生命周期: + * 2.Aware: + * BeanNameAware: setBeanName() + * ApplicationContextAware: setApplicationContext() + * spring 负责对beanName和applicationContext这两个属性进行赋值(在构建Student bean的时候) + * + * @author jrl + * @date 2022/2/7 + */ @Data @AllArgsConstructor @NoArgsConstructor @@ -23,7 +36,9 @@ public class Student implements Serializable, BeanNameAware, ApplicationContextA private int id; private String name; + // BeanNameAware private String beanName; + //ApplicationContextAware private ApplicationContext applicationContext; public void init() { @@ -34,11 +49,20 @@ public static Student create() { return new Student(102, "KK102", null, null); } + /** + * 输出beanName(不确定从哪进行的赋值) + * 输出the names of all beans defined in this factory + * TODO defined 是什么含义,这个bean创建了没有,是声明还是创建的意思 + * + * @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())); - } 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 48d3936f..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,6 +2,14 @@ import org.aspectj.lang.ProceedingJoinPoint; +/** + * 应用spring aop: + * 方式一:XML + * 这个方式需要在XML中说明切点和切面在哪,然后在代码里写好切面 + * + * @author jrl + * @date 2022/2/6 + */ public class Aop1 { //前置通知 @@ -14,10 +22,19 @@ 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 - //调用process()方法才会真正的执行实际被代理的方法 + /** 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 2ad2d1ed..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,14 +8,30 @@ 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 { + /** + * knowledge point: + * ˵еЩ + */ @Pointcut(value = "execution(* io.kimmking.*.Klass.*dong(..))") public void point() { } + /** + * knowledge point: + * Ҫ˵Ӧĸе + */ @Before(value = "point()") public void before() { System.out.println("========>begin klass dong... //2"); @@ -29,6 +45,9 @@ public void after() { @Around("point()") 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/Klass.java b/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java index 8c1d91bd..ac855a18 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java @@ -5,11 +5,23 @@ import java.util.List; +/** + * ûʵֽӿ + * + * @author Joly + */ @Data public class Klass { List students; + /** + * + * + * @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/School.java b/04fx/spring01/src/main/java/io/kimmking/spring02/School.java index 99a943a6..54031ac9 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/School.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/School.java @@ -7,9 +7,20 @@ import javax.annotation.Resource; +/** + * @author Joly + */ @Data public class School implements ISchool { - + /** + * knowledge point: + * springעķʽ + * Autowiredע⣺Ĭϸע + * requiredڱʾöAǷʱͰע뵽BУ + * ǵõAʱҲõAķԵʱٰAעȥBҲأ + * Ĭtruetrueһע + * Resourceע⣺Ĭϸע + */ // Resource @Autowired(required = true) //primary Klass class1; 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 cae24f1b..8f435ce1 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java @@ -6,19 +6,25 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringDemo01 { - public static void main(String[] args) { - + /** knowledge point: + * spring原始获取配置文件的方式 + */ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); -// Student student123 = context.getBean(Student.class); +// 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(); diff --git a/04fx/spring01/src/main/resources/applicationContext.xml b/04fx/spring01/src/main/resources/applicationContext.xml index 6d09cd3c..a31dcb17 100644 --- a/04fx/spring01/src/main/resources/applicationContext.xml +++ b/04fx/spring01/src/main/resources/applicationContext.xml @@ -36,26 +36,34 @@ - + - + + - - + + + + + + + + + - + \ No newline at end of file From daa46bb71ef3451ce3696340114100778c047eff Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Fri, 11 Feb 2022 15:14:48 +0800 Subject: [PATCH 21/64] =?UTF-8?q?spring=20xml=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/io/kimmking/spring01/Student.java | 2 +- .../src/main/resources/applicationContext.xml | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) 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 310eabbf..b0bfae14 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -50,7 +50,7 @@ public static Student create() { } /** - * 输出beanName(不确定从哪进行的赋值) + * 输出beanName(是BeanNameAware给set进来的) * 输出the names of all beans defined in this factory * TODO defined 是什么含义,这个bean创建了没有,是声明还是创建的意思 * diff --git a/04fx/spring01/src/main/resources/applicationContext.xml b/04fx/spring01/src/main/resources/applicationContext.xml index a31dcb17..c6f6d60c 100644 --- a/04fx/spring01/src/main/resources/applicationContext.xml +++ b/04fx/spring01/src/main/resources/applicationContext.xml @@ -1,4 +1,11 @@ - + + - @@ -46,7 +52,7 @@ - + From 7502d41c7aa8fa9b74b3aa87ef0966f82667fa1a Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Fri, 11 Feb 2022 19:56:25 +0800 Subject: [PATCH 22/64] spring jms --- 04fx/spring01/pom.xml | 36 ++++++++++--------- .../java/io/kimmking/spring01/Student.java | 2 +- .../io/kimmking/springjms/JmsListener.java | 13 +++++-- .../io/kimmking/springjms/JmsReceiver.java | 15 ++++---- .../java/io/kimmking/springjms/JmsSender.java | 17 +++++---- .../io/kimmking/springjms/SendService.java | 15 ++++++-- .../src/main/resources/springjms-receiver.xml | 21 +++++------ .../src/main/resources/springjms-sender.xml | 8 ++--- 8 files changed, 74 insertions(+), 53 deletions(-) diff --git a/04fx/spring01/pom.xml b/04fx/spring01/pom.xml index 505009a7..89645d51 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 - + @@ -25,7 +25,7 @@ - + com.google.guava @@ -42,11 +42,11 @@ spring-core ${spring-version} - - - - - + + + + + org.springframework spring-beans @@ -87,11 +87,13 @@ spring-test ${spring-version} + org.springframework spring-messaging ${spring-version} + org.springframework spring-jms @@ -102,7 +104,7 @@ spring-expression ${spring-version} - + com.alibaba fastjson @@ -151,18 +153,18 @@ 1.10.19 test - + org.apache.activemq activemq-client 5.15.0 - + - - - - + + + + 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 b0bfae14..cb33e094 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -46,7 +46,7 @@ public void init() { } public static Student create() { - return new Student(102, "KK102", null, null); + return new Student(101, "KK101", null, null); } /** 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..290e74ae 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,15 @@ 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"); 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..3e19b4c4 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"); } - + } 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..a1e8713a 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java @@ -11,14 +11,25 @@ import javax.jms.Message; import javax.jms.Session; +/** + * 使用JMSTemplate来发送消息 + * + * @author jrl + * @date 2022/2/11 + */ @Component public class SendService { + /** + * 配置文件里面注入的JMSTemplate + * + * @author jrl + * @date 2022/2/11 + */ @Autowired JmsTemplate jmsTemplate; - + public void send(final Student user) { jmsTemplate.send("test.queue", new MessageCreator() { - public Message createMessage(Session session) throws JMSException { return session.createObjectMessage(JSON.toJSONString(user)); } diff --git a/04fx/spring01/src/main/resources/springjms-receiver.xml b/04fx/spring01/src/main/resources/springjms-receiver.xml index e0d9fbc6..9afe1a3d 100644 --- a/04fx/spring01/src/main/resources/springjms-receiver.xml +++ b/04fx/spring01/src/main/resources/springjms-receiver.xml @@ -10,27 +10,28 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd"> - + - + - - + + - + - + - + - + - + + - + \ 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..29d334c0 100644 --- a/04fx/spring01/src/main/resources/springjms-sender.xml +++ b/04fx/spring01/src/main/resources/springjms-sender.xml @@ -9,15 +9,15 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> - + - + - + - + From 202f52f0650313af57eca37809e573626d493d9e Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Fri, 25 Feb 2022 18:00:19 +0800 Subject: [PATCH 23/64] lambda --- 04fx/java8/src/main/java/jrl/AInterface.java | 9 ++++++++ .../src/main/java/jrl/AnonymityClazz.java | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 04fx/java8/src/main/java/jrl/AInterface.java create mode 100644 04fx/java8/src/main/java/jrl/AnonymityClazz.java 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"); + } +} From 5dbf239f28f4e248dbfcc3891cac8c519ad135dd Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 27 Feb 2022 10:35:01 +0800 Subject: [PATCH 24/64] Lambda --- .../java/io/kimmking/java8/LambdaDemo.java | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) 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 39d68d18..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,25 +1,35 @@ package io.kimmking.java8; +import com.google.common.base.Function; + import java.io.Serializable; import java.util.Arrays; import java.util.Collection; /** + * 泛型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() { @@ -63,12 +73,17 @@ public Integer operation(int a, int b) { GreetingService greetService2 = (message) -> { System.out.println(message); }; - + // 类似函数指令的用法 + // 因为sayMessage的参数是String,println的参数也是String,所以在写println的时候就直接可以不写参数了 + // 这样就进一步简化了 GreetingService greetService3 = System.out::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"); @@ -78,15 +93,34 @@ private static void println(int x) { 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); } + + /** + * 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); } From 698a4f17605083d259dd41dfe85f2140cbeb4d91 Mon Sep 17 00:00:00 2001 From: jrl <584189010@qq.com> Date: Sun, 27 Feb 2022 17:08:07 +0800 Subject: [PATCH 25/64] stream --- .../io/kimmking/java8/CollectionDemo.java | 29 +++++--- .../java/io/kimmking/java8/StreamDemo.java | 70 ++++++++++++------- 2 files changed, 65 insertions(+), 34 deletions(-) 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/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)); } From f9be37c29d52da0d2822e91bc7bc6e0708ef5fc6 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sat, 9 Apr 2022 16:41:38 +0800 Subject: [PATCH 26/64] Spring IOC AOP --- .../java/io/kimmking/java8/ForeachDemo.java | 1 - .../java/io/kimmking/java8/GenericDemo.java | 1 - 04fx/spring01/README | 2 + 04fx/spring01/pom.xml | 4 +- .../src/main/java/io/kimmking/jrl/inter.java | 16 ----- .../main/java/io/kimmking/jrl/proxy/README.md | 9 +++ .../dynamic0/DebugInvocationHandler.java | 35 +++++++++++ .../jrl/proxy/dynamic0/JdkProxyFactory.java | 17 +++++ .../io/kimmking/jrl/proxy/dynamic0/Main.java | 16 +++++ .../jrl/proxy/dynamic0/SmsService.java | 17 +++++ .../jrl/proxy/dynamic0/SmsServiceImpl.java | 17 +++++ .../jrl/proxy/dynamic1/AliService.java | 12 ++++ .../jrl/proxy/dynamic1/CglibProxyFactory.java | 17 +++++ .../dynamic1/DebugMethodInterceptor.java | 24 +++++++ .../io/kimmking/jrl/proxy/dynamic1/Main.java | 12 ++++ .../jrl/proxy/homework/bean/AssembleBean.java | 34 ++++++++++ .../jrl/proxy/homework/bean/Teacher.java | 19 ++++++ .../io/kimmking/jrl/proxy/static0/Main.java | 12 ++++ .../jrl/proxy/static0/SmsService.java | 18 ++++++ .../jrl/proxy/static0/SmsServiceImpl.java | 16 +++++ .../jrl/proxy/static0/SmsServiceProxy.java | 24 +++++++ .../src/main/java/io/kimmking/spring01/README | 1 + .../java/io/kimmking/spring01/Student.java | 63 ++++++++++++++++--- ...loBeanDefinitionRegistryPostProcessor.java | 30 +++++++-- .../spring02/HelloBeanPostProcessor.java | 10 ++- .../main/java/io/kimmking/spring02/Klass.java | 3 +- .../src/main/java/io/kimmking/spring02/README | 1 + .../java/io/kimmking/spring02/School.java | 6 +- .../io/kimmking/spring02/SpringDemo01.java | 21 ++++++- .../src/main/resources/applicationContext.xml | 5 +- .../applicationContext4homework1.xml | 28 +++++++++ 31 files changed, 446 insertions(+), 45 deletions(-) create mode 100644 04fx/spring01/README delete mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/inter.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/README.md create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/DebugInvocationHandler.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/JdkProxyFactory.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/Main.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsService.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic0/SmsServiceImpl.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/AliService.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/CglibProxyFactory.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/DebugMethodInterceptor.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/dynamic1/Main.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/AssembleBean.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/Teacher.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/Main.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsService.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceImpl.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/static0/SmsServiceProxy.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/spring01/README create mode 100644 04fx/spring01/src/main/java/io/kimmking/spring02/README create mode 100644 04fx/spring01/src/main/resources/applicationContext4homework1.xml 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/spring01/README b/04fx/spring01/README new file mode 100644 index 00000000..0011713d --- /dev/null +++ b/04fx/spring01/README @@ -0,0 +1,2 @@ +介绍Spring Framework. +没有引入Spring Boot,所以没有自动配置,都要自己手动的做 \ No newline at end of file diff --git a/04fx/spring01/pom.xml b/04fx/spring01/pom.xml index 89645d51..577ca3b5 100644 --- a/04fx/spring01/pom.xml +++ b/04fx/spring01/pom.xml @@ -9,8 +9,8 @@ 1.0 - - 4.3.29.RELEASE + 5.2.7.RELEASE + diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/inter.java b/04fx/spring01/src/main/java/io/kimmking/jrl/inter.java deleted file mode 100644 index fc6dcc63..00000000 --- a/04fx/spring01/src/main/java/io/kimmking/jrl/inter.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.kimmking.jrl; - -public interface inter { - public static final int A = 1; - - public default void me() { - - } - - public static void me2() { - - } - - - public void me3(); -} 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/homework/bean/AssembleBean.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/AssembleBean.java new file mode 100644 index 00000000..810745b5 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/AssembleBean.java @@ -0,0 +1,34 @@ +package io.kimmking.jrl.proxy.homework.bean; + +import io.kimmking.spring01.Student; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.stereotype.Component; + +/** + * дʵ Spring Bean װ䣬ʽԽԽãXMLAnnotation ԣ, ύ GitHub + * + * @author jrl + * @date Create in 14:08 2022/4/9 + */ +@ComponentScan("io.kimmking.jrl.proxy.homework.bean") +public class AssembleBean { + @Bean + Student studentFactory(){ + return Student.create(); + } + @Autowired + Teacher teacher; + + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext4homework1.xml"); + // context.getBean("1"); + String[] beanDefinitionNames = context.getBeanDefinitionNames(); + System.out.println(String.join(",",beanDefinitionNames)); + Student student = new AssembleBean().teacher.student; + System.out.println(student); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/Teacher.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/Teacher.java new file mode 100644 index 00000000..712afa0c --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/Teacher.java @@ -0,0 +1,19 @@ +package io.kimmking.jrl.proxy.homework.bean; + +import io.kimmking.spring01.Student; +import lombok.Data; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author jrl + * @date Create in 14:24 2022/4/9 + */ +// TODO_Joly:ûsetter +@Component +@Data +public class Teacher { + @Autowired + Student student; +} 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 cb33e094..00689491 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -17,42 +17,63 @@ * pojo: * 1.aop使用 *

- * bean 生命周期: - * 2.Aware: - * BeanNameAware: setBeanName() - * ApplicationContextAware: setApplicationContext() + * 2.bean 生命周期: + * Aware: + * BeanNameAware + * ApplicationContextAware * spring 负责对beanName和applicationContext这两个属性进行赋值(在构建Student bean的时候) * * @author jrl * @date 2022/2/7 */ -@Data + @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; - - // BeanNameAware + /** + * knowledge point: BeanNameAware 用于在初始化Bean时将BeanName信息提供给该Bean应该是用反射实现的) + */ private String beanName; - //ApplicationContextAware + /** + * knowledge point: ApplicationContextAware 用于在初始化Bean的时候将ApplicationContext提供给该Bean + */ private ApplicationContext applicationContext; + /*初始化之前就调用了。应该是属性赋值的阶段做的。*/ + @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(101, "KK101", null, null); + return new Student(101, "KK101", "1", null); } /** * 输出beanName(是BeanNameAware给set进来的) * 输出the names of all beans defined in this factory - * TODO defined 是什么含义,这个bean创建了没有,是声明还是创建的意思 * * @param * @return @@ -65,5 +86,27 @@ public void print() { + 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/HelloBeanDefinitionRegistryPostProcessor.java b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java index d6433bd6..d43ab1f3 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,42 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.stereotype.Component; +/** + * knowledge point: + */ +// TODO_Joly:ǶеBeanSpring֮һ԰еBeanר䵽еģעǰע +// TODO_Joly:͹йصģԺBean޹ض +// TODO_Joly:ڳʼ֮ǰִа--->ԣBeanͳһгʼ @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 ac855a18..221c2d6e 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Klass.java @@ -6,7 +6,8 @@ import java.util.List; /** - * ûʵֽӿ + * 1.ʾAOP + * ûʵֽӿڣSpringĬʹCGLibʵAOP * * @author Joly */ 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 54031ac9..57d9af76 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/School.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/School.java @@ -8,6 +8,8 @@ import javax.annotation.Resource; /** + * ʾAOP + * ʵ˽ӿڣSpringĬʹJdkProxyʵAOP * @author Joly */ @Data @@ -15,11 +17,11 @@ public class School implements ISchool { /** * knowledge point: * springעķʽ - * Autowiredע⣺Ĭϸע + * 1.Autowiredע⣺Ĭϸע * requiredڱʾöAǷʱͰע뵽BУ * ǵõAʱҲõAķԵʱٰAעȥBҲأ * Ĭtruetrueһע - * Resourceע⣺Ĭϸע + * 2.Resourceע⣺Ĭϸע */ // Resource @Autowired(required = true) //primary 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 8f435ce1..33f7b663 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java @@ -5,10 +5,22 @@ 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原始获取配置文件的方式 + * spring加载xml配置文件,生成context和启动相关配置 */ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); @@ -27,7 +39,6 @@ public static void main(String[] args) { System.out.println("student100 ====>" + student100); student100.print(); - Klass class1 = context.getBean(Klass.class); System.out.println(class1); System.out.println("Klass对象AOP代理后的实际类型:" + class1.getClass()); @@ -36,7 +47,7 @@ public static void main(String[] args) { ISchool school = context.getBean(ISchool.class); System.out.println(school); 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()); @@ -51,6 +62,10 @@ public static void main(String[] args) { 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/resources/applicationContext.xml b/04fx/spring01/src/main/resources/applicationContext.xml index c6f6d60c..4b73d239 100644 --- a/04fx/spring01/src/main/resources/applicationContext.xml +++ b/04fx/spring01/src/main/resources/applicationContext.xml @@ -6,6 +6,7 @@ 这是一个网址,但是spring可以提前把对应的文件下载下来,就像下载一个jar包一样。 XSD用来说明XML的结构,通过XSD就可以校验这个XML文件的格式是否正确。 --> + - + @@ -46,7 +47,7 @@ - + diff --git a/04fx/spring01/src/main/resources/applicationContext4homework1.xml b/04fx/spring01/src/main/resources/applicationContext4homework1.xml new file mode 100644 index 00000000..a62f761d --- /dev/null +++ b/04fx/spring01/src/main/resources/applicationContext4homework1.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 9ddb772cd49a11b5657764ccd78d3fafe70ee1b0 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sat, 9 Apr 2022 19:21:26 +0800 Subject: [PATCH 27/64] Spring IOC AOP --- .../homework/bean0/config/Configuration0.java | 29 ++++++++++++++++ .../jrl/homework/bean0/main/main0.java | 17 ++++++++++ .../jrl/homework/bean0/pojo/HomeTeacher.java | 13 +++++++ .../bean0/pojo/SchoolTeacher.java} | 8 ++--- .../jrl/proxy/homework/bean/AssembleBean.java | 34 ------------------- .../java/io/kimmking/spring01/Student.java | 3 +- ...loBeanDefinitionRegistryPostProcessor.java | 7 ++-- .../applicationContext4homework1.xml | 15 ++++---- 8 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/config/Configuration0.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/main0.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/HomeTeacher.java rename 04fx/spring01/src/main/java/io/kimmking/jrl/{proxy/homework/bean/Teacher.java => homework/bean0/pojo/SchoolTeacher.java} (65%) delete mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/AssembleBean.java 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..7a8b7392 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/config/Configuration0.java @@ -0,0 +1,29 @@ +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; + +/** + * @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/main/main0.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/main0.java new file mode 100644 index 00000000..fc36763e --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/main0.java @@ -0,0 +1,17 @@ +package io.kimmking.jrl.homework.bean0.main; + +import io.kimmking.jrl.homework.bean0.pojo.SchoolTeacher; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author jrl + * @date Create in 17:39 2022/4/9 + */ +public class main0 { + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext4homework1.xml"); + String[] beanDefinitionNames = context.getBeanDefinitionNames(); + System.out.println(String.join(",", beanDefinitionNames)); + } +} 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/proxy/homework/bean/Teacher.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/SchoolTeacher.java similarity index 65% rename from 04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/Teacher.java rename to 04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/SchoolTeacher.java index 712afa0c..688e95bf 100644 --- a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/Teacher.java +++ b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/pojo/SchoolTeacher.java @@ -1,8 +1,7 @@ -package io.kimmking.jrl.proxy.homework.bean; +package io.kimmking.jrl.homework.bean0.pojo; import io.kimmking.spring01.Student; import lombok.Data; -import lombok.Setter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -10,10 +9,9 @@ * @author jrl * @date Create in 14:24 2022/4/9 */ -// TODO_Joly:ûsetter @Component @Data -public class Teacher { +public class SchoolTeacher { @Autowired - Student student; + Student favoriteStudent; } diff --git a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/AssembleBean.java b/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/AssembleBean.java deleted file mode 100644 index 810745b5..00000000 --- a/04fx/spring01/src/main/java/io/kimmking/jrl/proxy/homework/bean/AssembleBean.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.kimmking.jrl.proxy.homework.bean; - -import io.kimmking.spring01.Student; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.stereotype.Component; - -/** - * дʵ Spring Bean װ䣬ʽԽԽãXMLAnnotation ԣ, ύ GitHub - * - * @author jrl - * @date Create in 14:08 2022/4/9 - */ -@ComponentScan("io.kimmking.jrl.proxy.homework.bean") -public class AssembleBean { - @Bean - Student studentFactory(){ - return Student.create(); - } - @Autowired - Teacher teacher; - - public static void main(String[] args) { - ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext4homework1.xml"); - // context.getBean("1"); - String[] beanDefinitionNames = context.getBeanDefinitionNames(); - System.out.println(String.join(",",beanDefinitionNames)); - Student student = new AssembleBean().teacher.student; - System.out.println(student); - } -} 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 00689491..84b66e8c 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -47,6 +47,7 @@ public Student(int id, String name) { * knowledge point: ApplicationContextAware 用于在初始化Bean的时候将ApplicationContext提供给该Bean */ private ApplicationContext applicationContext; + /*初始化之前就调用了。应该是属性赋值的阶段做的。*/ @Override public void setBeanName(String name) { @@ -68,7 +69,7 @@ public void init() { public static Student create() { - return new Student(101, "KK101", "1", null); + return new Student(101, "KK101", null, null); } /** 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 d43ab1f3..0e95da12 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java @@ -11,9 +11,6 @@ /** * knowledge point: */ -// TODO_Joly:ǶеBeanSpring֮һ԰еBeanר䵽еģעǰע -// TODO_Joly:͹йصģԺBean޹ض -// TODO_Joly:ڳʼ֮ǰִа--->ԣBeanͳһгʼ @Component public class HelloBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override @@ -24,7 +21,7 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) t RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class); rootBeanDefinition.getPropertyValues().add("id", 101); rootBeanDefinition.getPropertyValues().add("name", "KK101"); - /*װָbean*/ + /*зָbean*/ registry.registerBeanDefinition("s101", rootBeanDefinition); RootBeanDefinition rootBeanDefinition2 = new RootBeanDefinition(Student.class); rootBeanDefinition2.getPropertyValues().add("id", 1125); @@ -45,5 +42,5 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) /*õ*/ // TODO_Joly:ûŽȥ beanFactory.registerSingleton("s102", Student.create()); - } + } } diff --git a/04fx/spring01/src/main/resources/applicationContext4homework1.xml b/04fx/spring01/src/main/resources/applicationContext4homework1.xml index a62f761d..8e1b77fa 100644 --- a/04fx/spring01/src/main/resources/applicationContext4homework1.xml +++ b/04fx/spring01/src/main/resources/applicationContext4homework1.xml @@ -2,12 +2,11 @@ + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> + + - - @@ -17,7 +16,7 @@ - + @@ -25,4 +24,8 @@ + + \ No newline at end of file From ec8aac4d284970c51155150a0f9d28bf3868faa7 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Mon, 11 Apr 2022 20:33:40 +0800 Subject: [PATCH 28/64] XML --- 04fx/XML/pom.xml | 26 +++++++ .../com/woniuxy/basic/xml/SAXReaderLearn.java | 71 +++++++++++++++++++ .../com/woniuxy/basic/xml/XMLWriterLearn.java | 65 +++++++++++++++++ 04fx/XML/src/main/resources/jdbc.xml | 15 ++++ 04fx/XML/src/main/resources/swun.xml | 7 ++ .../src/main/resources/applicationContext.xml | 21 ++++-- 6 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 04fx/XML/pom.xml create mode 100644 04fx/XML/src/main/java/src/com/woniuxy/basic/xml/SAXReaderLearn.java create mode 100644 04fx/XML/src/main/java/src/com/woniuxy/basic/xml/XMLWriterLearn.java create mode 100644 04fx/XML/src/main/resources/jdbc.xml create mode 100644 04fx/XML/src/main/resources/swun.xml 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/04fx/spring01/src/main/resources/applicationContext.xml b/04fx/spring01/src/main/resources/applicationContext.xml index 4b73d239..b5fc09ba 100644 --- a/04fx/spring01/src/main/resources/applicationContext.xml +++ b/04fx/spring01/src/main/resources/applicationContext.xml @@ -1,10 +1,15 @@ - + 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"> @@ -40,7 +47,7 @@ - + From 540eb957d5122f1cf6a7b5a6f4d149d545fea2a1 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Tue, 12 Apr 2022 14:18:12 +0800 Subject: [PATCH 29/64] Spring JMS --- 04fx/spring01/README | 5 ++++- 04fx/spring01/pom.xml | 10 ++++++---- .../main/java/io/kimmking/springjms/JmsReceiver.java | 1 + .../main/java/io/kimmking/springjms/JmsSender.java | 4 ++-- .../main/java/io/kimmking/springjms/SendService.java | 11 ++++------- .../src/main/resources/springjms-receiver.xml | 6 +++++- 04fx/spring01/src/main/resources/springjms-sender.xml | 1 + 7 files changed, 23 insertions(+), 15 deletions(-) diff --git a/04fx/spring01/README b/04fx/spring01/README index 0011713d..f8f3d7f4 100644 --- a/04fx/spring01/README +++ b/04fx/spring01/README @@ -1,2 +1,5 @@ 介绍Spring Framework. -没有引入Spring Boot,所以没有自动配置,都要自己手动的做 \ No newline at end of file +没有引入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 577ca3b5..77e0e58f 100644 --- a/04fx/spring01/pom.xml +++ b/04fx/spring01/pom.xml @@ -9,8 +9,8 @@ 1.0 - 5.2.7.RELEASE - + 5.2.7.RELEASE + @@ -93,7 +93,9 @@ spring-messaging ${spring-version} - + + org.springframework spring-jms @@ -153,7 +155,7 @@ 1.10.19 test - + org.apache.activemq activemq-client 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 290e74ae..22ed0c9c 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsReceiver.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsReceiver.java @@ -13,6 +13,7 @@ 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 3e19b4c4..ab69c4b5 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java @@ -14,8 +14,8 @@ public static void main(String[] args) { 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 a1e8713a..1136cbd5 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java @@ -19,18 +19,15 @@ */ @Component public class SendService { - /** - * 配置文件里面注入的JMSTemplate - * - * @author jrl - * @date 2022/2/11 - */ + @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/resources/springjms-receiver.xml b/04fx/spring01/src/main/resources/springjms-receiver.xml index 9afe1a3d..46d32144 100644 --- a/04fx/spring01/src/main/resources/springjms-receiver.xml +++ b/04fx/spring01/src/main/resources/springjms-receiver.xml @@ -1,4 +1,5 @@ + + + - + + diff --git a/04fx/spring01/src/main/resources/springjms-sender.xml b/04fx/spring01/src/main/resources/springjms-sender.xml index 29d334c0..68cf6c4b 100644 --- a/04fx/spring01/src/main/resources/springjms-sender.xml +++ b/04fx/spring01/src/main/resources/springjms-sender.xml @@ -1,4 +1,5 @@ + Date: Fri, 15 Apr 2022 21:37:10 +0800 Subject: [PATCH 30/64] =?UTF-8?q?Spring=20Boot=20=E6=BC=94=E7=A4=BA?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=20APP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {app => 04fx/app}/.gitignore | 0 .../.mvn/wrapper/MavenWrapperDownloader.java | 0 .../app}/.mvn/wrapper/maven-wrapper.jar | Bin .../.mvn/wrapper/maven-wrapper.properties | 0 {app => 04fx/app}/mvnw | 0 {app => 04fx/app}/mvnw.cmd | 0 {app => 04fx/app}/pom.xml | 0 .../src/main/java/com/example/app/App.java | 0 .../com/example/app/WebAutoConfiguration.java | 0 .../com/example/app/WebConfiguration.java | 0 .../main/java/com/example/app/WebInfo.java | 0 .../java/com/example/app/WebProperties.java | 0 .../main/resources/META-INF/spring.factories | 0 .../src/main/resources/application.properties | 0 .../com/example/app/AppApplicationTests.java | 0 production/01jvm/README.md | 119 ++++++++++++++++++ .../01jvm/out/production/01jvm/README.md | 41 ++++++ ...7\345\242\203\345\207\206\345\244\207.txt" | 38 ++++++ ...7\345\242\203\345\207\206\345\244\207.txt" | 38 ++++++ 19 files changed, 236 insertions(+) rename {app => 04fx/app}/.gitignore (100%) rename {app => 04fx/app}/.mvn/wrapper/MavenWrapperDownloader.java (100%) rename {app => 04fx/app}/.mvn/wrapper/maven-wrapper.jar (100%) rename {app => 04fx/app}/.mvn/wrapper/maven-wrapper.properties (100%) rename {app => 04fx/app}/mvnw (100%) mode change 100755 => 100644 rename {app => 04fx/app}/mvnw.cmd (100%) rename {app => 04fx/app}/pom.xml (100%) rename {app => 04fx/app}/src/main/java/com/example/app/App.java (100%) rename {app => 04fx/app}/src/main/java/com/example/app/WebAutoConfiguration.java (100%) rename {app => 04fx/app}/src/main/java/com/example/app/WebConfiguration.java (100%) rename {app => 04fx/app}/src/main/java/com/example/app/WebInfo.java (100%) rename {app => 04fx/app}/src/main/java/com/example/app/WebProperties.java (100%) rename {app => 04fx/app}/src/main/resources/META-INF/spring.factories (100%) rename {app => 04fx/app}/src/main/resources/application.properties (100%) rename {app => 04fx/app}/src/test/java/com/example/app/AppApplicationTests.java (100%) create mode 100644 production/01jvm/README.md create mode 100644 production/01jvm/out/production/01jvm/README.md create mode 100644 "production/01jvm/out/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" create mode 100644 "production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" diff --git a/app/.gitignore b/04fx/app/.gitignore similarity index 100% rename from app/.gitignore rename to 04fx/app/.gitignore diff --git a/app/.mvn/wrapper/MavenWrapperDownloader.java b/04fx/app/.mvn/wrapper/MavenWrapperDownloader.java similarity index 100% rename from app/.mvn/wrapper/MavenWrapperDownloader.java rename to 04fx/app/.mvn/wrapper/MavenWrapperDownloader.java diff --git a/app/.mvn/wrapper/maven-wrapper.jar b/04fx/app/.mvn/wrapper/maven-wrapper.jar similarity index 100% rename from app/.mvn/wrapper/maven-wrapper.jar rename to 04fx/app/.mvn/wrapper/maven-wrapper.jar diff --git a/app/.mvn/wrapper/maven-wrapper.properties b/04fx/app/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from app/.mvn/wrapper/maven-wrapper.properties rename to 04fx/app/.mvn/wrapper/maven-wrapper.properties diff --git a/app/mvnw b/04fx/app/mvnw old mode 100755 new mode 100644 similarity index 100% rename from app/mvnw rename to 04fx/app/mvnw diff --git a/app/mvnw.cmd b/04fx/app/mvnw.cmd similarity index 100% rename from app/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 100% rename from app/src/main/java/com/example/app/App.java rename to 04fx/app/src/main/java/com/example/app/App.java 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 100% rename from app/src/main/java/com/example/app/WebAutoConfiguration.java rename to 04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java 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 100% rename from app/src/main/java/com/example/app/WebConfiguration.java rename to 04fx/app/src/main/java/com/example/app/WebConfiguration.java 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 100% rename from app/src/main/java/com/example/app/WebProperties.java rename to 04fx/app/src/main/java/com/example/app/WebProperties.java 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/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 + From d884ef7f0a7d6aa1220f4f3c6004322c2315c9c5 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 17 Apr 2022 13:56:19 +0800 Subject: [PATCH 31/64] =?UTF-8?q?Spring=20Boot=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04fx/app/README.md | 4 +++ .../src/main/java/com/example/app/App.java | 5 ++-- .../com/example/app/WebAutoConfiguration.java | 6 ++-- .../java/com/example/app/WebProperties.java | 4 ++- .../java/io/kimmking/jrl/annotation/Main.java | 9 ++++++ .../kimmking/jrl/annotation/MyAnnotation.java | 22 ++++++++++++++ .../jrl/annotation/MyAnnotationImpl.java | 30 +++++++++++++++++++ 7 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 04fx/app/README.md create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/annotation/Main.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotation.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/annotation/MyAnnotationImpl.java 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/04fx/app/src/main/java/com/example/app/App.java b/04fx/app/src/main/java/com/example/app/App.java index 9a70eccc..b02bfebf 100644 --- a/04fx/app/src/main/java/com/example/app/App.java +++ b/04fx/app/src/main/java/com/example/app/App.java @@ -5,9 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; -/** - * knowledge point: springboot 的入口点 - */ + @SpringBootApplication public class App { @@ -20,6 +18,7 @@ public static void main(String[] args) { @Autowired WebInfo info; + // TODO_Joly:什么都没注册,那这里的目的是什么 @Bean public void printInfo() { System.out.println(info.getName()); diff --git a/04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java b/04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java index e74c3e73..2c1b004b 100644 --- a/04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java +++ b/04fx/app/src/main/java/com/example/app/WebAutoConfiguration.java @@ -7,7 +7,9 @@ import org.springframework.context.annotation.Import; /** - * knowledge point: @Import 用来当前类是用来自动装配被引入的那个类的 + * knowledge point: + * Import注解:和 Spring 的 xml 配置文件中的一样 + * EnableConfigurationProperties注解: */ @Configuration @Import(WebConfiguration.class) @@ -16,7 +18,7 @@ public class WebAutoConfiguration { @Autowired WebProperties properties; - + // TODO_Joly:这里就算不import也可以注入的吧 @Autowired WebConfiguration configuration; diff --git a/04fx/app/src/main/java/com/example/app/WebProperties.java b/04fx/app/src/main/java/com/example/app/WebProperties.java index 713fbeed..1109a497 100644 --- a/04fx/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/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(); + } +} From 745fd4f4f44dc8541876b4ab6a073e7a3ec31efa Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Mon, 18 Apr 2022 17:45:11 +0800 Subject: [PATCH 32/64] Spring Bean --- .../homework/bean0/config/Configuration0.java | 1 + .../controller/HomeTeacherController.java | 19 +++++++++++ .../jrl/homework/bean0/main/Main0.java | 34 +++++++++++++++++++ .../jrl/homework/bean0/main/main0.java | 17 ---------- .../applicationContext4homework1.xml | 4 ++- 5 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/controller/HomeTeacherController.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/Main0.java delete mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/main0.java 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 index 7a8b7392..00728704 100644 --- 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 @@ -6,6 +6,7 @@ import org.springframework.context.annotation.Configuration; /** + * beanע * @author jrl * @date Create in 17:30 2022/4/9 */ 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/main/main0.java b/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/main0.java deleted file mode 100644 index fc36763e..00000000 --- a/04fx/spring01/src/main/java/io/kimmking/jrl/homework/bean0/main/main0.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.kimmking.jrl.homework.bean0.main; - -import io.kimmking.jrl.homework.bean0.pojo.SchoolTeacher; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * @author jrl - * @date Create in 17:39 2022/4/9 - */ -public class main0 { - public static void main(String[] args) { - ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext4homework1.xml"); - String[] beanDefinitionNames = context.getBeanDefinitionNames(); - System.out.println(String.join(",", beanDefinitionNames)); - } -} diff --git a/04fx/spring01/src/main/resources/applicationContext4homework1.xml b/04fx/spring01/src/main/resources/applicationContext4homework1.xml index 8e1b77fa..90edc762 100644 --- a/04fx/spring01/src/main/resources/applicationContext4homework1.xml +++ b/04fx/spring01/src/main/resources/applicationContext4homework1.xml @@ -5,7 +5,9 @@ xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> - + + + From 3d1ab809a1b80c23031941aa2fbb18bc0db949bf Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Tue, 19 Apr 2022 14:52:22 +0800 Subject: [PATCH 33/64] Spring Boot starter --- .../src/main/java/com/example/app/App.java | 2 +- 04fx/my-starter/.gitignore | 33 ++ .../my-starter/.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 58727 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + 04fx/my-starter/mvnw | 316 ++++++++++++++++++ 04fx/my-starter/mvnw.cmd | 188 +++++++++++ 04fx/my-starter/pom.xml | 46 +++ .../mystarter/MyStarterApplication.java | 13 + .../config/LombokAutoConfigguration.java | 32 ++ .../config/LombokPropertiesConfiguration.java | 41 +++ .../main/resources/META-INF/spring.factories | 2 + .../src/main/resources/application.properties | 3 + .../mystarter/MyStarterApplicationTests.java | 13 + 13 files changed, 690 insertions(+), 1 deletion(-) create mode 100644 04fx/my-starter/.gitignore create mode 100644 04fx/my-starter/.mvn/wrapper/maven-wrapper.jar create mode 100644 04fx/my-starter/.mvn/wrapper/maven-wrapper.properties create mode 100644 04fx/my-starter/mvnw create mode 100644 04fx/my-starter/mvnw.cmd create mode 100644 04fx/my-starter/pom.xml create mode 100644 04fx/my-starter/src/main/java/top/jrl/homework/mystarter/MyStarterApplication.java create mode 100644 04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokAutoConfigguration.java create mode 100644 04fx/my-starter/src/main/java/top/jrl/homework/mystarter/config/LombokPropertiesConfiguration.java create mode 100644 04fx/my-starter/src/main/resources/META-INF/spring.factories create mode 100644 04fx/my-starter/src/main/resources/application.properties create mode 100644 04fx/my-starter/src/test/java/top/jrl/homework/mystarter/MyStarterApplicationTests.java diff --git a/04fx/app/src/main/java/com/example/app/App.java b/04fx/app/src/main/java/com/example/app/App.java index b02bfebf..7402ca99 100644 --- a/04fx/app/src/main/java/com/example/app/App.java +++ b/04fx/app/src/main/java/com/example/app/App.java @@ -18,7 +18,7 @@ public static void main(String[] args) { @Autowired WebInfo info; - // TODO_Joly:什么都没注册,那这里的目的是什么 + // DONE_Joly:什么都没注册,那这里的目的是什么--->为了运行一下,看看WebInfo注入了没有 @Bean public void printInfo() { System.out.println(info.getName()); 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 0000000000000000000000000000000000000000..c1dd12f17644411d6e840bd5a10c6ecda0175f18 GIT binary patch literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| literal 0 HcmV?d00001 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() { + } + +} From be14561d33603b8fe141f4cafb32b466f6895c38 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Tue, 19 Apr 2022 14:53:01 +0800 Subject: [PATCH 34/64] Spring Boot starter --- 04fx/starter-test/.gitignore | 33 ++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 58727 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + 04fx/starter-test/mvnw | 316 ++++++++++++++++++ 04fx/starter-test/mvnw.cmd | 188 +++++++++++ 04fx/starter-test/pom.xml | 46 +++ .../startertest/StarterTestApplication.java | 24 ++ .../src/main/resources/application.properties | 1 + .../StarterTestApplicationTests.java | 13 + 9 files changed, 623 insertions(+) create mode 100644 04fx/starter-test/.gitignore create mode 100644 04fx/starter-test/.mvn/wrapper/maven-wrapper.jar create mode 100644 04fx/starter-test/.mvn/wrapper/maven-wrapper.properties create mode 100644 04fx/starter-test/mvnw create mode 100644 04fx/starter-test/mvnw.cmd create mode 100644 04fx/starter-test/pom.xml create mode 100644 04fx/starter-test/src/main/java/top/jrl/homework/startertest/StarterTestApplication.java create mode 100644 04fx/starter-test/src/main/resources/application.properties create mode 100644 04fx/starter-test/src/test/java/top/jrl/homework/startertest/StarterTestApplicationTests.java 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 0000000000000000000000000000000000000000..c1dd12f17644411d6e840bd5a10c6ecda0175f18 GIT binary patch literal 58727 zcmb5W18`>1vNjyPv28mO+cqb*Z6_1kwr$(?#I}=(ZGUs`Jr}3`|DLbDUA3!L?dtC8 zUiH*ktDo+@6r@4HP=SCTA%WmZqm^Ro`Ls)bfPkcdfq?#g1(Fq27W^S8Cq^$TC?_c< zs-#ROD;6C)1wFuk7<3)nGuR^#!H;n&3*IjzXg+s8Z_S!!E0jUq(`}Itt=YdYa5Z_s z&e>2={87knpF*PKNzU;lsbk#P(l^WBvb$yEz)z+nYH43pKodrDkMp@h?;n{;K}hl>Fb^ zqx}C0|D7kg|Cj~3f7hn_zkAE}|6t|cZT|S5Hvb#3nc~C14u5UI{6#F<|FkJ0svs&S zA}S{=DXLT*BM1$`2rK%`D@vEw9l9%*=92X_2g?Fwfi=6Zfpr7+<~sgP#Bav+Df2ts zwtu~70zhqV?mrzM)}r7mMS`Hk_)NrI5K%CTtQtDxqw5iv5F0!ksIon{qqpPVnU?ds zN$|Vm{MHKEReUy>1kVfT-$3))Js0p2W_LFy3cjjZ7za0R zPdBH>y&pb0vr1|ckDpt2p$IQhwnPs5G*^b-y}sg4W!ALn}a`pY0JIa$H0$eV2T8WjWD= zWaENacQhlTyK4O!+aOXBurVR2k$eb8HVTCxy-bcHlZ4Xr!`juLAL#?t6|Ba!g9G4I zSwIt2Lla>C?C4wAZ8cKsZl9-Yd3kqE`%!5HlGdJJaFw0mu#--&**L-i|BcIdc3B$;0FC;FbE-dunVZ; zdIQ=tPKH4iJQQ=$5BeEMLov_Hn>gXib|9nOr}>eZt@B4W^m~>Zp#xhn1dax+?hS!AchWJ4makWZs@dQUeXQ zsI2+425_{X@t2KN zIbqec#)Jg5==VY3^YBeJ2B+%~^Y8|;F!mE8d(`UgNl2B9o>Ir5)qbBr)a?f%nrP zQyW(>FYPZjCVKDOU;Bw#PqPF1CCvp)dGdA&57a5hD&*vIc)jA)Z-!y5pS{5W6%#prH16zgD8s zexvpF#a|=*acp>L^lZ(PT)GiA8BJL-9!r8S$ZvXRKMVtiGe`+!@O%j<1!@msc177U zTDy>WOZu)W5anPrweQyjIu3IJC|ngdjZofGbdW&oj^DJlC7$;|xafB45evT|WBgGf-b|9y0J`fe0W-vw6xh}` z=(Tnq(-K0O{;VUcKe2y63{HXc+`R_#HLwnZ0rzWO*b#VeSuC4NG!H_ApCypbt1qx( z6y7Q$5(JOpQ&pTkc^0f}A0Kq*?;g9lEfzeE?5e2MBNZB)^8W1)YgdjsVyN+I9EZlh z3l}*}*)cFl=dOq|DvF=!ui$V%XhGQ%bDn3PK9 zV%{Y|VkAdt^d9~y4laGDqSwLd@pOnS&^@sI7}YTIb@El1&^_sq+{yAGf0|rq5TMp# z6d~;uAZ(fY3(eH=+rcbItl2=u6mf|P{lD4kiRCv;>GtFaHR3gim?WU9RjHmFZLm+m z+j<}_exaOQ1a}=K#voc~En+Mk_<(L!?1e#Uay~|H5q)LjD*yE6xFYQ-Wx{^iH1@pP zC0De#D6I26&W{;J40sZB!=%{c?XdO?YQvnTMA3TwfhAm@bvkX*(x?JTs*dFDv^=2X z284}AK)1nRn+8(Q2P?f)e>0~;NUI9%p%fnv1wBVpoXL+9OE`Vv1Y7=+nub$o7AN>y zB?R(^G8PYcMk4bxe7XItq@48QqWKb8fa*i9-N)=wdU-Q^=}!nFgTr_uT=Z=9pq z`{7!$U|+fnXFcsJ4GNm3JQQCN+G85k$)ZLhF{NbIy{REj84}Zt;0fe#>MARW)AoSb zrBpwF37ZVBMd>wZn_hAadI*xu8)Y#`aMbwRIA2n^-OS~M58_@j?#P1|PXJ1XBC9{4 zT^8*|xu<@(JlSOT*ILrVGr+7$nZN`Z3GxJJO@nY&mHsv^^duAh*lCu5q+S6zWA+`- z%^*y#)O7ko_RwGJl;bcEpP03FOrhlLWs`V_OUCrR-g>NJz*pN|itmN6O@Hw05Zq;Xtif%+sp4Py0{<7<^c zeoHHhRq>2EtYy9~2dZywm&OSk`u2ECWh6dJY?;fT-3-$U`!c(o$&hhPC%$~fT&bw3 zyj+8aXD;G!p*>BC6rpvx#6!|Qaic;KEv5>`Y+R(6F^1eIeYG6d1q3D3OL{7%7iw3R zwO)W7gMh27ASSB>-=OfP(YrKqBTNFv4hL@Im~~ombbSu44p~VoH$H-6+L_JW>Amkl zhDU~|r77?raaxD!-c$Ta?WAAi{w3T}YV=+S?1HQGC0+{Bny_^b+4Jum}oW4c=$ z#?D<}Ds{#d5v`L`${Pee;W84X*osNQ96xsKp^EAzuUh9#&zDX=eqdAp$UY)EGrkU% z(6m35n=46B$TNnejNSlih_!<)Iu@K!PW5S@Ya^0OK+EMWM=1w=GUKW^(r59U%i?d zzbo?|V4tDWGHHsrAQ}}ma#<`9r=M8%XF#%a=@Hn(p3wFBlkZ2L@8=*@J-^zuyF0aN zzJ7f!Jf8I+^6Tt$e+IIh zb80@?7y#Iz3w-0VEjgbHurqI>$qj<@n916)&O340!_5W9DtwR)P5mk6v2ljyK*DG5 zYjzE~m`>tq8HYXl%1JJ%e-%BqV4kRdPUZB1Cm$BQZr(fzp_@rn_W+;GwI$?L2Y4;b z)}c5D$#LT}2W8Si<`EHKIa_X+>+2PF(C*u~F=8E!jL(=IdQxY40%|( zoNg2Z&Aob@LEui-lJ#@)Ts)tE0_!*3{Uk)r{;-IZpX`N4mZX`#E|A;viQWImB6flI z?M_|xHCXV$5LOY-!U1_O1k;OWa=EchwlDCK4xHwBW2jE-6&%}og+9NILu${v10Z^Z#* zap|)B9a-AMU~>$r)3&|dQuP#MA$jnw54w*Ax~*_$iikp+j^OR8I5Fo<_UR#B-c>$? zeg)=;w^sGeAMi<3RGDRj$jA30Qq$e|zf2z;JyQ}tkU)ZI_k6tY%(`#AvL)p)iYXUy z5W9Su3NJ8mVyy)WqzFSk&vZM!;kUh8dVeA-myqcV%;xUne`PbHCPpvH?br`U2Y&dM zV!nJ!^n%`!H&!QSlpzLWnZpgi;#P0OAleH+<CfLa?&o|kyw1}W%6Pij zp$Vv5=;Z0LFN|j9i&9>zqX>*VnV3h#>n!2L?5gO6HJS3~kpy5G zYAVPMaB-FJOk3@OrxL(*-O~OB9^d{!G0K>wlzXuBm*$&%p1O#6SQ*?Q0CETLQ->XpfkW7< zj&Nep(}eAH1u$wWFvLV*lA{JOltP_%xKXC*a8DB&;{fD&2bATy>rC^kFY+$hFS7us;Y) zy_H?cv9XTHYz<4C<0b`WKC#{nJ15{F=oaq3x5}sYApT?Po+(Cmmo#dHZFO^{M#d~d znRT=TFATGVO%z_FNG-@G;9az|udZ>t@5l+A-K)BUWFn_|T#K3=d3EXRNqHyi#>;hX z*JQ`pT3#&tH>25laFlL6Rllu(seA*OboEd%rxMtz3@5v-+{qDP9&BcoS$2fgjgvp$ zc8!3=p0p@Ee1$u{Gg}Kkxg@M*qgZfYLlnD88{uwG1T?zxCbBR+x(RK$JB(eWJH#~; zZoY6L+esVRV?-*QmRCG}h`rB*Lv=uE%URF@+#l-g!Artx>Y9D;&G=jY2n2`J z{6-J%WX~Glx*QBmOOJ(RDRIzhfk&ibsm1t&&7aU{1P3U0uM%F2zJb4~50uby_ng+# zN)O9lK=dkJpxsUo7u8|e`Y~mmbxOTDn0i!i;d;ml#orN(Lc=j+n422NoSnlH6?0<0?th-qB7u}`5My%#?ES}>@RldOQz}WILz<$+cN~&ET zwUI01HCB((TyU$Ej8bxsE8oLmT-c7gA1Js?Iq`QMzIHV|)v)n2 zT_L(9x5%8*wU(C`VapaHoicWcm|0X@9TiNtbc|<4N6_H1F6&qgEEj=vjegFt;hC7- zLG7_=vedRFZ6Chbw!{#EpAlM?-sc#pc<~j#537n)M%RT)|L}y(ggi_-SLpsE3qi3V z=EEASxc>a{Su)jXcRS41Z@Mxk&0B7B<(?Izt5wpyyIBO|-M}ex8BhbIgi*X4 zDZ+Yk1<6&=PoZ=U-!9`!?sBVpYF#Y!JK<`fx}bXN651o0VVaW;t6ASVF@gq-mIDV_)?F^>rq1XX0NYy~(G=I6x%Fi5C2rMtvs z%P`g2>0{xLUy~#ye)%QAz^NkD5GUyPYl}K#;e-~UQ96`I$U0D!sMdQ>;%+c0h>k*Y z)sD1mi_@|rZnQ+zbWq~QxFlBQXj8WEY7NKaOYjUxAkGB8S#;l@b^C?;twRKl=mt0< zazifrBs`(q7_r14u1ZS`66VmsLpV>b5U!ktX>g4Nq~VPq6`%`3iCdr(>nS~uxxylU z>h(2p$XPJVh9BDpRLLzTDlNdp+oq8sOUlJ#{6boG`k)bwnsw5iy@#d{f_De-I|}vx6evw;ch97=;kLvM)-DBGwl6%fA%JItoMeyqjCR*_5Q70yd!KN zh=>ek8>f#~^6CJR0DXp0;7ifZjjSGBn}Cl{HeX!$iXMbtAU$F+;`%A<3TqbN#PCM& z&ueq$cB%pu2oMm_-@*aYzgn9`OiT@2ter*d+-$Aw42(@2Ng4mKG%M-IqX?q%3R|_( zN|&n$e1L#Ev=YMX5F53!O%))qDG3D(0rsOHblk;9ghWyqEOpg)mC$OduqpHAuIxr_>*|zy+|=EmOFn zFM+Ni%@CymLS-3vRWn=rVk?oZEz0V#y356IE6HR5#>7EigxZ05=cA|4<_tC8jyBJ| zgg!^kNwP7S^ooIj6riI9x`jFeQfRr4JCPumr<82M zto$j^Qb~MPmJ-|*2u{o7?yI8BI``zDaOCg2tG_5X;w<|uj5%oDthnLx-l4l)fmUGx z6N^jR|DC);yLi4q-ztTkf>*U$@2^w5(lhxu=OC|=WuTTp^!?2Nn27R`2FY_ zLHY-zFS}r+4|XyZw9b0D3)DmS!Gr+-LSdI}m{@-gL%^8CFSIYL?UZaCVd)2VI3|ay zwue39zshVrB+s2lp*};!gm<79@0HkjhgF^>`UhoR9Mi`aI#V#fI@x&1K3f&^8kaq% zkHVg$CTBoaGqEjrL)k*Y!rtiD2iQLYZ%|B}oBl8GHvR%n>HiIQN*+$mCN>I=c7H2N z&K4$4e@E^ff-cVHCbrHNMh4Dy|2Q;M{{xu|DYjeaRh2FK5QK!bG_K`kbBk$l$S4UF zq?F-%7UrX_Q?9M)a#WvcZ^R-fzJB5IFP>3uEoeCAAhN5W-ELRB&zsCnWY6#E?!)E56Pe+bxHjGF6;R9Hps)+t092-bf4 z_Wieg+0u5JL++k)#i0r?l`9*k)3ZlHOeMJ1DTdx9E1J2@BtdD3qX;&S_wMExOGv$T zl^T%oxb+)vq6vJvR`8{+YOsc@8}wSXpoK%v0k@8X*04Se3<8f)rE|fRXAoT!$6MdrKSuzeK@L*yug?MQs8oTbofqW)Df# zC2J3irHAaX_e~SGlBoRhEW`W6Z}&YX|5IMfzskAt{B*m z*w=3i!;x5Gfgc~>y9fPXFAPMhO@Si}SQESjh`P|dlV5HPRo7j(hV=$o8UMIT7~7+k z*@Sd>f%#{ARweJYhQs~ECpHie!~YXL|FJA;KS4m|CKFnT{fN`Ws>N?CcV@(>7WMPYN} z1}Wg+XU2(Yjpq7PJ|aSn;THEZ{4s8*@N!dz&bjys_Zk7%HiD+56;cF26`-a zEIo!B(T|L*uMXUvqJs&54`^@sUMtH-i~rOM9%$xGXTpmow$DxI>E5!csP zAHe|);0w%`I<==_Zw9t$e}?R+lIu%|`coRum(1p~*+20mBc?Z=$+z<0n&qS0-}|L4 zrgq|(U*eB%l3nfC=U1Y?(Tf@0x8bhdtsU2w&Y-WvyzkiyJ>GZqUP6c+<_p0`ZOnIK z#a~ynuzRWxO6c;S@*}B1pTjLJQHi(+EuE2;gG*p^Fq%6UoE1x95(^BY$H$$soSf=vpJ)_3E zp&$l=SiNaeoNLAK8x%XaHp3-So@F7 z3NMRRa@%k+Z$a%yb25ud&>Cdcb<+}n>=jZ`91)a z{wcA(j$%z#RoyB|&Z+B4%7Pe*No`pAX0Y;Ju4$wvJE{VF*Qej8C}uVF=xFpG^rY6Y+9mcz$T9^x(VP3uY>G3Zt&eU{pF*Bu<4j9MPbi4NMC=Z$kS6DMW9yN#vhM&1gd1t}8m(*YY9 zh2@s)$1p4yYT`~lYmU>>wKu+DhlnI1#Xn4(Rnv_qidPQHW=w3ZU!w3(@jO*f;4;h? zMH0!08(4=lT}#QA=eR(ZtW1=~llQij7)L6n#?5iY_p>|_mLalXYRH!x#Y?KHyzPB^ z6P3YRD}{ou%9T%|nOpP_??P;Rmra7$Q*Jz-f?42PF_y>d)+0Q^)o5h8@7S=je}xG# z2_?AdFP^t{IZHWK)9+EE_aPtTBahhUcWIQ7Awz?NK)ck2n-a$gplnd4OKbJ;;tvIu zH4vAexlK2f22gTALq5PZ&vfFqqERVT{G_d`X)eGI%+?5k6lRiHoo*Vc?ie6dx75_t z6hmd#0?OB9*OKD7A~P$e-TTv3^aCdZys6@`vq%Vi_D8>=`t&q9`Jn1=M#ktSC>SO3 z1V?vuIlQs6+{aHDHL?BB&3baSv;y#07}(xll9vs9K_vs2f9gC9Biy+9DxS77=)c z6dMbuokO-L*Te5JUSO$MmhIuFJRGR&9cDf)@y5OQu&Q$h@SW-yU&XQd9;_x;l z<`{S&Hnl!5U@%I~5p)BZspK894y7kVQE7&?t7Z|OOlnrCkvEf7$J5dR?0;Jt6oANc zMnb_Xjky|2ID#fhIB2hs-48Er>*M?56YFnjC)ixiCes%fgT?C|1tQupZ0Jon>yr|j z6M66rC(=;vw^orAMk!I1z|k}1Ox9qOILGJFxU*ZrMSfCe?)wByP=U73z+@Pfbcndc=VzYvSUnUy z+-B+_n`=f>kS8QBPwk+aD()=#IqkdxHPQMJ93{JGhP=48oRkmJyQ@i$pk(L&(p6<0 zC9ZEdO*i+t`;%(Ctae(SjV<@i%r5aune9)T4{hdzv33Uo9*K=V18S$6VVm^wgEteF za0zCLO(9~!U9_z@Qrh&rS|L0xG}RWoE1jXiEsrTgIF4qf#{0rl zE}|NGrvYLMtoORV&FWaFadDNCjMt|U8ba8|z&3tvd)s7KQ!Od*Kqe(48&C7=V;?`SQV)Qc?6L^k_vNUPbJ>>!5J?sDYm5kR&h_RZk)MfZ1 znOpQ|T;Me(%mdBJR$sbEmp3!HKDDSmMDnVpeo{S13l#9e6OImR$UPzjd-eCwmMwyT zm5~g6DIbY<_!8;xEUHdT(r_OQ<6QCE9Jy|QLoS>d(B zW6GRzX)~&Mx}})ITysFzl5_6JM*~ciBfVP(WF_r zY>z4gw&AxB%UV3Y{Y6z*t*o!p@~#u3X_t{Q9Us8ar8_9?N% zN&M~6y%2R(mAZ~@Tg1Oapt?vDr&fHuJ=V$wXstq|)eIG_4lB#@eU>fniJh zwJY<8yH5(+SSQ=$Y=-$2f$@^Ak#~kaR^NYFsi{XGlFCvK(eu{S$J(owIv17|p-%0O zL-@NyUg!rx0$Uh~JIeMX6JJE>*t<7vS9ev#^{AGyc;uio_-Je1?u#mA8+JVczhA2( zhD!koe;9$`Qgaxlcly4rdQ1VlmEHUhHe9TwduB+hm3wH2o27edh?|vrY{=;1Doy4& zIhP)IDd91@{`QQqVya(ASth4}6OY z-9BQj2d-%+-N7jO8!$QPq%o$9Fy8ja{4WT$gRP+b=Q1I48g-g|iLNjbhYtoNiR*d- z{sB}~8j*6*C3eM8JQj5Jn?mD#Gd*CrVEIDicLJ-4gBqUwLA-bp58UXko;M|ql+i5` zym-&U5BIS9@iPg#fFbuXCHrprSQKRU0#@yd%qrX1hhs*85R}~hahfFDq=e@bX))mf zWH%mXxMx|h5YhrTy;P_Xi_IDH*m6TYv>|hPX*_-XTW0G9iu!PqonQneKKaCVvvF^% zgBMDpN7!N?|G5t`v{neLaCFB{OyIl>qJQ_^0MJXQ zY2%-si~ej?F^%ytIIHU(pqT+3d+|IQ{ss#!c91R{2l*00e3ry!ha|XIsR%!q=E^Fal`6Oxu`K0fmPM?P6ZgzH7|TVQhl;l2 z)2w0L9CsN-(adU5YsuUw19OY_X69-!=7MIJ^(rUNr@#9l6aB8isAL^M{n2oD0FAHk97;X* z-INjZ5li`a|NYNt9gL2WbKT!`?%?lB^)J)9|025nBcBtEmWBRXQwi21EGg8>!tU>6Wf}S3p!>7vHNFSQR zgC>pb^&OHhRQD~7Q|gh5lV)F6i++k4Hp_F2L2WrcxH&@wK}QgVDg+y~o0gZ=$j&^W zz1aP8*cvnEJ#ffCK!Kz{K>yYW`@fc8ByF9X4XmyIv+h!?4&$YKl*~`ToalM{=Z_#^ zUs<1Do+PA*XaH;&0GW^tDjrctWKPmCF-qo7jGL)MK=XP*vt@O4wN1Y!8o`{DN|Rh) znK?nvyU&`ATc@U*l}=@+D*@l^gYOj&6SE|$n{UvyPwaiRQ_ua2?{Vfa|E~uqV$BhH z^QNqA*9F@*1dA`FLbnq;=+9KC@9Mel*>6i_@oVab95LHpTE)*t@BS>}tZ#9A^X7nP z3mIo+6TpvS$peMe@&=g5EQF9Mi9*W@Q`sYs=% z`J{3llzn$q;2G1{N!-#oTfQDY`8>C|n=Fu=iTk443Ld>>^fIr4-!R3U5_^ftd>VU> zij_ix{`V$I#k6!Oy2-z#QFSZkEPrXWsYyFURAo`Kl$LkN>@A?_);LE0rZIkmjb6T$ zvhc#L-Cv^4Ex*AIo=KQn!)A4;7K`pu-E+atrm@Cpmpl3e>)t(yo4gGOX18pL#xceU zbVB`#5_@(k{4LAygT1m#@(7*7f5zqB)HWH#TCrVLd9}j6Q>?p7HX{avFSb?Msb>Jg z9Q9DChze~0Psl!h0E6mcWh?ky! z$p#@LxUe(TR5sW2tMb#pS1ng@>w3o|r~-o4m&00p$wiWQ5Sh-vx2cv5nemM~Fl1Pn z@3ALEM#_3h4-XQ&z$#6X&r~U-&ge+HK6$)-`hqPj0tb|+kaKy*LS5@a9aSk!=WAEB z7cI`gaUSauMkEbg?nl0$44TYIwTngwzvUu0v0_OhpV;%$5Qgg&)WZm^FN=PNstTzW z5<}$*L;zrw>a$bG5r`q?DRc%V$RwwnGIe?m&(9mClc}9i#aHUKPLdt96(pMxt5u`F zsVoku+IC|TC;_C5rEU!}Gu*`2zKnDQ`WtOc3i#v}_9p>fW{L4(`pY;?uq z$`&LvOMMbLsPDYP*x|AVrmCRaI$UB?QoO(7mlBcHC};gA=!meK)IsI~PL0y1&{Dfm6! zxIajDc1$a0s>QG%WID%>A#`iA+J8HaAGsH z+1JH=+eX5F(AjmZGk|`7}Gpl#jvD6_Z!&{*kn@WkECV-~Ja@tmSR|e_L@9?N9 z3hyyry*D0!XyQh_V=8-SnJco#P{XBd1+7<5S3FA)2dFlkJY!1OO&M7z9uO?$#hp8K z><}uQS-^-B;u7Z^QD!7#V;QFmx0m%{^xtl3ZvPyZdi;^O&c;sNC4CHxzvvOB8&uHl zBN;-lu+P=jNn`2k$=vE0JzL{v67psMe_cb$LsmVfxA?yG z^q7lR00E@Ud3)mBPnT0KM~pwzZiBREupva^PE3~e zBgQ9oh@kcTk2)px3Hv^VzTtMzCG?*X(TDZ1MJ6zx{v- z;$oo46L#QNjk*1przHSQn~Ba#>3BG8`L)xla=P{Ql8aZ!A^Z6rPv%&@SnTI7FhdzT z-x7FR0{9HZg8Bd(puRlmXB(tB?&pxM&<=cA-;RT5}8rI%~CSUsR^{Dr%I2WAQghoqE5 zeQ874(T`vBC+r2Mi(w`h|d zA4x%EfH35I?h933@ic#u`b+%b+T?h=<}m@x_~!>o35p|cvIkkw07W=Ny7YcgssA_^ z|KJQrnu||Nu9@b|xC#C5?8Pin=q|UB?`CTw&AW0b)lKxZVYrBw+whPwZJCl}G&w9r zr7qsqm>f2u_6F@FhZU0%1Ioc3X7bMP%by_Z?hds`Q+&3P9-_AX+3CZ=@n!y7udAV2 zp{GT6;VL4-#t0l_h~?J^;trk1kxNAn8jdoaqgM2+mL&?tVy{I)e`HT9#Tr}HKnAfO zAJZ82j0+49)E0+=x%#1_D;sKu#W>~5HZV6AnZfC`v#unnm=hLTtGWz+21|p)uV+0= zDOyrLYI2^g8m3wtm-=pf^6N4ebLJbV%x`J8yd1!3Avqgg6|ar z=EM0KdG6a2L4YK~_kgr6w5OA;dvw0WPFhMF7`I5vD}#giMbMzRotEs&-q z^ji&t1A?l%UJezWv?>ijh|$1^UCJYXJwLX#IH}_1K@sAR!*q@j(({4#DfT|nj}p7M zFBU=FwOSI=xng>2lYo5*J9K3yZPwv(=7kbl8Xv0biOba>vik>6!sfwnH(pglq1mD-GrQi8H*AmfY*J7&;hny2F zupR}4@kzq+K*BE%5$iX5nQzayWTCLJ^xTam-EEIH-L2;huPSy;32KLb>>4 z#l$W^Sx7Q5j+Sy*E;1eSQQuHHWOT;1#LjoYpL!-{7W3SP4*MXf z<~>V7^&sY|9XSw`B<^9fTGQLPEtj=;<#x^=;O9f2{oR+{Ef^oZ z@N>P$>mypv%_#=lBSIr_5sn zBF-F_WgYS81vyW6$M;D_PoE&%OkNV1&-q+qgg~`A7s}>S`}cn#E$2m z%aeUXwNA(^3tP=;y5%pk#5Yz&H#AD`Jph-xjvZm_3KZ|J>_NR@croB^RUT~K;Exu5%wC}1D4nov3+@b8 zKyU5jYuQ*ZpTK23xXzpN51kB+r*ktnQJ7kee-gP+Ij0J_#rFTS4Gux;pkVB;n(c=6 zMks#)ZuXUcnN>UKDJ-IP-u2de1-AKdHxRZDUGkp)0Q#U$EPKlSLQSlnq)OsCour)+ zIXh@3d!ImInH7VrmR>p8p4%n;Tf6l2jx1qjJu>e3kf5aTzU)&910nXa-g0xn$tFa& z2qZ7UAl*@5o=PAh`6L${6S-0?pe3thPB4pahffb$#nL8ncN(Nyos`}r{%{g64Ji^= zK8BIywT0-g4VrhTt}n~Y;3?FGL74h?EG*QfQy0A8u>BtXuI{C-BYu*$o^}U1)z;8d zVN(ssw?oCbebREPD~I$-t7}`_5{{<0d10So7Pc2%EREdpMWIJI&$|rq<0!LL+BQM4 zn7)cq=qy|8YzdO(?NOsVRk{rW)@e7g^S~r^SCawzq3kj#u(5@C!PKCK0cCy zT@Tey2IeDYafA2~1{gyvaIT^a-Yo9kx!W#P-k6DfasKEgFji`hkzrmJ#JU^Yb%Nc~ zc)+cIfTBA#N0moyxZ~K!`^<>*Nzv-cjOKR(kUa4AkAG#vtWpaD=!Ku&;(D#(>$&~B zI?V}e8@p%s(G|8L+B)&xE<({g^M`#TwqdB=+oP|5pF3Z8u>VA!=w6k)zc6w2=?Q2` zYCjX|)fRKI1gNj{-8ymwDOI5Mx8oNp2JJHG3dGJGg!vK>$ji?n>5qG)`6lEfc&0uV z)te%G&Q1rN;+7EPr-n8LpNz6C6N0*v{_iIbta7OTukSY zt5r@sO!)rjh0aAmShx zd3=DJ3c(pJXGXzIh?#RR_*krI1q)H$FJ#dwIvz);mn;w6Rlw+>LEq4CN6pP4AI;!Y zk-sQ?O=i1Mp5lZX3yka>p+XCraM+a!1)`F`h^cG>0)f0OApGe(^cz-WoOno-Y(EeB zVBy3=Yj}ak7OBj~V259{&B`~tbJCxeVy@OEE|ke4O2=TwIvf-=;Xt_l)y`wuQ-9#D z(xD-!k+2KQzr`l$7dLvWf*$c8=#(`40h6d$m6%!SB1JzK+tYQihGQEwR*-!cM>#LD>x_J*w(LZbcvHW@LTjM?RSN z0@Z*4$Bw~Ki3W|JRI-r3aMSepJNv;mo|5yDfqNLHQ55&A>H5>_V9<_R!Ip`7^ylX=D<5 zr40z>BKiC@4{wSUswebDlvprK4SK2!)w4KkfX~jY9!W|xUKGTVn}g@0fG94sSJGV- z9@a~d2gf5s>8XT@`If?Oway5SNZS!L5=jpB8mceuf2Nd%aK2Zt|2FVcg8~7O{VPgI z#?H*_Kl!9!B}MrK1=O!Aw&faUBluA0v#gWVlAmZt;QN7KC<$;;%p`lmn@d(yu9scs zVjomrund9+p!|LWCOoZ`ur5QXPFJtfr_b5%&Ajig2dI6}s&Fy~t^j}()~4WEpAPL= zTj^d;OoZTUf?weuf2m?|R-7 z*C4M6ZhWF(F@2}nsp85rOqt+!+uZz3$ReX#{MP5-r6b`ztXDWl$_mcjFn*{sEx7f*O(ck+ou8_?~a_2Ztsq6qB|SPw26k!tLk{Q~Rz z$(8F1B;zK-#>AmmDC7;;_!;g&CU7a?qiIT=6Ts0cbUNMT6yPRH9~g zS%x{(kxYd=D&GKCkx;N21sU;OI8@4vLg2}L>Lb{Qv`B*O0*j>yJd#`R5ypf^lp<7V zCc|+>fYgvG`ROo>HK+FAqlDm81MS>&?n2E-(;N7}oF>3T9}4^PhY=Gm`9i(DPpuS- zq)>2qz!TmZ6q8;&M?@B;p1uG6RM_Y8zyId{-~XQD_}bXL{Jp7w`)~IR{l5a2?7!Vg zp!OfP4E$Ty_-K3VY!wdGj%2RL%QPHTL)uKfO5Am5<$`5 zHCBtvI~7q-ochU`=NJF*pPx@^IhAk&ZEA>w$%oPGc-}6~ywV~3-0{>*sb=|ruD{y$ ze%@-m`u28vKDaf*_rmN`tzQT>&2ltg-lofR8~c;p;E@`zK!1lkgi?JR0 z+<61+rEupp7F=mB=Ch?HwEjuQm}1KOh=o@ zMbI}0J>5}!koi&v9?!B?4FJR88jvyXR_v{YDm}C)lp@2G2{a{~6V5CwSrp6vHQsfb-U<{SSrQ zhjRbS;qlDTA&TQ2#?M(4xsRXFZ^;3A+_yLw>o-9GJ5sgsauB`LnB-hGo9sJ~tJ`Q>=X7sVmg<=Fcv=JDe*DjP-SK-0mJ7)>I zaLDLOU*I}4@cro&?@C`hH3tiXmN`!(&>@S2bFyAvI&axlSgd=!4IOi#+W;sS>lQ28 zd}q&dew9=x;5l0kK@1y9JgKWMv9!I`*C;((P>8C@JJRGwP5EL;JAPHi5fI|4MqlLU z^4D!~w+OIklt7dx3^!m6Be{Lp55j{5gSGgJz=hlNd@tt_I>UG(GP5s^O{jFU;m~l0 zfd`QdE~0Ym=6+XN*P`i0ogbgAJVjD9#%eBYJGIbDZ4s(f-KRE_>8D1Dv*kgO1~NSn zigx8f+VcA_xS)V-O^qrs&N9(}L!_3HAcegFfzVAntKxmhgOtsb4k6qHOpGWq6Q0RS zZO=EomYL%;nKgmFqxD<68tSGFOEM^u0M(;;2m1#4GvSsz2$jawEJDNWrrCrbO<}g~ zkM6516erswSi_yWuyR}}+h!VY?-F!&Y5Z!Z`tkJz&`8AyQ=-mEXxkQ%abc`V1s>DE zLXd7!Q6C)`7#dmZ4Lm?>CTlyTOslb(wZbi|6|Pl5fFq3y^VIzE4DALm=q$pK>-WM> z@ETsJj5=7=*4 z#Q8(b#+V=~6Gxl?$xq|?@_yQJ2+hAYmuTj0F76c(B8K%;DPhGGWr)cY>SQS>s7%O- zr6Ml8h`}klA=1&wvbFMqk}6fml`4A%G=o@K@8LHifs$)}wD?ix~Id@9-`;?+I7 zOhQN(D)j=^%EHN16(Z3@mMRM5=V)_z(6y^1b?@Bn6m>LUW7}?nupv*6MUVPSjf!Ym zMPo5YoD~t(`-c9w)tV%RX*mYjAn;5MIsD?0L&NQ#IY`9k5}Fr#5{CeTr)O|C2fRhY z4zq(ltHY2X)P*f?yM#RY75m8c<%{Y?5feq6xvdMWrNuqnR%(o(uo8i|36NaN<#FnT ze-_O*q0DXqR>^*1sAnsz$Ueqe5*AD@Htx?pWR*RP=0#!NjnaE-Gq3oUM~Kc9MO+o6 z7qc6wsBxp7GXx+hwEunnebz!|CX&`z{>loyCFSF-zg za}zec;B1H7rhGMDfn+t9n*wt|C_0-MM~XO*wx7-`@9~-%t?IegrHM(6oVSG^u?q`T zO<+YuVbO2fonR-MCa6@aND4dBy^~awRZcp!&=v+#kH@4jYvxt=)zsHV0;47XjlvDC8M1hSV zm!GB(KGLwSd{F-?dmMAe%W0oxkgDv8ivbs__S{*1U}yQ=tsqHJYI9)jduSKr<63$> zp;a-B^6Hg3OLUPi1UwHnptVSH=_Km$SXrCM2w8P z%F#Boi&CcZ5vAGjR1axw&YNh~Q%)VDYUDZ6f^0;>W7_sZr&QvRWc2v~p^PqkA%m=S zCwFUg2bNM(DaY>=TLmOLaDW&uH;Za?8BAwQo4+Xy4KXX;Z}@D5+}m)U#o?3UF}+(@jr$M4ja*`Y9gy~Y`0 z6Aex1*3ng@2er)@{%E9a3A;cts9cAor=RWt7ege)z=$O3$d5CX&hORZ3htL>jj5qT zW#KGQ;AZ|YbS0fvG~Y)CvVwXnBLJkSps7d~v;cj$D3w=rB9Tx>a&4>(x00yz!o*SOd*M!yIwx;NgqW?(ysFv8XLxs6Lrh8-F`3FO$}V{Avztc4qmZ zoz&YQR`*wWy_^&k-ifJ&N8Qh=E-fH6e}-}0C{h~hYS6L^lP>=pLOmjN-z4eQL27!6 zIe2E}knE;dxIJ_!>Mt|vXj%uGY=I^8(q<4zJy~Q@_^p@JUNiGPr!oUHfL~dw9t7C4I9$7RnG5p9wBpdw^)PtGwLmaQM=KYe z;Dfw@%nquH^nOI6gjP+K@B~0g1+WROmv1sk1tV@SUr>YvK7mxV3$HR4WeQ2&Y-{q~ z4PAR&mPOEsTbo~mRwg&EJE2Dj?TOZPO_@Z|HZX9-6NA!%Pb3h;G3F5J+30BoT8-PU z_kbx`I>&nWEMtfv(-m>LzC}s6q%VdBUVI_GUv3@^6SMkEBeVjWplD5y58LyJhikp4VLHhyf?n%gk0PBr(PZ3 z+V`qF971_d@rCO8p#7*#L0^v$DH>-qB!gy@ut`3 zy3cQ8*t@@{V7F*ti(u{G4i55*xY9Erw3{JZ8T4QPjo5b{n=&z4P^}wxA;x85^fwmD z6mEq9o;kx<5VneT_c-VUqa|zLe+BFgskp_;A)b>&EDmmP7Gx#nU-T@;O+(&&n7ljK zqK7&yV!`FIJAI+SaA6y=-H=tT`zWvBlaed!3X^_Lucc%Q=kuiG%65@@6IeG}e@`ieesOL} zKHBJBso6u&7gzlrpB%_yy<>TFwDI>}Ec|Gieb4=0fGwY|3YGW2Dq46=a1 zVo`Vi%yz+L9)9hbb%FLTC@-G(lODgJ(f&WmSCK9zV3-IV7XI<{2j}ms_Vmb!os)06 zhVIZPZF)hW--kWTCyDVRd2T&t|P&aDrtO5kzXy<*A+5$k7$>4+y%;% znYN-t#1^#}Z6d+ahj*Gzor+@kBD7@f|IGNR$4U=Y0J2#D2)YSxUCtiC1weJg zLp0Q&JFrt|In8!~1?fY0?=fPyaqPy$iQXJDhHP>N%B42Yck`Qz-OM_~GMuWow)>=Q z0pCCC7d0Z^Ipx29`}P3;?b{dO?7z0e{L|O*Z}nxi>X|RL8XAw$1eOLKd5j@f{RQ~Y zG?7$`hy@s7IoRF2@KA%2ZM6{ru9T5Gj)iDCz};VvlG$WuT+>_wCTS~J6`I9D{nsrU z2;X#OyopBgo778Q>D%_E>rMN~Po~d5H<`8|Zcv}F`xL5~NCVLX4Wkg007HhMgj9Pa z94$km3A+F&LzOJlpeFR*j+Y%M!Qm42ziH~cKM&3b;15s)ycD@3_tL-dk{+xP@J7#o z-)bYa-gd2esfy<&-nrj>1{1^_L>j&(MA1#WNPg3UD?reL*}V{ag{b!uT755x>mfbZ z0PzwF+kx91`qqOn`1>xw@801XAJlH>{`~|pyi6J;3s=cTOfelA&K5HX#gBp6s<|r5 zjSSj+CU*-TulqlnlP`}?)JkJ_7fg){;bRlXf+&^e8CWwFqGY@SZ=%NmLCXpYb+}7* z$4k}%iFUi^kBdeJg^kHt)f~<;Ovlz!9frq20cIj>2eIcG(dh57ry;^E^2T)E_8#;_9iJT>4sdCB_db|zO?Z^*lBN zNCs~f+Jkx%EUgkN2-xFF?B%TMr4#)%wq?-~+Nh;g9=n3tM>i5ZcH&nkVcPXgYRjG@ zf(Y7WN@hGV7o0bjx_2@bthJ`hjXXpfaes_(lWIw!(QK_nkyqj?{j#uFKpNVpV@h?7_WC3~&%)xHR1kKo`Cypj15#%0m z-o0GXem63g^|IltM?eZV=b+Z2e8&Z1%{0;*zmFc62mNqLTy$Y_c|9HiH0l>K z+mAx7DVYoHhXfdCE8Bs@j=t0f*uM++Idd25BgIm`Ad;I_{$mO?W%=JF82blr8rl>yMk6?pM z^tMluJ-ckG_}OkxP91t2o>CQ_O8^VZn$s$M_APWIXBGBq0Lt^YrTD5(Vwe2ta4y#DEYa(W~=eLOy7rD^%Vd$kL27M)MSpwgoP3P{ z!yS$zc|uP{yzaIqCwE!AfYNS;KW|OdP1Q%!LZviA0e^WDsIS5#= z!B{TW)VB)VHg{LoS#W7i6W>*sFz!qr^YS0t2kh90y=Je5{p>8)~D@dLS@QM(F# zIp{6M*#(@?tsu1Rq-Mdq+eV}ibRSpv#976C_5xlI`$#1tN`sK1?)5M+sj=OXG6dNu zV1K{y>!i0&9w8O{a>`IA#mo(3a zf*+Q=&HW7&(nX8~C1tiHZj%>;asBEp$p_Q!@Y0T8R~OuPEy3Lq@^t$8=~(FhPVmJJ z#VF8`(fNzK-b%Iin7|cxWP0xr*M&zoz|fCx@=Y!-0j_~cuxsDHHpmSo)qOalZ$bRl z2F$j0k3llJ$>28HH3l_W(KjF^!@LwtLej_b9;i;{ku2x+&WA@jKTO0ad71@_Yta!{ z2oqhO4zaU433LK371>E{bZ?+3kLZ9WQ2+3PTZAP90%P13Yy3lr3mhmy|>eN6(SHs1C%Q39p)YsUr7(kuaoIJGJhXV-PyG zjnxhcAC;fqY@6;MWWBnRK6ocG`%T&0&*k95#yK7DFtZV?;cy;!RD_*YJjsb6Q`$;K zy)&X{P`*5xEgjTQ9r=oh0|>Z_yeFm?ev!p z7q;JA4mtu@qa39v%6i)Z4%qwdxcHuOMO;a1wFMP_290FqH1OsmCG{ zq^afYrz2BQyQ0*JGE}1h!W9fKgk$b!)|!%q(1x?5=}PpmZQ$e;2EB*k4%+&+u;(E* z2n@=9HsqMv;4>Nn^2v&@4T-YTkd`TdWU^U*;sA5|r7TjZGnLY*xC=_K-GmDfkWEGC z;oN&!c1xB-<4J7=9 zJ(BedZwZhG4|64<=wvCn4)}w%Zx_TEs6ehmjVG&p5pi46r zg=3-3Q~;v55KR&8CfG;`Lv6NsXB}RqPVyNeKAfj9=Ol>fQlEUl2cH7=mPV!68+;jgtKvo5F#8&9m? z``w+#S5UR=QHFGM~noocC zVFa#v2%oo{%;wi~_~R2ci}`=B|0@ zinDfNxV3%iHIS(7{h_WEXqu!v~`CMH+7^SkvLe_3i}=pyDRah zN#L)F-`JLj6BiG}sj*WBmrdZuVVEo86Z<6VB}s)T$ZcWvG?i0cqI}WhUq2Y#{f~x# zi1LjxSZCwiKX}*ETGVzZ157=jydo*xC^}mJ<+)!DDCd4sx?VM%Y;&CTpw5;M*ihZ| zJ!FBJj0&j&-oJs?9a_I$;jzd%7|pdsQ3m`bPBe$nLoV1!YV8?Pw~0D zmSD-5Ue60>L$Rw;yk{_2d~v@CnvZa%!7{{7lb$kxWx!pzyh;6G~RbN5+|mFTbxcxf!XyfbLI^zMQSb6P~xzESXmV{9 zCMp)baZSz%)j&JWkc|Gq;_*$K@zQ%tH^91X2|Byv>=SmWR$7-shf|_^>Ll;*9+c(e z{N%43;&e8}_QGW+zE0m0myb-@QU%=Qo>``5UzB(lH0sK=E``{ZBl2Ni^-QtDp0ME1 zK88E-db_XBZQaU}cuvkCgH7crju~9eE-Y`os~0P-J=s;aS#wil$HGdK;Ut?dSO71ssyrdm{QRpMAV2nXslvlIE#+Oh>l7y_~?;}F!;ENCR zO+IG#NWIRI`FLntsz^FldCkky2f!d-%Pij9iLKr>IfCK);=}}?(NL%#4PfE(4kPQN zSC%BpZJ*P+PO5mHw0Wd%!zJsn&4g<$n#_?(=)JnoR2DK(mCPHp6e6VdV>?E5KCUF@ zf7W9wm%G#Wfm*NxTWIcJX-qtR=~NFxz4PSmDVAU8(B2wIm#IdHae-F{3jKQFiX?8NlKEhXR2Z|JCUd@HMnNVwqF~V9YJtD+T zQlOroDX-mg2% zBKV^Q5m5ECK{nWjJ7FHOSUi*a-C_?S_yo~G5HuRZH6R``^dS3Bh6u!nD`kFbxYThD zw~2%zL4tHA26rcdln4^=A(C+f9hLlcuMCv{8`u;?uoEVbU=YVNkBP#s3KnM@Oi)fQ zt_F3VjY)zASub%Q{Y?XgzlD3M5#gUBUuhW;$>uBSJH9UBfBtug*S|-;h?|L#^Z&uE zB&)spqM89dWg9ZrXi#F{KtL@r9g^xeR8J+$EhL~2u@cf`dS{8GUC76JP0hHtCKRg0 zt*rVyl&jaJAez;!fb!yX^+So4-8XMNpP@d3H*eF%t_?I|zN^1Iu5aGBXSm+}eCqn3 z^+vzcM*J>wV-FJRrx@^5;l>h0{OYT)lg{dr8!{s7(i{5T|3bivDoTonV1yo1@nVPR zXxEgGg^x5KHgp?=$xBwm_cKHeDurCgO>$B$GSO`Cd<~J8@>ni>Z-Ef!3+ck(MHVy@ z@#<*kCOb5S$V+Fvc@{Qv$oLfnOAG&YO5z_E2j6E z7a+c(>-`H)>g+6DeY1Y*ag-B6>Cl@@VhkZY@Uihe!{LlRpuTsmIsN4;+UDsHd954n9WZV6qq*{qZ5j<W)`UorOmXtVnLo3T{t#h3q^fooqQ~A+EY<$TDG4RKP*cK0liX95STt= zToC<2M2*(H1tZ)0s|v~iSAa^F-9jMwCy4cK0HM*3$@1Q`Pz}FFYm`PGP0wuamWrt*ehz3(|Fn%;0;K4}!Q~cx{0U0L=cs6lcrY^Y%Vf_rXpQIw~DfxB-72tZU6gdK8C~ea6(2P@kGH}!2N?>r(Ca{ zsI!6B!alPl%j1CHq97PTVRng$!~?s2{+6ffC#;X2z(Xb#9GsSYYe@9zY~7Dc7Hfgh z5Tq!})o30pA3ywg<9W3NpvUs;E%Cehz=s?EfLzcV0H?b{=q?vJCih2y%dhls6w3j$ zk9LB0L&(15mtul3T^QSK7KIZVTod#Sc)?1gzY~M=?ay87V}6G?F>~AIv()-N zD3rHX`;r;L{9N|Z8REN}OZB&SZ|5a80B%dQd-CNESP7HnuNn43T~Agcl1YOF@#W03 z1b*t!>t5G@XwVygHYczDIC|RdMB+ z$s5_5_W-EXN-u_5Pb{((!+8xa+?@_#dwtYHeJ_49Dql%3Fv0yXeV?!cC&Iqx@s~P%$X6%1 zYzS9pqaUv&aBQqO zBQs7d63FZIL1B&<8^oni%CZOdf6&;^oNqQ-9j-NBuQ^|9baQuZ^Jtyt&?cHq$Q9JE z5D>QY1?MU7%VVbvjysl~-a&ImiE(uFwHo{!kp;Jd`OLE!^4k8ID{`e-&>2uB7XB~= z+nIQGZ8-Sbfa}OrVPL}!mdieCrs3Nq8Ic_lpTKMIJ{h>XS$C3`h~ z?p2AbK~%t$t(NcOq5ZB3V|`a0io8A))v_PMt)Hg3x+07RL>i zGUq@t&+VV`kj55_snp?)Y@0rKZr`riC`9Q(B1P^nxffV9AvBLPrE<8D>ZP{HCDY@JIvYcYNRz8 z0Rf+Q0riSU@KaVpK)0M{2}Wuh!o~t*6>)EZSCQD{=}N4Oxjo1KO-MNpPYuPABh}E|rM!=TSl^F%NV^dg+>WNGi@Q5C z%JGsP#em`4LxDdIzA@VF&`2bLDv%J)(7vedDiXDqx{y6$Y0o~j*nVY73pINPCY?9y z$Rd&^64MN)Pkxr-CuZ+WqAJx6vuIAwmjkN{aPkrJ0I4F5-Bl}$hRzhRhZ^xN&Oe5$ za4Wrh6PyFfDG+Nzd8NTp2})j>pGtyejb&;NkU3C5-_H;{?>xK1QQ9S`xaHoMgee=2 zEbEh+*I!ggW@{T{qENlruZT)ODp~ZXHBc_Ngqu{jyC#qjyYGAQsO8VT^lts$z0HP+ z2xs^QjUwWuiEh863(PqO4BAosmhaK`pEI{-geBD9UuIn8ugOt-|6S(xkBLeGhW~)< z8aWBs0)bzOnY4wC$yW{M@&(iTe{8zhDnKP<1yr9J8akUK)1svAuxC)}x-<>S!9(?F zcA?{_C?@ZV2Aei`n#l(9zu`WS-hJsAXWt(SGp4(xg7~3*c5@odW;kXXbGuLOFMj{d z{gx81mQREmRAUHhfp#zoWh>z}GuS|raw1R#en%9R3hSR`qGglQhaq>#K!M%tooG;? zzjo}>sL7a3M5jW*s8R;#Y8b(l;%*I$@YH9)YzWR!T6WLI{$8ScBvw+5&()>NhPzd! z{>P(yk8{(G&2ovV^|#1HbcVMvXU&;0pk&6CxBTvBAB>#tK~qALsH`Ad1P0tAKWHv+BR8Fv4!`+>Obu1UX^Ov zmOpuS@Ui|NK4k-)TbG?+9T$)rkvq+?=0RDa=xdmY#JHLastjqPXdDbShqW>7NrHZ7 z7(9(HjM1-Ef(^`%3TlhySDJ27vQ?H`xr9VOM%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| literal 0 HcmV?d00001 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() { + } + +} From e3123be93b2fc7b410ed0f601211d332ba7b27d7 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sat, 23 Apr 2022 14:24:06 +0800 Subject: [PATCH 35/64] JDBC Hikari --- 04fx/jdbc/.gitignore | 33 ++ 04fx/jdbc/.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 58727 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + 04fx/jdbc/README.md | 5 + 04fx/jdbc/mvnw | 316 ++++++++++++++++++ 04fx/jdbc/mvnw.cmd | 188 +++++++++++ .../java/top/jrl/homework/jdbc/JDBCCRUD.java | 44 +++ .../jrl/homework/jdbc/JdbcApplication.java | 13 + .../jrl/homework/jdbc/MyHikariDataSource.java | 31 ++ .../homework/jdbc/PrepareStatementJDBC.java | 75 +++++ .../jdbc/connection/BasicConnectionPool.java | 102 ++++++ .../jdbc/connection/ConnectionPool.java | 24 ++ .../src/main/resources/application.properties | 1 + .../homework/jdbc/JdbcApplicationTests.java | 13 + 14 files changed, 847 insertions(+) create mode 100644 04fx/jdbc/.gitignore create mode 100644 04fx/jdbc/.mvn/wrapper/maven-wrapper.jar create mode 100644 04fx/jdbc/.mvn/wrapper/maven-wrapper.properties create mode 100644 04fx/jdbc/README.md create mode 100644 04fx/jdbc/mvnw create mode 100644 04fx/jdbc/mvnw.cmd create mode 100644 04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JDBCCRUD.java create mode 100644 04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JdbcApplication.java create mode 100644 04fx/jdbc/src/main/java/top/jrl/homework/jdbc/MyHikariDataSource.java create mode 100644 04fx/jdbc/src/main/java/top/jrl/homework/jdbc/PrepareStatementJDBC.java create mode 100644 04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/BasicConnectionPool.java create mode 100644 04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/ConnectionPool.java create mode 100644 04fx/jdbc/src/main/resources/application.properties create mode 100644 04fx/jdbc/src/test/java/top/jrl/homework/jdbc/JdbcApplicationTests.java 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 0000000000000000000000000000000000000000..c1dd12f17644411d6e840bd5a10c6ecda0175f18 GIT binary patch literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| literal 0 HcmV?d00001 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/04fx/jdbc/mvnw b/04fx/jdbc/mvnw new file mode 100644 index 00000000..8a8fb228 --- /dev/null +++ b/04fx/jdbc/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/jdbc/mvnw.cmd b/04fx/jdbc/mvnw.cmd new file mode 100644 index 00000000..1d8ab018 --- /dev/null +++ b/04fx/jdbc/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/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..6377a827 --- /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..445d829b --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/MyHikariDataSource.java @@ -0,0 +1,31 @@ +package top.jrl.homework.jdbc; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @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..88b59de9 --- /dev/null +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/connection/ConnectionPool.java @@ -0,0 +1,24 @@ +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/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() { + } + +} From 81154825811f4c721ee30947a385fc85c3f5906b Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 24 Apr 2022 22:46:04 +0800 Subject: [PATCH 36/64] =?UTF-8?q?JDBC=20=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/top/jrl/homework/jdbc/JDBCCRUD.java | 2 +- .../top/jrl/homework/jdbc/MyHikariDataSource.java | 2 ++ .../homework/jdbc/connection/ConnectionPool.java | 1 + .../learn/transaction/TransactionApplication.java | 13 +++++++++++++ .../transaction/TransactionApplicationTests.java | 13 +++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 04fx/jdbc/src/main/java/top/jrl/learn/transaction/TransactionApplication.java create mode 100644 04fx/jdbc/src/test/java/top/jrl/learn/transaction/TransactionApplicationTests.java 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 index 6377a827..182872fd 100644 --- a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JDBCCRUD.java +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/JDBCCRUD.java @@ -32,7 +32,7 @@ public static void main(String[] args) throws SQLException { //4.2 增 int executeUpdate = statement.executeUpdate("insert into person values (26,'Jolin-super',0)"); //5.2 增 - if (executeUpdate != -1){ + if (executeUpdate != -1) { System.out.println(executeUpdate); } //6.关闭资源 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 index 445d829b..2e06f98d 100644 --- a/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/MyHikariDataSource.java +++ b/04fx/jdbc/src/main/java/top/jrl/homework/jdbc/MyHikariDataSource.java @@ -7,6 +7,8 @@ import java.sql.SQLException; /** + * https://www.baeldung.com/hikaricp + * * @author jrl * @date Create in 14:16 2022/4/23 */ 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 index 88b59de9..b3badd55 100644 --- 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 @@ -5,6 +5,7 @@ /** * 自制数据库连接池 * https://www.baeldung.com/java-connection-pooling + * * @author jrl * @date Create in 11:35 2022/4/23 */ 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/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() { + } + +} From d3735ade53fc201c7e0bc3bdb68932c92b2a2299 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 24 Apr 2022 22:46:18 +0800 Subject: [PATCH 37/64] Lombok --- 04fx/java8/README.md | 5 +++ 04fx/java8/pom.xml | 1 + .../src/main/java/io/kimmking/java8/A.java | 6 ++++ .../java/io/kimmking/java8/LombokDemo.java | 31 ++++++++++++++++--- .../main/java/io/kimmking/java8/Student.java | 27 +++++++++------- .../java/io/kimmking/java8/Student4Data.java | 15 +++++++++ 04fx/java8/src/main/java/jrl/README.md | 1 + 7 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 04fx/java8/README.md create mode 100644 04fx/java8/src/main/java/io/kimmking/java8/Student4Data.java create mode 100644 04fx/java8/src/main/java/jrl/README.md 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/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/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/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 From 7b61d4347379f7cd3a1777dafa6e7b534f83a1b2 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Thu, 23 Jun 2022 17:39:39 +0800 Subject: [PATCH 38/64] =?UTF-8?q?=E8=87=AA=E5=B7=B1=E5=8A=A8=E6=89=8B?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0RPC=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md" | 3 + .../pom.xml" | 66 ++++ .../concurrency/interview/MultiThread.java" | 31 ++ .../java/top/jrl/concurrency/part1/Calc.java" | 41 +++ .../java/top/jrl/concurrency/part2/Abc3.java" | 59 ++++ .../jrl/concurrency/part2/BlockedQueue.java" | 55 +++ .../top/jrl/concurrency/part2/Integer1.java" | 16 + .../top/jrl/concurrency/part2/Vector1.java" | 37 ++ 03concurrency/README2.md | 12 + 03concurrency/README3.md | 3 + .../java/io/kimmking/java8/GuavaDemo.java | 101 +++--- 07rpc/rpc/.gitignore | 33 ++ 07rpc/rpc/.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 58727 bytes .../rpc/.mvn/wrapper/maven-wrapper.properties | 2 + 07rpc/rpc/README.md | 1 + 07rpc/rpc/mvnw | 316 ++++++++++++++++++ 07rpc/rpc/mvnw.cmd | 188 +++++++++++ 07rpc/rpc/pom.xml | 54 +++ .../java/top/jrl/lean/rpc/RpcApplication.java | 13 + .../java/top/jrl/lean/rpc/syntac/Reflec.java | 10 + .../src/main/resources/application.properties | 1 + .../top/jrl/lean/rpc/RpcApplicationTests.java | 13 + 07rpc/rpc01/README.md | 15 + 07rpc/rpc01/rpcfx-core/README.md | 14 + 07rpc/rpc01/rpcfx-core/pom.xml | 2 +- .../io/kimmking/rpcfx/api/RpcfxRequest.java | 7 +- .../io/kimmking/rpcfx/api/RpcfxResponse.java | 9 +- .../java/io/kimmking/rpcfx/client/Rpcfx.java | 58 +++- .../kimmking/rpcfx/server/RpcfxInvoker.java | 14 +- .../io/kimmking/rpcfx/demo/api/Order.java | 2 +- .../kimmking/rpcfx/demo/api/OrderService.java | 2 +- .../demo/consumer/RpcfxClientApplication.java | 17 +- 07rpc/rpc01/rpcfx-demo-provider/README.md | 3 + .../rpcfx/demo/provider/DemoResolver.java | 6 +- .../rpcfx/demo/provider/OrderServiceImpl.java | 6 +- .../rpcfx/demo/provider/UserServiceImpl.java | 6 + .../src/main/resources/application.yml | 2 +- 07rpc/rpc02/dubbo-demo-provider/README.md | 1 + 38 files changed, 1156 insertions(+), 63 deletions(-) create mode 100644 "03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/README.md" create mode 100644 "03concurrency/Java\345\271\266\345\217\221\347\274\226\347\250\213\345\256\236\346\210\230/pom.xml" create mode 100644 "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" create mode 100644 "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" create mode 100644 "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" create mode 100644 "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" create mode 100644 "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" create mode 100644 "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" create mode 100644 03concurrency/README2.md create mode 100644 03concurrency/README3.md create mode 100644 07rpc/rpc/.gitignore create mode 100644 07rpc/rpc/.mvn/wrapper/maven-wrapper.jar create mode 100644 07rpc/rpc/.mvn/wrapper/maven-wrapper.properties create mode 100644 07rpc/rpc/README.md create mode 100644 07rpc/rpc/mvnw create mode 100644 07rpc/rpc/mvnw.cmd create mode 100644 07rpc/rpc/pom.xml create mode 100644 07rpc/rpc/src/main/java/top/jrl/lean/rpc/RpcApplication.java create mode 100644 07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/Reflec.java create mode 100644 07rpc/rpc/src/main/resources/application.properties create mode 100644 07rpc/rpc/src/test/java/top/jrl/lean/rpc/RpcApplicationTests.java create mode 100644 07rpc/rpc01/README.md create mode 100644 07rpc/rpc01/rpcfx-core/README.md create mode 100644 07rpc/rpc01/rpcfx-demo-provider/README.md create mode 100644 07rpc/rpc02/dubbo-demo-provider/README.md 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/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/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 0000000000000000000000000000000000000000..c1dd12f17644411d6e840bd5a10c6ecda0175f18 GIT binary patch literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| literal 0 HcmV?d00001 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..6d76516a --- /dev/null +++ b/07rpc/rpc/README.md @@ -0,0 +1 @@ +# 学习RPC时,Joly创建的练习模块 \ 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/syntac/Reflec.java b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/Reflec.java new file mode 100644 index 00000000..6b2a23f6 --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/Reflec.java @@ -0,0 +1,10 @@ +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) { + } +} 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..8f0076a5 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 @@ -27,19 +27,20 @@ public static void main(String[] args) { // UserService service = new xxx(); // service.findById - + // 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())); + + // + UserService userService2 = Rpcfx.createFromRegistry(UserService.class, "localhost:2181", new TagRouter(), new RandomLoadBalancer(), new CuicuiFilter()); -// SpringApplication.run(RpcfxClientApplication.class, args); + // 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..e27b3487 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,7 +2,11 @@ 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 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/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 From 22be025fc467a2b76469bb8ca2f755320f153b65 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Thu, 23 Jun 2022 22:51:41 +0800 Subject: [PATCH 39/64] =?UTF-8?q?=E8=87=AA=E5=B7=B1=E5=8A=A8=E6=89=8B?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0RPC=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/top/jrl/lean/rpc/syntac/ClassA.java | 8 ++++++++ .../main/java/top/jrl/lean/rpc/syntac/InterfaceA.java | 8 ++++++++ .../src/main/java/top/jrl/lean/rpc/syntac/Reflec.java | 3 ++- .../rpcfx/demo/consumer/RpcfxClientApplication.java | 8 +++++--- .../kimmking/rpcfx/demo/provider/OrderServiceImpl.java | 2 +- .../rpcfx/demo/provider/RpcfxServerApplication.java | 9 +++++++-- 6 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA.java create mode 100644 07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/InterfaceA.java 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..f415b44a --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA.java @@ -0,0 +1,8 @@ +package top.jrl.lean.rpc.syntac; + +/** + * @author jrl + * @date Create in 22:42 2022/6/23 + */ +public class ClassA implements InterfaceA { +} 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..a1d30252 --- /dev/null +++ b/07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/InterfaceA.java @@ -0,0 +1,8 @@ +package top.jrl.lean.rpc.syntac; + +/** + * @author jrl + * @date Create in 22:40 2022/6/23 + */ +public interface InterfaceA { +} 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 index 6b2a23f6..70f11b53 100644 --- 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 @@ -5,6 +5,7 @@ * @date Create in 12:40 2022/6/14 */ public class Reflec { - public static void main(String[] args) { + public static void main(String[] args) throws IllegalAccessException, InstantiationException { + System.out.println(); } } 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 8f0076a5..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 @@ -27,7 +27,9 @@ public static void main(String[] args) { // UserService service = new xxx(); // service.findById - // stub + + /*这里演示了两种生成stub的方式*/ + // 生成stub UserService userService = Rpcfx.create(UserService.class, "http://localhost:8080/"); // 调用服务(由代理去做实际的远程调用) User user = userService.findById(1); @@ -37,8 +39,8 @@ public static void main(String[] args) { 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()); + // 从注册中心选个服务,来生成stub + // UserService userService2 = Rpcfx.createFromRegistry(UserService.class, "localhost:2181", new TagRouter(), new RandomLoadBalancer(), new CuicuiFilter()); // SpringApplication.run(RpcfxClientApplication.class, args); } 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 e27b3487..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 @@ -11,6 +11,6 @@ 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); } From ee3793dbd580e42cfaf1d4d49af9879135b3bdbf Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Fri, 24 Jun 2022 16:57:59 +0800 Subject: [PATCH 40/64] ServiceLoader --- 07rpc/rpc/README.md | 5 ++++- .../java/top/jrl/lean/rpc/syntac/ClassA.java | 5 +++++ .../java/top/jrl/lean/rpc/syntac/ClassA2.java | 13 +++++++++++++ .../java/top/jrl/lean/rpc/syntac/InterfaceA.java | 1 + .../top/jrl/lean/rpc/syntac/ServiceLoader1.java | 16 ++++++++++++++++ .../services/top.jrl.lean.rpc.syntac.InterfaceA | 2 ++ 07rpc/rpc02/README2.md | 0 7 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ClassA2.java create mode 100644 07rpc/rpc/src/main/java/top/jrl/lean/rpc/syntac/ServiceLoader1.java create mode 100644 07rpc/rpc/src/main/resources/META-INF/services/top.jrl.lean.rpc.syntac.InterfaceA create mode 100644 07rpc/rpc02/README2.md diff --git a/07rpc/rpc/README.md b/07rpc/rpc/README.md index 6d76516a..bc4466c6 100644 --- a/07rpc/rpc/README.md +++ b/07rpc/rpc/README.md @@ -1 +1,4 @@ -# 学习RPC时,Joly创建的练习模块 \ No newline at end of file +# 学习RPC时,Joly创建的练习模块 + +# 内容 +1. InterfaceA、ClassA、ClassA2、ServiceLoader1、META-INF用于联系ServiceLoader的使用,ServiceLoader是JDK对SPI的实现 \ No newline at end of file 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 index f415b44a..4128de3d 100644 --- 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 @@ -5,4 +5,9 @@ * @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 index a1d30252..21d71a20 100644 --- 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 @@ -5,4 +5,5 @@ * @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/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/rpc02/README2.md b/07rpc/rpc02/README2.md new file mode 100644 index 00000000..e69de29b From 19cdb297445599ef979e94415ee2df95acc9083f Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Fri, 15 Jul 2022 10:52:28 +0800 Subject: [PATCH 41/64] . --- 07rpc/dubbo/.gitignore | 33 ++ 07rpc/dubbo/.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 58727 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + 07rpc/dubbo/README.md | 2 + 07rpc/dubbo/mvnw | 316 ++++++++++++++++++ 07rpc/dubbo/mvnw.cmd | 188 +++++++++++ 07rpc/dubbo/pom.xml | 46 +++ .../top/jrl/learm/dubbo/DubboApplication.java | 13 + .../top/jrl/learm/dubbo/basic/Generic.java | 17 + .../src/main/resources/application.properties | 1 + .../learm/dubbo/DubboApplicationTests.java | 13 + .../top/jrl/lean/rpc/generic/Generic1.java | 11 + 08cache/README2.md | 0 08cache/cache/README.md | 8 + 08cache/cache/pom.xml | 5 + .../io/kimmking/cache/CacheApplication.java | 2 +- .../cache/src/main/resources/application.yml | 9 +- 08cache/redis/README.md | 2 + 08cache/redis/pom.xml | 4 +- .../io/kimmking/cache/RedisApplication.java | 4 +- 20 files changed, 668 insertions(+), 8 deletions(-) create mode 100644 07rpc/dubbo/.gitignore create mode 100644 07rpc/dubbo/.mvn/wrapper/maven-wrapper.jar create mode 100644 07rpc/dubbo/.mvn/wrapper/maven-wrapper.properties create mode 100644 07rpc/dubbo/README.md create mode 100644 07rpc/dubbo/mvnw create mode 100644 07rpc/dubbo/mvnw.cmd create mode 100644 07rpc/dubbo/pom.xml create mode 100644 07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/DubboApplication.java create mode 100644 07rpc/dubbo/src/main/java/top/jrl/learm/dubbo/basic/Generic.java create mode 100644 07rpc/dubbo/src/main/resources/application.properties create mode 100644 07rpc/dubbo/src/test/java/top/jrl/learm/dubbo/DubboApplicationTests.java create mode 100644 07rpc/rpc/src/main/java/top/jrl/lean/rpc/generic/Generic1.java create mode 100644 08cache/README2.md create mode 100644 08cache/cache/README.md create mode 100644 08cache/redis/README.md 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 0000000000000000000000000000000000000000..c1dd12f17644411d6e840bd5a10c6ecda0175f18 GIT binary patch literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` 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 YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| literal 0 HcmV?d00001 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/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/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..f7072358 --- /dev/null +++ b/08cache/cache/README.md @@ -0,0 +1,8 @@ +# 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 +# 项目内容 +1. mybatis 结合 ehcache 实现数据缓存功能 +2. Spring 利用 ehcache 实现数据缓存功能 + + \ No newline at end of file diff --git a/08cache/cache/pom.xml b/08cache/cache/pom.xml index 88c9a37e..4aa84abf 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/resources/application.yml b/08cache/cache/src/main/resources/application.yml index 1d76edf5..f7727c6b 100644 --- a/08cache/cache/src/main/resources/application.yml +++ b/08cache/cache/src/main/resources/application.yml @@ -3,14 +3,15 @@ server: spring: datasource: - username: root - password: - url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC + username: idea_user + password: 123456 + url: jdbc:mysql://47.115.48.27:3306/cache?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC driver-class-name: com.mysql.jdbc.Driver cache: type: redis redis: - host: localhost + host: 47.115.48.27 + password: 123456 lettuce: pool: max-active: 16 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")); From 8d5b5c560050e16d3cf12b2cad3e02aa66bd8b5f Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Fri, 15 Jul 2022 19:04:54 +0800 Subject: [PATCH 42/64] Spring Cache && Mybatis && ehcache/Redis --- 08cache/cache/README.md | 11 +++++++---- 08cache/cache/pom.xml | 2 +- .../java/io/kimmking/cache/CacheConfig.java | 11 +++++++++-- .../cache/controller/UserController.java | 5 +++-- .../io/kimmking/cache/service/UserService.java | 3 ++- .../cache/src/main/resources/application.yml | 18 ++++++++++-------- .../src/main/resources/mapper/UserMapper.xml | 1 + 7 files changed, 33 insertions(+), 18 deletions(-) diff --git a/08cache/cache/README.md b/08cache/cache/README.md index f7072358..acbb7bbd 100644 --- a/08cache/cache/README.md +++ b/08cache/cache/README.md @@ -1,8 +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的数据存在了Redis中,哈哈哈哈哈 +* 数据存在了JVM中 # 项目内容 -1. mybatis 结合 ehcache 实现数据缓存功能 -2. Spring 利用 ehcache 实现数据缓存功能 - +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 4aa84abf..ea45a15f 100644 --- a/08cache/cache/pom.xml +++ b/08cache/cache/pom.xml @@ -46,7 +46,7 @@ org.projectlombok lombok - + org.springframework.boot spring-boot-starter-cache 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 f7727c6b..5e2ab33a 100644 --- a/08cache/cache/src/main/resources/application.yml +++ b/08cache/cache/src/main/resources/application.yml @@ -3,23 +3,25 @@ server: spring: datasource: - username: idea_user - password: 123456 - url: jdbc:mysql://47.115.48.27:3306/cache?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: 47.115.48.27 - password: 123456 + 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 @@ + From f9e3327f26a17e46cbd024e1fd173fa56afab70c Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Mon, 18 Jul 2022 16:57:18 +0800 Subject: [PATCH 43/64] =?UTF-8?q?redis=20=E4=B8=BB=E4=BB=8E=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E3=80=81Redission?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08cache/ha/conf/redis6379.conf | 6 +++--- 08cache/ha/conf/redis6380.conf | 3 ++- .../java/io/kimmking/cache/redission/RedissionDemo.java | 3 +-- .../java/io/kimmking/cache/redission/RedissionDemo1.java | 4 +++- 4 files changed, 9 insertions(+), 7 deletions(-) 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/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{ From 49cdfe49ee872f1c616550576cc66b43b9559fc0 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Thu, 28 Jul 2022 11:07:22 +0800 Subject: [PATCH 44/64] =?UTF-8?q?rabbitMQ=20=E9=85=8D=E5=90=88=20spring=20?= =?UTF-8?q?=E7=AE=80=E5=8D=95=E5=AE=9E=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 09mq/rabbit/README.md | 2 + 09mq/rabbit/pom.xml | 41 ++++++++++--------- .../kimmking/mq/rabbit/MessageProducer.java | 12 ++++-- .../kimmking/mq/rabbit/MessageReceiverA.java | 6 ++- .../kimmking/mq/rabbit/MessageReceiverB.java | 8 +++- .../io/kimmking/mq/rabbit/RabbitConfig.java | 8 +++- .../src/main/resources/application.yaml | 5 +-- 7 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 09mq/rabbit/README.md 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 From 61ba78be64764eb4f9002894e0a775c3bc4ac659 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Thu, 28 Jul 2022 11:07:36 +0800 Subject: [PATCH 45/64] . --- 09mq/activemq-demo/pom.xml | 2 +- 09mq/activemq-demo/src/README.md | 3 + .../mq/activemq/ActivemqApplication.java | 63 ++++++++++++++++--- 09mq/kafka-demo/README2.md | 3 + 09mq/kafka-demo/pom.xml | 20 ++++-- .../io/kimmking/javacourse/kafka/Order.java | 6 ++ .../kafka/kimmking/ConsumerImpl.java | 5 +- .../javacourse/kafka/kimmking/Producer.java | 2 +- .../kafka/kimmking/ProducerImpl.java | 18 ++++++ .../kafkademo/KafkaDemoApplication.java | 3 + 10 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 09mq/activemq-demo/src/README.md create mode 100644 09mq/kafka-demo/README2.md 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/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(); } } From 331e8be4b78b5d8c30420dc1affa32664c4b9906 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 31 Jul 2022 14:28:17 +0800 Subject: [PATCH 46/64] . --- 09mq/pulsar/pom.xml | 19 +++++----- .../java/io/kimmking/mq/pulsar/Config.java | 7 +++- .../io/kimmking/mq/pulsar/ConsumerDemo.java | 8 ++--- .../io/kimmking/mq/pulsar/ProducerDemo.java | 8 ++--- .../src/main/resources/application.properties | 1 - 09mq/rocket/pom.xml | 2 +- .../java/io/kimmking/mq/rocket/Order.java | 6 +++- .../kimmking/mq/rocket/OrderConsumerDemo.java | 4 +-- .../kimmking/mq/rocket/RocketApplication.java | 36 ++++++++++--------- .../mq/rocket/StringConsumerDemo.java | 12 ++++--- .../src/main/resources/application.properties | 3 +- 11 files changed, 62 insertions(+), 44 deletions(-) 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/rocket/pom.xml b/09mq/rocket/pom.xml index d2931a7e..0e0d22fd 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..6d816ff6 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 @@ -7,8 +7,8 @@ @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..c7eaee81 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,7 @@ import java.math.BigDecimal; import java.util.List; +// CommandLineRunner 和 ApplicationRunner 的作用是一样的,用来运行 run () 方法 @SpringBootApplication public class RocketApplication implements CommandLineRunner { @@ -21,6 +22,7 @@ public static void main(String[] args) { SpringApplication.run(RocketApplication.class, args); } + /*Spring Boot 直接给配好了 Template*/ @Resource private RocketMQTemplate rocketMQTemplate; @@ -28,31 +30,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..9dccb237 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 @@ -3,11 +3,15 @@ import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; 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 From 404adc279d1cb49998cd46b148be7079e8092f02 Mon Sep 17 00:00:00 2001 From: JolyPhone <18990341730@163.com> Date: Sun, 31 Jul 2022 22:28:26 +0800 Subject: [PATCH 47/64] =?UTF-8?q?=E6=89=8B=E5=8A=A8=E5=AE=9E=E7=8E=B0MQ?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 09mq/kmq-core/README.md | 3 ++- .../src/main/java/io/kimmking/kmq/core/Kmq.java | 7 ++++++- .../src/main/java/io/kimmking/kmq/core/KmqBroker.java | 10 ++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) 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) { From a6c0effd05c333d2eee3e6c24faeb1faf15f26fd Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Mon, 5 Dec 2022 18:49:46 +0800 Subject: [PATCH 48/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/io/kimmking/spring02/SpringDemo01.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 33f7b663..4acbe95b 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java @@ -54,7 +54,7 @@ public static void main(String[] args) { school1.ding(); - class1.dong(); + class1.dong(); System.out.println(" context.getBeanDefinitionNames() ===>> " + String.join(",", context.getBeanDefinitionNames())); From 501820bcbdad9c49b9e6e5c5621482d6766b3462 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Sat, 17 Dec 2022 15:31:15 +0800 Subject: [PATCH 49/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml" | 0 .../java/java0/conc0301/DaemonThread.java" | 0 .../main/java/java0/conc0301/Runner1.java" | 0 .../main/java/java0/conc0301/Runner2.java" | 0 .../main/java/java0/conc0301/RunnerMain.java" | 0 .../main/java/java0/conc0301/ThreadA.java" | 0 .../main/java/java0/conc0301/ThreadB.java" | 0 .../main/java/java0/conc0301/ThreadC.java" | 0 .../java/java0/conc0301/ThreadCount.java" | 0 .../main/java/java0/conc0301/ThreadMain.java" | 0 .../java/java0/conc0301/ThreadMain2.java" | 0 .../java0/conc0301/jrl/HighConcurrency.java" | 0 .../java/java0/conc0301/jrl/ThreadJoin.java" | 0 .../main/java/java0/conc0301/op/Join.java" | 0 .../java0/conc0301/op/WaitAndNotify.java" | 0 .../java/java0/conc0301/sync/Counter.java" | 0 .../main/java/java0/conc0301/sync/Cref.java" | 0 .../java/java0/conc0301/sync/TestSetGet.java" | 0 .../java/java0/conc0301/sync/Thread1.java" | 0 .../java/java0/conc0301/sync/Thread2.java" | 0 .../java/java0/conc0301/sync/Thread3.java" | 0 .../java0/conc0302/atomic/AtomicCount.java" | 0 .../java0/conc0302/atomic/AtomicMain.java" | 0 .../java/java0/conc0302/atomic/Count.java" | 0 .../java/java0/conc0302/atomic/LongDemo.java" | 0 .../java0/conc0302/atomic/SyncCount.java" | 0 .../java0/conc0302/lock/ConditionDemo.java" | 0 .../main/java/java0/conc0302/lock/Count.java" | 0 .../java/java0/conc0302/lock/Count2.java" | 0 .../java/java0/conc0302/lock/Count3.java" | 0 .../java/java0/conc0302/lock/LockMain.java" | 0 .../java0/conc0302/lock/LockSupportDemo.java" | 0 .../java0/conc0302/lock/ObjectCache.java" | 0 .../conc0302/lock/ReentrantLockDemo.java" | 0 .../lock/ReentrantReadWriteLockDemo.java" | 0 .../lock/ReentrantReadWriteLockDemo2.java" | 0 .../java/java0/conc0302/lock/TestFair.java" | 0 .../java/java0/conc0302/lock/ThreadA.java" | 0 .../java/java0/conc0302/lock/ThreadB.java" | 0 .../conc0302/lock/jrl/LockProperties.java" | 0 .../conc0302/threadpool/ExceptionDemo.java" | 0 .../threadpool/ExecutorServiceDemo.java" | 0 .../threadpool/NewCachedThreadPoolDemo.java" | 0 .../threadpool/NewFixedThreadPoolDemo.java" | 0 .../NewScheduledThreadExecutorDemo.java" | 0 .../NewSingleThreadExecutorDemo.java" | 0 .../main/java/java0/conc0303/Homework03.java" | 0 .../collection/ConcurrentHashMapDemo.java" | 0 .../collection/CopyOnWriteArrayListDemo.java" | 0 .../CopyOnWriteArrayListDemo1.java" | 0 .../CopyOnWriteArrayListDemo2.java" | 0 .../collection/LinkedHashMapDemo.java" | 0 .../conc0303/collection/SyncListDemo.java" | 0 .../conc0303/collection/TreeMapDemo.java" | 0 .../future/CompletableFutureDemo.java" | 0 .../java0/conc0303/future/FutureDemo1.java" | 0 .../java0/conc0303/future/FutureTask1.java" | 0 .../conc0303/stream/StreamParallelDemo.java" | 0 .../threadlocal/ThreadLocalDemo.java" | 0 .../conc0303/tool/CountDownLatchDemo.java" | 0 .../conc0303/tool/CountDownLatchDemo2.java" | 0 .../conc0303/tool/CyclicBarrierDemo.java" | 0 .../conc0303/tool/CyclicBarrierDemo2.java" | 0 .../java0/conc0303/tool/SemaphoreDemo.java" | 0 .../java0/conc0303/tool/SemaphoreDemo2.java" | 0 .../java0/conc0303/tool/SemaphoreDemo3.java" | 0 08cache/cache/pom.xml | 4 +- .../.mvn/wrapper/MavenWrapperDownloader.java | 118 ------- 09mq/rocket/.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - 09mq/rocket/README.md | 6 + 09mq/rocket/mvnw | 310 ------------------ 09mq/rocket/mvnw.cmd | 182 ---------- 09mq/rocket/pom.xml | 2 +- .../kimmking/mq/rocket/OrderConsumerDemo.java | 7 +- .../kimmking/mq/rocket/RocketApplication.java | 28 +- .../mq/rocket/StringConsumerDemo.java | 6 +- 77 files changed, 35 insertions(+), 630 deletions(-) rename 03concurrency/0301/pom.xml => "03concurrency/0301\345\244\232\347\272\277\347\250\213/pom.xml" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/DaemonThread.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/Runner1.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/Runner1.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/Runner2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/Runner2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/RunnerMain.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/RunnerMain.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/ThreadA.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadA.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/ThreadB.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadB.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/ThreadC.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadC.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/ThreadCount.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadCount.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/ThreadMain.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadMain.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/ThreadMain2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/ThreadMain2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/jrl/HighConcurrency.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/HighConcurrency.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/jrl/ThreadJoin.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/ThreadJoin.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/op/Join.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/Join.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/WaitAndNotify.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Counter.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/sync/Cref.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Cref.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/sync/TestSetGet.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/TestSetGet.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/sync/Thread1.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread1.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0301/sync/Thread3.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/sync/Thread3.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicCount.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/AtomicMain.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/Count.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/LongDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/atomic/SyncCount.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/Count.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/Count2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/Count3.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/LockMain.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockMain.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockSupportDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/ObjectCache.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ObjectCache.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/TestFair.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadA.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadA.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadB.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ThreadB.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/lock/jrl/LockProperties.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/jrl/LockProperties.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExecutorServiceDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewCachedThreadPoolDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewFixedThreadPoolDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewScheduledThreadExecutorDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/Homework03.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/Homework03.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/ConcurrentHashMapDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/collection/LinkedHashMapDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/LinkedHashMapDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/collection/SyncListDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/SyncListDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/collection/TreeMapDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/TreeMapDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/future/CompletableFutureDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/CompletableFutureDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureDemo1.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/future/FutureTask1.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureTask1.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/stream/StreamParallelDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/stream/StreamParallelDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CyclicBarrierDemo2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java" (100%) rename 03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo3.java" (100%) delete mode 100644 09mq/rocket/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 09mq/rocket/.mvn/wrapper/maven-wrapper.jar delete mode 100644 09mq/rocket/.mvn/wrapper/maven-wrapper.properties create mode 100644 09mq/rocket/README.md delete mode 100755 09mq/rocket/mvnw delete mode 100644 09mq/rocket/mvnw.cmd 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/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/DaemonThread.java" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/jrl/HighConcurrency.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/HighConcurrency.java" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/jrl/ThreadJoin.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/ThreadJoin.java" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0301/op/Join.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/op/Join.java" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo.java" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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/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 100% 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" 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 100% 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" 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 100% 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" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/TestFair.java" 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 100% 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" 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 100% 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" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0302/lock/jrl/LockProperties.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/jrl/LockProperties.java" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" 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 100% 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" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/NewSingleThreadExecutorDemo.java" 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 100% 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" 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 100% 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" 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/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/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 100% 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" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/FutureDemo1.java" 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/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 100% 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" 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 100% 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" diff --git a/03concurrency/0301/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" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java" 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 100% 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" 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 100% 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" 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 100% 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" diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo.java" diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java" similarity index 100% rename from 03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java" 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 100% 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" diff --git a/08cache/cache/pom.xml b/08cache/cache/pom.xml index ea45a15f..6e4bde0f 100644 --- a/08cache/cache/pom.xml +++ b/08cache/cache/pom.xml @@ -31,7 +31,7 @@ org.springframework.boot spring-boot-starter-web - + org.mybatis.spring.boot mybatis-spring-boot-starter @@ -70,7 +70,7 @@ ehcache 2.8.3 - + org.mybatis mybatis-ehcache diff --git a/09mq/rocket/.mvn/wrapper/MavenWrapperDownloader.java b/09mq/rocket/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index a45eb6ba..00000000 --- a/09mq/rocket/.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/09mq/rocket/.mvn/wrapper/maven-wrapper.jar b/09mq/rocket/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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 EfAhh=DF6Tf diff --git a/09mq/rocket/.mvn/wrapper/maven-wrapper.properties b/09mq/rocket/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 642d572c..00000000 --- a/09mq/rocket/.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/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/mvnw b/09mq/rocket/mvnw deleted file mode 100755 index a16b5431..00000000 --- a/09mq/rocket/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/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 /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="`which 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/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.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" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$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 \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/09mq/rocket/mvnw.cmd b/09mq/rocket/mvnw.cmd deleted file mode 100644 index c8d43372..00000000 --- a/09mq/rocket/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@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 "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\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/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "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%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.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 "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\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% - -exit /B %ERROR_CODE% diff --git a/09mq/rocket/pom.xml b/09mq/rocket/pom.xml index 0e0d22fd..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/OrderConsumerDemo.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java index 6d816ff6..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 { // 这里的Order是确认了泛型,这个泛型要和onMessage()的参数类型一样 - // 消费完了以后,返回个String 【这里实现的是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 c7eaee81..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,7 +14,13 @@ import java.math.BigDecimal; import java.util.List; -// CommandLineRunner 和 ApplicationRunner 的作用是一样的,用来运行 run () 方法 +/** + * 生产者 + * + * @author jrl + * @date 2022/12/9 + */ +// CommandLineRunner 和 ApplicationRunner 的作用是一样的,可以运行 run () 方法 @SpringBootApplication public class RocketApplication implements CommandLineRunner { @@ -45,18 +51,18 @@ public void run(String... args) throws Exception { 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); - } + 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); - } + @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 9dccb237..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 @@ -3,15 +3,17 @@ import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; 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") // 制定了消费者组和要接受的topic -public class StringConsumerDemo implements RocketMQListener { // 这里的 String 是确认了泛型,这个泛型要和onMessage()的参数类型一样 - // 没有返回值,所以这个消息是消费掉了就结束了 【这里实现的是RocketMQListener】 +public class StringConsumerDemo implements RocketMQListener { // 这里的 String 是确认了泛型,这个泛型要和 onMessage()的参数类型一样 + // 没有返回值,所以这个消息是消费掉了就结束了 【这里实现的是 RocketMQListener】 @Override public void onMessage(String message) { // one way System.out.println(this.getClass().getName() + " -> " + message); From 4d7c93e89ee712574db8053481ec9784a089c6fe Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Mon, 19 Dec 2022 17:37:33 +0800 Subject: [PATCH 50/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/java0/conc0301/ThreadA.java" | 6 ++++++ .../src/main/java/java0/conc0301/ThreadB.java" | 6 ++++++ .../src/main/java/java0/conc0301/ThreadC.java" | 7 ++++++- .../main/java/java0/conc0301/ThreadMain.java" | 16 ++++++++++++---- .../src/main/java/java0/conc0301/op/Join.java" | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 50e548f6..726fbe60 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index fe7dda58..ba7d2f4c 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index cc01e3b8..015d2645 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 5478e112..62567240 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\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" index 41c7ea7c..b7af9bac 100644 --- "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" @@ -2,7 +2,7 @@ public class Join { - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { Object oo = new Object(); MyThread thread1 = new MyThread("thread1 -- "); From b33f2f8de14f2e85bad48c2f4db21e520be44fe6 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Thu, 22 Dec 2022 16:01:55 +0800 Subject: [PATCH 51/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java0/conc0301/jrl/TwiceStartMethod.java" | 17 + .../conc0302/threadpool/ExceptionDemo.java" | 1 + .../jolyne/ThreadPoolExecutor0.java" | 299 ++++++++++++++++++ .../threadlocal/ThreadLocalDemo.java" | 26 +- .../threadlocal/jolyne/ThreadLocal0.java" | 28 ++ 5 files changed, 360 insertions(+), 11 deletions(-) create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/TwiceStartMethod.java" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/jolyne/ThreadPoolExecutor0.java" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/threadlocal/jolyne/ThreadLocal0.java" 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/conc0302/threadpool/ExceptionDemo.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/threadpool/ExceptionDemo.java" index c014872d..3cf1f01f 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" @@ -10,6 +10,7 @@ * 2.Future能够拿到子线程的异常,那么具体都有什么内容呢?--->可以直接catch拿到子线程抛出来的异常 * 3.子线程异常了以后,在主线程中shutdown子线程,会抛异常吗?--->不会,就正常执行。 * 甚至子线程当前还有任务正在执行的话,不会强行关闭,而是等执行完了当前任务,再关闭子线程,也就是所谓的优雅停机。 + * @author Joly */ public class ExceptionDemo { 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\345\244\232\347\272\277\347\250\213/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" index bbfe35e0..45c32a55 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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,51 @@ package java0.conc0303.threadlocal; public class ThreadLocalDemo { - + // кţ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 ļֵ + //--->Ϊ˱ڴһ˺ܶ߳أ԰ɡ 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..8eea9eb5 --- /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,28 @@ +package java0.conc0303.threadlocal.jolyne; + +/** + * @author jrl + * @date Create in 14:43 2022/12/20 + */ +public class ThreadLocal0 { + static ThreadLocal tls = 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()); + } + } +} From 9a8cd4e7e66165ec349c44a9943e1f43014d97f4 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Fri, 23 Dec 2022 18:06:37 +0800 Subject: [PATCH 52/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../threadpool/NewCachedThreadPoolDemo.java" | 6 +++++ .../threadpool/NewFixedThreadPoolDemo.java" | 11 ++++++++- .../NewScheduledThreadExecutorDemo.java" | 12 ++++++++-- .../NewSingleThreadExecutorDemo.java" | 23 +++++++++++++++--- .../conc0303/future/jolyne/Future0.java" | 24 +++++++++++++++++++ 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/future/jolyne/Future0.java" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 2137af53..0073a545 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 8d4052b2..8312bf58 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 3a618f0c..fdc139f2 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index dee7b07c..8a487fbf 100644 --- "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" @@ -1,26 +1,43 @@ 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) { + public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newSingleThreadExecutor(); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 3; i++) { final int no = i; - executorService.execute(() -> { + 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/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); + } +} From 77a32e70ad02ea80eaf83de96b2baaa1c9b144f2 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Sun, 25 Dec 2022 22:34:43 +0800 Subject: [PATCH 53/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/java0/conc0302/lock/Count3.java" | 28 +++++++++++++++++++ .../java/java0/conc0302/lock/LockMain.java" | 5 ++++ .../main/java/java0/conc0302/lock/README.md" | 2 ++ .../java/java0/conc0302/lock/ThreadA.java" | 5 ++++ .../java/java0/conc0302/lock/ThreadB.java" | 5 ++++ 5 files changed, 45 insertions(+) create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README.md" diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index f99eaa3e..59ac8172 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index e8f203e2..9e00ab43 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README.md" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README.md" new file mode 100644 index 00000000..09caf3e3 --- /dev/null +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README.md" @@ -0,0 +1,2 @@ +# ˵ +1. \ 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/ThreadA.java" "b/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\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index ee6942f1..6f67ccf9 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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(); } From 755fa346737642f2ce7044368f2a097f22fd7ca4 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Sun, 25 Dec 2022 22:37:11 +0800 Subject: [PATCH 54/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/java0/conc0302/lock/README" | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README.md" => "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README" (100%) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README.md" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README" similarity index 100% rename from "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README.md" rename to "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/README" From c2c699f5c00c6635eec79aaa4bef836d23329013 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Mon, 26 Dec 2022 15:18:45 +0800 Subject: [PATCH 55/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java0/conc0302/lock/ConditionDemo.java" | 59 ++++++++++++++++--- .../java0/conc0302/lock/ConditionDemo0.java" | 18 ++++++ .../main/java/java0/conc0302/lock/Count.java" | 19 ++++++ .../java/java0/conc0302/lock/Count2.java" | 10 ++++ .../java0/conc0302/lock/LockSupportDemo.java" | 29 +++++++-- .../src/main/java/java0/conc0302/lock/README" | 6 +- .../conc0302/lock/ReentrantLockDemo.java" | 7 +++ .../lock/ReentrantReadWriteLockDemo.java" | 5 ++ .../lock/ReentrantReadWriteLockDemo2.java" | 10 +++- .../java/java0/conc0302/lock/TestFair.java" | 44 +++++++++----- 10 files changed, 175 insertions(+), 32 deletions(-) create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/ConditionDemo0.java" 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" index 33ad0bab..9381737f 100644 --- "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" @@ -4,37 +4,78 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -class ConditionDemo { +/** + * ReentrantLock + * Condition + * + * @author Joly + */ +public class ConditionDemo { + // TODO_Joly:为什么用的是可重入锁? + /** + * @author jrl + * @date 2022/12/26 + */ final Lock lock = new ReentrantLock(); - final Condition notFull = lock.newCondition(); + + 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 { // 当count等于数组的大小时,当前线程等待,直到notFull通知,再进行生产 - while (count == items.length) + //也就是说要等到满足了 notFull 这个 Condition 的时候,才开始继续执行 + while (count == items.length) { + //相当于 wait notFull.await(); + } + //朝数组放置一个元素 items[putptr] = x; - if (++putptr == items.length) putptr = 0; + 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) + while (count == 0) { notEmpty.await(); + } Object x = items[takeptr]; - if (++takeptr == items.length) takeptr = 0; + if (++takeptr == items.length) { + takeptr = 0; + } --count; notFull.signal(); return x; 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..4aa5d31a --- /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,18 @@ +package java0.conc0302.lock; + +/** + * @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(); + conditionDemo.put("a"); + Object take = conditionDemo.take(); + Object tak2e = conditionDemo.take(); + conditionDemo.take(); + conditionDemo.take(); + System.out.println(take); + System.out.println(tak2e); + } +} diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 09197048..42926798 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 8cd691d1..f26434fd 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 18f598f1..dbb78d0f 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\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" index 09caf3e3..1327467d 100644 --- "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" @@ -1,2 +1,6 @@ # ˵ -1. \ No newline at end of file +1. + LockMain.java + Count3.java + ThreadA.java + ThreadB.java \ 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/ReentrantLockDemo.java" "b/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\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index e36e3375..ed4cc639 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 82b4001b..b38e3097 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 1dc47538..922cd093 100644 --- "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" @@ -3,36 +3,52 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; +/** + * 测试ReentrantLock使用公平排序策略与否的性能差异 + * @author Joly + */ public class TestFair { - public static volatile int race=0; + //互斥变量 + public static volatile int race = 0; + + //25875 true + //80 false 300倍 public static ReentrantLock lock = new ReentrantLock(true); // 改成false会好100倍 - public static void increase(){ + + 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){ + + 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;i 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++){ + public void run() { + for (int i = 0; i < 100000; i++) { increase(); } } }); threads[i].start(); - }//等待所有累加线程都结束 - while(Thread.activeCount()>count) { - Thread.yield(); } - System.out.println(lock.getClass().getName() + " ts = "+ (System.currentTimeMillis()-now)); + //等待所有累加线程都结束。 噢!这个方式牛逼! + while (Thread.activeCount() > count) { + Thread.yield();// 哈哈,让一让,我再让一让 + } + System.out.println(count); + System.out.println(lock.getClass().getName() + " ts = " + (System.currentTimeMillis() - now)); } } From 1ac0df68f159b4b4aa76d7e1c246f5e6e1dc03c9 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Tue, 27 Dec 2022 17:38:37 +0800 Subject: [PATCH 56/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/java0/conc0302/atomic/AtomicCount.java" | 4 ++++ .../main/java/java0/conc0302/atomic/AtomicMain.java" | 9 +++++++-- .../src/main/java/java0/conc0302/atomic/Count.java" | 3 +++ .../main/java/java0/conc0302/atomic/LongDemo.java" | 7 ++++++- .../main/java/java0/conc0302/atomic/SyncCount.java" | 12 +++++++++--- .../java/java0/conc0302/lock/LockSupportDemo.java" | 2 +- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index cece1ec3..a06e62ab 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 297eb343..14bb3fec 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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,10 @@ package java0.conc0302.atomic; +/** + * ʾLock̲߳ȫ + * @author Joly + */ public class AtomicMain { public static void main(String[] args) { @@ -10,7 +14,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 +25,8 @@ public void run() { } catch (InterruptedException e) { e.printStackTrace(); } - + // TODO_Joly://num=338247 õǹƽòƽĻǶԵ + // ȣҲΪʲôܲԣҲƽզӰ System.out.println("num=" + count.getNum()); } diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 02fd13d5..279c2ca9 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 6a7356c6..4d5865c0 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index b95c7cff..b000e703 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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/LockSupportDemo.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0302/lock/LockSupportDemo.java" index dbb78d0f..e452c345 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" @@ -9,7 +9,7 @@ * @author Joly */ public class LockSupportDemo { - //对象锁 + //类锁 public static Object u = new Object(); static ChangeObjectThread t1 = new ChangeObjectThread("t1"); From ece5c48a8664d611ac0af92d5b9f6384302efc83 Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Tue, 27 Dec 2022 17:39:56 +0800 Subject: [PATCH 57/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/java0/conc0302/atomic/AtomicMain.java" | 1 + 1 file changed, 1 insertion(+) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 14bb3fec..10033c48 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" @@ -2,6 +2,7 @@ package java0.conc0302.atomic; /** + * TODOQQQQQQ * ʾLock̲߳ȫ * @author Joly */ From f4da5d122648d652c20222e159e50ff6004c15be Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Thu, 29 Dec 2022 13:55:33 +0800 Subject: [PATCH 58/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java0/conc0303/tool/SemaphoreDemo.java" | 24 +++++-- .../java0/conc0303/tool/SemaphoreDemo2.java" | 68 +++++++++++-------- .../java0/conc0303/tool/SemaphoreDemo3.java" | 24 +++++-- 3 files changed, 78 insertions(+), 38 deletions(-) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo.java" index d9642c04..d968940a 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo.java" +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo.java" @@ -2,24 +2,34 @@ import java.util.concurrent.Semaphore; +/** + * Semaphore + * 同时允许指定线程数(permits)来访问和使用共享资源 + * + * @author jrl + * @date 2022/12/28 + */ public class SemaphoreDemo { - + public static void main(String[] args) { - int N = 8; //工人数 - Semaphore semaphore = new Semaphore(2); //机器数目 - for (int i = 0; i < N; i++) + //工人数 + int N = 8; + //机器数目 + Semaphore semaphore = new Semaphore(2); + for (int i = 0; i < N; i++) { new Worker(i, semaphore).start(); + } } - + static class Worker extends Thread { private int num; private Semaphore semaphore; - + public Worker(int num, Semaphore semaphore) { this.num = num; this.semaphore = semaphore; } - + @Override public void run() { try { diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java" "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java" index 2acb724a..96e84f6b 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java" +++ "b/03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java" @@ -4,33 +4,47 @@ import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; +/** + * Semaphore + * @author Joly + */ 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); + + 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 { + // 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\345\244\232\347\272\277\347\250\213/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" index 3a02dc78..631d9787 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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); @@ -63,13 +78,14 @@ static class Warehouse { 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 From 723c4409bc124c54909bf5c3b45069965bc3287f Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Thu, 29 Dec 2022 14:50:21 +0800 Subject: [PATCH 59/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/java0/conc0303/tool/SemaphoreDemo3.java" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 631d9787..a4b0ad96 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" @@ -76,7 +76,7 @@ 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]; From ca886d421bb50c48b7a1ba314c29c86caf9c8cfe Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Fri, 30 Dec 2022 14:12:54 +0800 Subject: [PATCH 60/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../future/CompletableFutureDemo.java" | 66 +++++++++++-------- .../java0/conc0303/future/FutureDemo1.java" | 24 +++++++ 2 files changed, 64 insertions(+), 26 deletions(-) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index c5d1e900..56dd2376 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 14a16383..9e16a8fe 100644 --- "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" @@ -3,16 +3,40 @@ 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(); From 1a5797a8c9a341dffa8562256d6924f44fb7785b Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Sun, 1 Jan 2023 17:48:17 +0800 Subject: [PATCH 61/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java0/conc0301/op/WaitAndNotify.java" | 29 ++++++++---- .../java0/conc0302/lock/ConditionDemo.java" | 4 +- .../java0/conc0302/lock/ConditionDemo0.java" | 30 +++++++++--- .../conc0303/tool/CountDownLatchDemo.java" | 44 +++++++++++++---- .../conc0303/tool/CountDownLatchDemo2.java" | 22 ++++++--- .../conc0303/tool/CyclicBarrierDemo.java" | 47 ++++++++++++++----- .../conc0303/tool/CyclicBarrierDemo2.java" | 38 +++++++++------ 7 files changed, 156 insertions(+), 58 deletions(-) diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 61660faf..3e17fb29 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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(); @@ -30,32 +33,40 @@ public static void main(String[] args) { t1.start(); t2.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(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); @@ -63,10 +74,10 @@ public synchronized void customer() throws InterruptedException { if (productCount <= 0) { System.out.println("货舱已无货...无法消费"); wait(); - }else { + } else { productCount--; } - + notifyAll(); } } 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" index 9381737f..6064a419 100644 --- "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" @@ -11,7 +11,6 @@ * @author Joly */ public class ConditionDemo { - // TODO_Joly:为什么用的是可重入锁? /** * @author jrl * @date 2022/12/26 @@ -38,12 +37,15 @@ 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) { 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" index 4aa5d31a..810b130c 100644 --- "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" @@ -1,5 +1,9 @@ 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 @@ -7,12 +11,24 @@ public class ConditionDemo0 { public static void main(String[] args) throws InterruptedException { ConditionDemo conditionDemo = new ConditionDemo(); - conditionDemo.put("a"); - Object take = conditionDemo.take(); - Object tak2e = conditionDemo.take(); - conditionDemo.take(); - conditionDemo.take(); - System.out.println(take); - System.out.println(tak2e); + 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\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" index b93731be..0f22cddc 100644 --- "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" @@ -2,30 +2,56 @@ 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<5;i++){ - new Thread(new readNum(i,countDownLatch)).start(); + 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("==>主线程执行结束。。。。"); } - - static class readNum implements Runnable{ + + /** + * 任务 + * + * @author jrl + * @date 2023/1/1 + */ + static class ReadNum implements Runnable { private int id; private CountDownLatch latch; - public readNum(int id,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(); + synchronized (this) { + System.out.println("id:" + id + "," + Thread.currentThread().getName()); + System.out.println("线程组任务" + id + "结束,其他任务继续"); latch.countDown(); } } diff --git "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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" index 62a1007a..377e720b 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 628d980d..b0291b46 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 33e88260..a7aaacb2 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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 Date: Mon, 16 Jan 2023 21:52:27 +0800 Subject: [PATCH 62/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../conc0301/jrl/share/GlobalVariable.java" | 20 +++++++++++++++++ .../conc0301/jrl/share/LocalVariable.java" | 18 +++++++++++++++ .../jrl/share/LocalVariableMain.java" | 22 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/GlobalVariable.java" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariable.java" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/share/LocalVariableMain.java" 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(); + } +} From 433d9f4953e22173af7868ce2d6054ff00c6b2ef Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Tue, 24 Jan 2023 14:56:29 +0800 Subject: [PATCH 63/64] =?UTF-8?q?=E5=86=85=E9=83=A8bean=20,=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=8D=95=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/kimmking/jrl/ioc0/Base1.java | 29 ++++++++++++++ .../java/io/kimmking/jrl/ioc0/bean0/Home.java | 33 ++++++++++++++++ .../io/kimmking/jrl/ioc0/bean0/Relative.java | 27 +++++++++++++ .../resources/applicationContext4jrlioc0.xml | 38 +++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/Base1.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Home.java create mode 100644 04fx/spring01/src/main/java/io/kimmking/jrl/ioc0/bean0/Relative.java create mode 100644 04fx/spring01/src/main/resources/applicationContext4jrlioc0.xml 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/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 From 49377648d1ce0a023f0f1a89a5fe81af977db8fa Mon Sep 17 00:00:00 2001 From: Joly163 <18990341730@163.com> Date: Wed, 22 Mar 2023 19:55:16 +0800 Subject: [PATCH 64/64] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/java0/conc0301/jrl/MultiObject.java" | 20 +++++++++ .../java/java0/conc0301/sync/TestSetGet.java" | 4 +- .../collection/ConcurrentHashMapDemo.java" | 17 +++++-- .../collection/CopyOnWriteArrayListDemo.java" | 40 ++++++++--------- .../java/java0/conc0303/collection/README.md" | 2 + .../conc0303/collection/joly/Arrays0.java" | 18 ++++++++ .../collection/joly/Collections0.java" | 26 +++++++++++ .../joly/ConcurrentHashMapDemo0.java" | 44 +++++++++++++++++++ .../conc0303/stream/StreamParallelDemo.java" | 28 ++++++++---- .../threadlocal/ThreadLocalDemo.java" | 10 ++++- .../threadlocal/jolyne/ThreadLocal0.java" | 14 ++++++ .../java/io/kimmking/spring01/Student.java | 2 +- 12 files changed, 188 insertions(+), 37 deletions(-) create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0301/jrl/MultiObject.java" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/README.md" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Arrays0.java" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/Collections0.java" create mode 100644 "03concurrency/0301\345\244\232\347\272\277\347\250\213/src/main/java/java0/conc0303/collection/joly/ConcurrentHashMapDemo0.java" 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/sync/TestSetGet.java" "b/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\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 1ec7f12b..f7aed69f 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index df60dc64..191c343d 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\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\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\345\244\232\347\272\277\347\250\213/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" index aaf9567d..4c66e9ee 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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\345\244\232\347\272\277\347\250\213/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" index 45c32a55..576093c5 100644 --- "a/03concurrency/0301\345\244\232\347\272\277\347\250\213/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,8 +1,15 @@ 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; } @@ -45,7 +52,8 @@ public void run() { 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" index 8eea9eb5..83d096f5 100644 --- "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" @@ -1,11 +1,20 @@ 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(); @@ -23,6 +32,11 @@ public void 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/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java index 84b66e8c..996894bf 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -42,13 +42,13 @@ public Student(int id, String name) { /** * knowledge point: BeanNameAware 用于在初始化Bean时将BeanName信息提供给该Bean应该是用反射实现的) */ + // TODO_Joly:拿来有什么用? private String beanName; /** * knowledge point: ApplicationContextAware 用于在初始化Bean的时候将ApplicationContext提供给该Bean */ private ApplicationContext applicationContext; - /*初始化之前就调用了。应该是属性赋值的阶段做的。*/ @Override public void setBeanName(String name) { this.beanName = name;