├── docs ├── Ref.md ├── aio.md ├── bio.md ├── ipc.md ├── jmx.md ├── nio.md ├── jax-ws.md ├── mq-other.md ├── overview.md ├── mas-overview.md ├── monitor-overview.md ├── rest.md ├── web-overview.md ├── zookeeper.md ├── actiovemq.md ├── spring-boot.md ├── 一个“超市”发展的例子.md ├── jersey.md ├── appendix.md ├── rmi-example.md ├── 分层.md ├── 草稿.md ├── architecture.md ├── api.md ├── mq-overview.md ├── basic.md ├── jms.md ├── rmi-overview.md ├── net-overview.md └── socket.md ├── samples ├── cxf-rest │ ├── .gitignore │ ├── .settings │ │ ├── org.eclipse.wst.jsdt.ui.superType.name │ │ ├── org.eclipse.wst.validation.prefs │ │ ├── org.eclipse.wst.jsdt.ui.superType.container │ │ ├── org.eclipse.m2e.core.prefs │ │ ├── org.eclipse.wst.common.project.facet.core.prefs.xml │ │ ├── org.eclipse.wst.common.project.facet.core.xml │ │ ├── org.eclipse.wst.common.component │ │ ├── org.eclipse.jdt.core.prefs │ │ └── .jsdtscope │ ├── src │ │ ├── main │ │ │ ├── webapp │ │ │ │ ├── META-INF │ │ │ │ │ └── context.xml │ │ │ │ └── WEB-INF │ │ │ │ │ ├── web.xml │ │ │ │ │ └── beans.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── cxf │ │ │ │ ├── JsonBean.java │ │ │ │ └── HelloWorld.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── cxf │ │ │ └── HelloWorldIT.java │ └── .classpath ├── jersey-rest │ ├── .gitignore │ ├── .settings │ │ ├── org.eclipse.m2e.core.prefs │ │ ├── org.eclipse.core.resources.prefs │ │ └── org.eclipse.jdt.core.prefs │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── jersey │ │ │ │ ├── MyResource.java │ │ │ │ └── Main.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── jersey │ │ │ └── MyResourceTest.java │ ├── .classpath │ └── pom.xml ├── hello-world-docker │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ └── application.properties │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── spring │ │ │ │ └── cloud │ │ │ │ └── weather │ │ │ │ ├── Application.java │ │ │ │ └── controller │ │ │ │ └── HelloController.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── spring │ │ │ └── cloud │ │ │ └── weather │ │ │ ├── ApplicationTests.java │ │ │ └── controller │ │ │ └── HelloControllerTest.java │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── Dockerfile │ ├── .gitignore │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── spring-boot-rest │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ └── application.properties │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── spring │ │ │ │ └── cloud │ │ │ │ └── weather │ │ │ │ ├── Application.java │ │ │ │ ├── controller │ │ │ │ ├── HelloController.java │ │ │ │ └── UserController.java │ │ │ │ ├── repository │ │ │ │ ├── UserRepository.java │ │ │ │ └── UserRepositoryImpl.java │ │ │ │ └── domain │ │ │ │ └── User.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── spring │ │ │ └── cloud │ │ │ └── weather │ │ │ ├── ApplicationTests.java │ │ │ └── controller │ │ │ └── HelloControllerTest.java │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ └── gradlew.bat ├── java-rmi │ ├── .gitignore │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── java │ │ │ └── demo │ │ │ └── rmi │ │ │ ├── ServerConstant.java │ │ │ ├── Message.java │ │ │ ├── RmiEchoClient.java │ │ │ └── RmiEchoServer.java │ └── pom.xml ├── java-ws │ ├── .gitignore │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── java │ │ │ └── ws │ │ │ ├── HelloService.java │ │ │ ├── HelloPublisher.java │ │ │ ├── HelloServiceImpl.java │ │ │ └── HelloClient.java │ └── pom.xml ├── java-io-mode │ ├── .gitignore │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── waylau │ │ └── java │ │ └── demo │ │ ├── net │ │ ├── BlockingEchoServer.java │ │ └── BlockingEchoClient.java │ │ ├── nio │ │ ├── NonBlockingEchoClient.java │ │ └── NonBlokingEchoServer.java │ │ └── aio │ │ ├── AsyncEchoClient.java │ │ └── AsyncEchoServer.java ├── javase-rest │ ├── .gitignore │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── rest │ │ │ ├── bean │ │ │ └── MyBean.java │ │ │ ├── RestApplication.java │ │ │ ├── App.java │ │ │ └── resource │ │ │ └── MyResource.java │ └── pom.xml ├── java-concurrency │ ├── .gitignore │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── waylau │ │ └── java │ │ └── demo │ │ └── concurrency │ │ └── Deadlock.java ├── eureka-client │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── application.properties │ │ │ │ └── static │ │ │ │ │ └── favicon.ico │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── spring │ │ │ │ └── cloud │ │ │ │ ├── controller │ │ │ │ └── HelloController.java │ │ │ │ └── Application.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── spring │ │ │ └── cloud │ │ │ ├── ApplicationTests.java │ │ │ └── controller │ │ │ └── HelloControllerTest.java │ ├── .gitignore │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── eureka-server │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── static │ │ │ │ │ └── favicon.ico │ │ │ │ └── application.properties │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── spring │ │ │ │ └── cloud │ │ │ │ ├── controller │ │ │ │ └── HelloController.java │ │ │ │ └── Application.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── spring │ │ │ └── cloud │ │ │ ├── ApplicationTests.java │ │ │ └── controller │ │ │ └── HelloControllerTest.java │ ├── .gitignore │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── jms-msg │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── spring │ │ │ │ └── jms │ │ │ │ ├── queue │ │ │ │ ├── ConsumerService.java │ │ │ │ ├── ConsumerListener.java │ │ │ │ ├── QueueMessageListener.java │ │ │ │ ├── ConsumerServiceImpl.java │ │ │ │ ├── ProducerService.java │ │ │ │ ├── ConsumerSessionAwareMessageListener.java │ │ │ │ └── ProducerServiceImpl.java │ │ │ │ └── topic │ │ │ │ ├── TopicMessageListener.java │ │ │ │ ├── TopicMessageListener2.java │ │ │ │ └── TopicProvider.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── spring │ │ │ └── jms │ │ │ └── SpringJmsTest.java │ ├── .gitignore │ └── pom.xml ├── axon-cqrs │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── log4j2.xml │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── axon │ │ │ └── cqrs │ │ │ ├── common │ │ │ ├── events │ │ │ │ ├── WithdrawMoneyEvent.java │ │ │ │ └── CreateAccountEvent.java │ │ │ └── domain │ │ │ │ └── AccountId.java │ │ │ ├── command │ │ │ ├── commands │ │ │ │ ├── WithdrawMoneyCommand.java │ │ │ │ └── CreateAccountCommand.java │ │ │ └── aggregates │ │ │ │ └── BankAccount.java │ │ │ └── Application.java │ └── pom.xml ├── spring-rest │ ├── .gitignore │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── spring │ │ │ └── mvc │ │ │ ├── Application.java │ │ │ ├── configuration │ │ │ ├── AppConfiguration.java │ │ │ └── MvcConfiguration.java │ │ │ ├── controller │ │ │ └── HelloController.java │ │ │ ├── vo │ │ │ └── User.java │ │ │ └── JettyServer.java │ └── pom.xml ├── security-basic │ ├── .gitignore │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── spring │ │ │ └── mvc │ │ │ ├── Application.java │ │ │ ├── configuration │ │ │ ├── AppConfiguration.java │ │ │ ├── MvcConfiguration.java │ │ │ └── WebSecurityConfig.java │ │ │ ├── controller │ │ │ └── HelloController.java │ │ │ ├── vo │ │ │ └── User.java │ │ │ └── JettyServer.java │ ├── dependency-reduced-pom.xml │ └── pom.xml ├── spark-word-count │ ├── .gitignore │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── waylau │ │ └── spark │ │ └── JavaWordCount.java ├── zk-registry-discovery │ ├── .gitignore │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── waylau │ │ │ │ └── zk │ │ │ │ ├── discovery │ │ │ │ ├── ServiceDiscovery.java │ │ │ │ └── ZkServiceDiscovery.java │ │ │ │ ├── Constant.java │ │ │ │ └── registry │ │ │ │ ├── ServiceRegistry.java │ │ │ │ └── ZkServiceRegistry.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── waylau │ │ │ └── zk │ │ │ └── ApplicationTests.java │ └── pom.xml └── game-server │ └── aws_game_server.js ├── images ├── net-2tcp.gif ├── net-1netw.gif ├── net-3tcpudp.gif ├── rpc-rmi_flow.png ├── rpc-rmi_logical.png ├── socket-5connect.gif ├── socket-6connect.gif └── distributed-object.jpg ├── .gitignore ├── LICENSE ├── SUMMARY.md └── README.md /docs/Ref.md: -------------------------------------------------------------------------------- 1 | # 参考文献 2 | 3 | -------------------------------------------------------------------------------- /docs/aio.md: -------------------------------------------------------------------------------- 1 | # AIO 2 | 3 | -------------------------------------------------------------------------------- /docs/bio.md: -------------------------------------------------------------------------------- 1 | # BIO 2 | 3 | -------------------------------------------------------------------------------- /docs/ipc.md: -------------------------------------------------------------------------------- 1 | # IPC 2 | 3 | -------------------------------------------------------------------------------- /docs/jmx.md: -------------------------------------------------------------------------------- 1 | # JMX 2 | 3 | -------------------------------------------------------------------------------- /docs/nio.md: -------------------------------------------------------------------------------- 1 | # NIO 2 | 3 | -------------------------------------------------------------------------------- /docs/jax-ws.md: -------------------------------------------------------------------------------- 1 | # JAX-WS 2 | 3 | -------------------------------------------------------------------------------- /docs/mq-other.md: -------------------------------------------------------------------------------- 1 | # 其他 2 | 3 | -------------------------------------------------------------------------------- /docs/overview.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | -------------------------------------------------------------------------------- /docs/mas-overview.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | -------------------------------------------------------------------------------- /docs/monitor-overview.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | -------------------------------------------------------------------------------- /docs/rest.md: -------------------------------------------------------------------------------- 1 | # RESTful 概述 2 | 3 | -------------------------------------------------------------------------------- /docs/web-overview.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | -------------------------------------------------------------------------------- /docs/zookeeper.md: -------------------------------------------------------------------------------- 1 | # ZooKeeper 2 | 3 | -------------------------------------------------------------------------------- /docs/actiovemq.md: -------------------------------------------------------------------------------- 1 | # ActiveMQ 示例 2 | 3 | -------------------------------------------------------------------------------- /docs/spring-boot.md: -------------------------------------------------------------------------------- 1 | # Spring Boot 2 | 3 | -------------------------------------------------------------------------------- /docs/一个“超市”发展的例子.md: -------------------------------------------------------------------------------- 1 | # 一个“超市”发展的例子 2 | 3 | -------------------------------------------------------------------------------- /samples/cxf-rest/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /samples/jersey-rest/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /docs/jersey.md: -------------------------------------------------------------------------------- 1 | # 基于 Jersey 的 JAX-RS 示例 2 | 3 | -------------------------------------------------------------------------------- /docs/appendix.md: -------------------------------------------------------------------------------- 1 | # 附录 2 | 3 | * 《分布式系统原理与范型(第二版)》 -------------------------------------------------------------------------------- /docs/rmi-example.md: -------------------------------------------------------------------------------- 1 | # 示例 2 | 3 | 4 | 5 | 本节示例,可以在`java-rmi`项目下找到。 -------------------------------------------------------------------------------- /samples/hello-world-docker/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /samples/java-rmi/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.idea/ 3 | /.settings/ 4 | .classpath 5 | .project -------------------------------------------------------------------------------- /samples/java-ws/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.idea/ 3 | /.settings/ 4 | .classpath 5 | .project -------------------------------------------------------------------------------- /images/net-2tcp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/net-2tcp.gif -------------------------------------------------------------------------------- /samples/java-io-mode/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.idea/ 3 | /.settings/ 4 | .classpath 5 | .project -------------------------------------------------------------------------------- /samples/javase-rest/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.idea/ 3 | /.settings/ 4 | .classpath 5 | .project -------------------------------------------------------------------------------- /images/net-1netw.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/net-1netw.gif -------------------------------------------------------------------------------- /images/net-3tcpudp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/net-3tcpudp.gif -------------------------------------------------------------------------------- /samples/java-concurrency/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.idea/ 3 | /.settings/ 4 | .classpath 5 | .project -------------------------------------------------------------------------------- /docs/分层.md: -------------------------------------------------------------------------------- 1 | # 分层 2 | 3 | * 试图层 4 | * 业务逻辑层 5 | * 数据层 6 | 7 | SQL 与领域模型分离 8 | 9 | 数据映射器 10 | JDO -------------------------------------------------------------------------------- /images/rpc-rmi_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/rpc-rmi_flow.png -------------------------------------------------------------------------------- /images/rpc-rmi_logical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/rpc-rmi_logical.png -------------------------------------------------------------------------------- /images/socket-5connect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/socket-5connect.gif -------------------------------------------------------------------------------- /images/socket-6connect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/socket-6connect.gif -------------------------------------------------------------------------------- /samples/cxf-rest/src/main/webapp/META-INF/context.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/distributed-object.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/images/distributed-object.jpg -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | disabled=06target 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /samples/spring-boot-rest/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/samples/spring-boot-rest/build.gradle -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /samples/jersey-rest/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /samples/eureka-client/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/samples/eureka-client/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/eureka-server/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/samples/eureka-server/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/eureka-client/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name: eureka-client 2 | 3 | eureka.client.serviceUrl.defaultZone: http://localhost:8761/eureka/ -------------------------------------------------------------------------------- /samples/eureka-client/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/samples/eureka-client/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /samples/eureka-server/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/samples/eureka-server/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/hello-world-docker/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylau/distributed-java/HEAD/samples/hello-world-docker/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/jersey-rest/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/test/java=UTF-8 4 | encoding/=UTF-8 5 | -------------------------------------------------------------------------------- /samples/hello-world-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ARG JAR_FILE 4 | ADD ${JAR_FILE} app.jar 5 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/eureka-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port: 8761 2 | 3 | eureka.instance.hostname: localhost 4 | eureka.client.registerWithEureka: false 5 | eureka.client.fetchRegistry: false 6 | eureka.client.serviceUrl.defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ -------------------------------------------------------------------------------- /samples/eureka-client/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 06 12:27:20 CET 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip 7 | -------------------------------------------------------------------------------- /samples/eureka-server/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 06 12:27:20 CET 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip 7 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jul 28 13:37:07 BST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | #distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-bin.zip 7 | distributionUrl=file\:/D:/software/webdev/java/gradle-4.0-all.zip -------------------------------------------------------------------------------- /samples/hello-world-docker/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jul 28 13:37:07 BST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | #distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-bin.zip 7 | distributionUrl=file\:/D:/software/webdev/java/gradle-4.0-all.zip -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/queue/ConsumerService.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.queue; 2 | 3 | import javax.jms.Destination; 4 | 5 | /** 6 | * Consumer Service. 7 | * 8 | * @since 1.0.0 2018年4月15日 9 | * @author Way Lau 10 | */ 11 | public interface ConsumerService { 12 | public void receive(Destination queueDestination); 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | /target/ 28 | -------------------------------------------------------------------------------- /samples/eureka-client/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | -------------------------------------------------------------------------------- /samples/eureka-server/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | -------------------------------------------------------------------------------- /samples/java-ws/src/main/java/com/waylau/java/ws/HelloService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.ws; 5 | 6 | import javax.jws.WebService; 7 | 8 | /** 9 | * Hello Service. 10 | * 11 | * @since 1.0.0 2020年1月25日 12 | * @author Way Lau 13 | */ 14 | @WebService 15 | public interface HelloService { 16 | String getHelloworld(); 17 | } 18 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | -------------------------------------------------------------------------------- /samples/hello-world-docker/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | -------------------------------------------------------------------------------- /samples/jms-msg/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | /target/ 28 | -------------------------------------------------------------------------------- /samples/axon-cqrs/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | /target/ 28 | -------------------------------------------------------------------------------- /samples/spring-rest/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | /target/ 28 | -------------------------------------------------------------------------------- /samples/security-basic/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | /target/ 28 | -------------------------------------------------------------------------------- /samples/spark-word-count/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | /target/ 28 | -------------------------------------------------------------------------------- /samples/zk-registry-discovery/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ 26 | /bin/ 27 | /target/ 28 | -------------------------------------------------------------------------------- /samples/security-basic/src/main/java/com/waylau/spring/mvc/Application.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.spring.mvc; 5 | 6 | /** 7 | * Application Main. 8 | * 9 | * @since 1.0.0 2018年3月21日 10 | * @author Way Lau 11 | */ 12 | public class Application { 13 | 14 | public static void main(String[] args) throws Exception { 15 | new JettyServer().run(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /samples/spring-rest/src/main/java/com/waylau/spring/mvc/Application.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.spring.mvc; 5 | 6 | /** 7 | * Application Main. 8 | * 9 | * @since 1.0.0 2018年3月21日 10 | * @author Way Lau 11 | */ 12 | public class Application { 13 | 14 | public static void main(String[] args) throws Exception { 15 | new JettyServer().run();; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /samples/zk-registry-discovery/src/main/java/com/waylau/zk/discovery/ServiceDiscovery.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.zk.discovery; 5 | 6 | /** 7 | * Service Discovery. 8 | * 9 | * @since 1.0.0 2018年5月16日 10 | * @author Way Lau 11 | */ 12 | public interface ServiceDiscovery { 13 | 14 | /** 15 | * 服务发现. 16 | * 17 | * @param name 18 | * @return 19 | */ 20 | String discover(String name); 21 | } 22 | -------------------------------------------------------------------------------- /samples/jersey-rest/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 5 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 6 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 7 | org.eclipse.jdt.core.compiler.release=disabled 8 | org.eclipse.jdt.core.compiler.source=1.7 9 | -------------------------------------------------------------------------------- /samples/zk-registry-discovery/src/main/java/com/waylau/zk/Constant.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.zk; 5 | 6 | /** 7 | * Constant. 8 | * 9 | * @since 1.0.0 2018年5月16日 10 | * @author Way Lau 11 | */ 12 | public interface Constant { 13 | 14 | /**会话超时时间*/ 15 | int ZK_SESSION_TIMEOUT = 5000; 16 | 17 | /**连接超时时间*/ 18 | int ZK_CONNECTION_TIMEOUT = 1000; 19 | 20 | String ZK_REGISTRY = "/registry"; 21 | } 22 | -------------------------------------------------------------------------------- /samples/zk-registry-discovery/src/main/java/com/waylau/zk/registry/ServiceRegistry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.zk.registry; 5 | 6 | /** 7 | * 8 | * @since 1.0.0 2018年5月16日 9 | * @author Way Lau 10 | */ 11 | public interface ServiceRegistry { 12 | 13 | /** 14 | * 注册服务. 15 | * 16 | * @param serviceName 17 | * @param serviceAddress 18 | */ 19 | void registry(String serviceName, String serviceAddress); 20 | } 21 | -------------------------------------------------------------------------------- /samples/cxf-rest/src/main/java/com/waylau/cxf/JsonBean.java: -------------------------------------------------------------------------------- 1 | package com.waylau.cxf; 2 | 3 | 4 | public class JsonBean { 5 | private String val1; 6 | private String val2; 7 | 8 | public String getVal1() { 9 | return val1; 10 | } 11 | 12 | public void setVal1(String val1) { 13 | this.val1 = val1; 14 | } 15 | 16 | public String getVal2() { 17 | return val2; 18 | } 19 | 20 | public void setVal2(String val2) { 21 | this.val2 = val2; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /samples/javase-rest/src/main/java/com/waylau/rest/bean/MyBean.java: -------------------------------------------------------------------------------- 1 | package com.waylau.rest.bean; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | @XmlRootElement 6 | public class MyBean { 7 | 8 | private String name; 9 | private int age; 10 | 11 | public String getName() { 12 | return name; 13 | } 14 | public void setName(String name) { 15 | this.name = name; 16 | } 17 | public int getAge() { 18 | return age; 19 | } 20 | public void setAge(int age) { 21 | this.age = age; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/java-ws/src/main/java/com/waylau/java/ws/HelloPublisher.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.ws; 5 | 6 | import javax.xml.ws.Endpoint; 7 | 8 | /** 9 | * Hello Publisher. 10 | * 11 | * @since 1.0.0 2020年1月25日 12 | * @author Way Lau 13 | */ 14 | public class HelloPublisher { 15 | public static void main(String[] args) { 16 | 17 | Endpoint.publish("http://localhost:9999/ws/hello", 18 | new HelloServiceImpl()); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /samples/java-rmi/src/main/java/com/waylau/java/demo/rmi/ServerConstant.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.rmi; 5 | 6 | /** 7 | * Server Constant. 8 | * 9 | * @since 1.0.0 2020年1月18日 10 | * @author Way Lau 11 | */ 12 | public interface ServerConstant { 13 | 14 | String HOST = 15 | "localhost"; 16 | 17 | int PORT = 1099; 18 | 19 | String REGIRTRY_NAME = "Echo Server Message"; 20 | 21 | String HELLO_WORLD = 22 | "Hello World! Welcome to waylau.com!"; 23 | } 24 | -------------------------------------------------------------------------------- /samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/Application.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * 主应用程序. 8 | * 9 | * @since 1.0.0 2017年9月27日 10 | * @author Way Lau 11 | */ 12 | @SpringBootApplication 13 | public class Application { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(Application.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/Application.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * 主应用程序. 8 | * 9 | * @since 1.0.0 2017年9月27日 10 | * @author Way Lau 11 | */ 12 | @SpringBootApplication 13 | public class Application { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(Application.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/javase-rest/src/main/java/com/waylau/rest/RestApplication.java: -------------------------------------------------------------------------------- 1 | package com.waylau.rest; 2 | 3 | 4 | import org.glassfish.jersey.media.multipart.MultiPartFeature; 5 | import org.glassfish.jersey.server.ResourceConfig; 6 | 7 | /** 8 | * REST 主应用 9 | * 10 | * @author waylau.com 11 | * 2015年3月3日 12 | */ 13 | public class RestApplication extends ResourceConfig { 14 | 15 | public RestApplication() { 16 | // 资源类所在的包路径 17 | packages("com.waylau.rest.resource"); 18 | 19 | // 注册 MultiPart 20 | register(MultiPartFeature.class); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/java-ws/src/main/java/com/waylau/java/ws/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.ws; 5 | 6 | import javax.jws.WebMethod; 7 | import javax.jws.WebService; 8 | /** 9 | * 10 | * @since 1.0.0 2020年1月25日 11 | * @author Way Lau 12 | */ 13 | @WebService(endpointInterface = "com.waylau.java.ws.HelloService") 14 | public class HelloServiceImpl implements HelloService { 15 | 16 | @WebMethod 17 | public String getHelloworld() { 18 | return "Hello world!"; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/java-rmi/src/main/java/com/waylau/java/demo/rmi/Message.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.rmi; 5 | 6 | import java.rmi.Remote; 7 | import java.rmi.RemoteException; 8 | 9 | /** 10 | * Message. 11 | * 12 | * @since 1.0.0 2020年1月18日 13 | * @author Way Lau 14 | */ 15 | public interface Message extends Remote { 16 | 17 | /** 18 | * 发送消息. 19 | * 20 | * @param msg 消息 21 | * @return 响应内容 22 | * @throws RemoteException 23 | */ 24 | String echoMessage(String msg) throws RemoteException; 25 | } 26 | -------------------------------------------------------------------------------- /samples/eureka-client/src/test/java/com/waylau/spring/cloud/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | /** 9 | * 主应用测试用例. 10 | * 11 | * @since 1.0.0 2017年9月27日 12 | * @author Way Lau 13 | */ 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class ApplicationTests { 17 | 18 | @Test 19 | public void contextLoads() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /samples/eureka-server/src/test/java/com/waylau/spring/cloud/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | /** 9 | * 主应用测试用例. 10 | * 11 | * @since 1.0.0 2017年9月27日 12 | * @author Way Lau 13 | */ 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class ApplicationTests { 17 | 18 | @Test 19 | public void contextLoads() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /samples/eureka-client/src/main/java/com/waylau/spring/cloud/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * Hello Controller. 8 | * 9 | * @since 1.0.0 2017年9月27日 10 | * @author Way Lau 11 | */ 12 | @RestController 13 | public class HelloController { 14 | 15 | @RequestMapping("/hello") 16 | public String hello() { 17 | return "Hello World! Welcome to visit waylau.com!"; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /samples/eureka-server/src/main/java/com/waylau/spring/cloud/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * Hello Controller. 8 | * 9 | * @since 1.0.0 2017年9月27日 10 | * @author Way Lau 11 | */ 12 | @RestController 13 | public class HelloController { 14 | 15 | @RequestMapping("/hello") 16 | public String hello() { 17 | return "Hello World! Welcome to visit waylau.com!"; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | /** 9 | * 主应用测试用例. 10 | * 11 | * @since 1.0.0 2017年9月27日 12 | * @author Way Lau 13 | */ 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class ApplicationTests { 17 | 18 | @Test 19 | public void contextLoads() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | /** 9 | * 主应用测试用例. 10 | * 11 | * @since 1.0.0 2017年9月27日 12 | * @author Way Lau 13 | */ 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class ApplicationTests { 17 | 18 | @Test 19 | public void contextLoads() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/queue/ConsumerListener.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.queue; 2 | 3 | /** 4 | * Consumer Listener. 5 | * 1. MessageListenerAdapter可以把一个普通的java当做MessageListener来处理消息。 6 | * 2. 返回类型不是void的时候,MessageListenerAdapter会自动把返回值封装成Message,并回复。 7 | * 8 | * @since 1.0.0 2018年4月15日 9 | * @author Way Lau 10 | */ 11 | public class ConsumerListener { 12 | 13 | public String receiveMessage(String message) { 14 | System.out.println("ConsumerListener接收到一个Text消息:\t" + message); 15 | 16 | return "I am ConsumerListener response"; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * Hello Controller. 8 | * 9 | * @since 1.0.0 2017年9月27日 10 | * @author Way Lau 11 | */ 12 | @RestController 13 | public class HelloController { 14 | 15 | @RequestMapping("/hello") 16 | public String hello() { 17 | return "Hello World! Welcome to visit waylau.com!"; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * Hello Controller. 8 | * 9 | * @since 1.0.0 2017年9月27日 10 | * @author Way Lau 11 | */ 12 | @RestController 13 | public class HelloController { 14 | 15 | @RequestMapping("/hello") 16 | public String hello() { 17 | return "Hello World! Welcome to visit waylau.com!"; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /samples/spring-rest/src/main/java/com/waylau/spring/mvc/configuration/AppConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc.configuration; 2 | 3 | import org.springframework.context.annotation.ComponentScan; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Import; 6 | 7 | /** 8 | * App Configuration. 9 | * 10 | * @since 1.0.0 2018年3月21日 11 | * @author Way Lau 12 | */ 13 | @Configuration 14 | @ComponentScan(basePackages = { "com.waylau.spring" }) 15 | @Import({ MvcConfiguration.class }) 16 | public class AppConfiguration { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /samples/eureka-client/src/main/java/com/waylau/spring/cloud/Application.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | /** 8 | * 主应用程序. 9 | * 10 | * @since 1.0.0 2017年11月01日 11 | * @author Way Lau 12 | */ 13 | @SpringBootApplication 14 | @EnableDiscoveryClient 15 | public class Application { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/eureka-server/src/main/java/com/waylau/spring/cloud/Application.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | /** 8 | * 主应用程序. 9 | * 10 | * @since 1.0.0 2017年10月31日 11 | * @author Way Lau 12 | */ 13 | @SpringBootApplication 14 | @EnableEurekaServer 15 | public class Application { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/AppConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc.configuration; 2 | 3 | import org.springframework.context.annotation.ComponentScan; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Import; 6 | 7 | /** 8 | * App Configuration. 9 | * 10 | * @since 1.0.0 2018年3月21日 11 | * @author Way Lau 12 | */ 13 | @Configuration 14 | @ComponentScan(basePackages = { "com.waylau.spring" }) 15 | @Import({ WebSecurityConfig.class, MvcConfiguration.class }) 16 | public class AppConfiguration { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.compliance=1.8 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 7 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 8 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 9 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 10 | org.eclipse.jdt.core.compiler.release=disabled 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /samples/cxf-rest/.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/jersey-rest/src/main/java/com/waylau/jersey/MyResource.java: -------------------------------------------------------------------------------- 1 | package com.waylau.jersey; 2 | 3 | import javax.ws.rs.GET; 4 | import javax.ws.rs.Path; 5 | import javax.ws.rs.Produces; 6 | import javax.ws.rs.core.MediaType; 7 | 8 | /** 9 | * Root resource (exposed at "myresource" path) 10 | */ 11 | @Path("myresource") 12 | public class MyResource { 13 | 14 | /** 15 | * Method handling HTTP GET requests. The returned object will be sent 16 | * to the client as "text/plain" media type. 17 | * 18 | * @return String that will be returned as a text/plain response. 19 | */ 20 | @GET 21 | @Produces(MediaType.TEXT_PLAIN) 22 | public String getIt() { 23 | return "Got it!"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/topic/TopicMessageListener.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.topic; 2 | 3 | import javax.jms.JMSException; 4 | import javax.jms.Message; 5 | import javax.jms.MessageListener; 6 | import javax.jms.TextMessage; 7 | 8 | /** 9 | * Topic Message Listener. 10 | * 11 | * @since 1.0.0 2018年4月15日 12 | * @author Way Lau 13 | */ 14 | public class TopicMessageListener implements MessageListener { 15 | 16 | public void onMessage(Message message) { 17 | TextMessage tm = (TextMessage) message; 18 | try { 19 | System.out.println("TopicMessageListener 监听到消息:\t" + tm.getText()); 20 | } catch (JMSException e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/queue/QueueMessageListener.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.queue; 2 | 3 | import javax.jms.JMSException; 4 | import javax.jms.Message; 5 | import javax.jms.MessageListener; 6 | import javax.jms.TextMessage; 7 | 8 | /** 9 | * Queue Message Listener. 10 | * 11 | * @since 1.0.0 2018年4月15日 12 | * @author Way Lau 13 | */ 14 | public class QueueMessageListener implements MessageListener { 15 | 16 | public void onMessage(Message message) { 17 | TextMessage tm = (TextMessage) message; 18 | try { 19 | System.out.println("ConsumerMessageListener收到了文本消息:\t" + tm.getText()); 20 | } catch (JMSException e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/topic/TopicMessageListener2.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.topic; 2 | 3 | import javax.jms.JMSException; 4 | 5 | import javax.jms.Message; 6 | import javax.jms.MessageListener; 7 | import javax.jms.TextMessage; 8 | 9 | /** 10 | * Topic Message Listener 2. 11 | * 12 | * @since 1.0.0 2018年4月15日 13 | * @author Way Lau 14 | */ 15 | public class TopicMessageListener2 implements MessageListener { 16 | 17 | public void onMessage(Message message) { 18 | TextMessage tm = (TextMessage) message; 19 | try { 20 | System.out.println("TopicMessageListener2监听到消息 \t" + tm.getText()); 21 | } catch (JMSException e) { 22 | e.printStackTrace(); 23 | } 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /samples/security-basic/src/main/java/com/waylau/spring/mvc/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import com.waylau.spring.mvc.vo.User; 7 | 8 | 9 | /** 10 | * Hello 控制器. 11 | * 12 | * @since 1.0.0 2018年3月21日 13 | * @author Way Lau 14 | */ 15 | @RestController 16 | public class HelloController { 17 | 18 | @RequestMapping("/hello") 19 | public String hello() { 20 | return "Hello World! Welcome to visit waylau.com!"; 21 | } 22 | 23 | @RequestMapping("/hello/way") 24 | public User helloWay() { 25 | return new User("Way Lau", 30); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/spring-rest/src/main/java/com/waylau/spring/mvc/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import com.waylau.spring.mvc.vo.User; 7 | 8 | 9 | /** 10 | * Hello 控制器. 11 | * 12 | * @since 1.0.0 2018年3月21日 13 | * @author Way Lau 14 | */ 15 | @RestController 16 | public class HelloController { 17 | 18 | @RequestMapping("/hello") 19 | public String hello() { 20 | return "Hello World! Welcome to visit waylau.com!"; 21 | } 22 | 23 | @RequestMapping("/hello/way") 24 | public User helloWay() { 25 | return new User("Way Lau", 30); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/java/com/waylau/axon/cqrs/common/events/WithdrawMoneyEvent.java: -------------------------------------------------------------------------------- 1 | package com.waylau.axon.cqrs.common.events; 2 | 3 | import com.waylau.axon.cqrs.common.domain.AccountId; 4 | 5 | /** 6 | * Withdraw Money Event. 7 | * 8 | * @since 1.0.0 2020年1月21日 9 | * @author Way Lau 10 | */ 11 | public class WithdrawMoneyEvent { 12 | private AccountId accountId; 13 | private long amount; 14 | 15 | public WithdrawMoneyEvent(AccountId accountId, long amount) { 16 | this.accountId = accountId; 17 | this.amount = amount; 18 | } 19 | 20 | public AccountId getAccountId() { 21 | return accountId; 22 | } 23 | 24 | public long getAmount() { 25 | return amount; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/spring-rest/src/main/java/com/waylau/spring/mvc/vo/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.spring.mvc.vo; 5 | 6 | /** 7 | * User. 8 | * 9 | * @since 1.0.0 2018年2月10日 10 | * @author Way Lau 11 | */ 12 | public class User { 13 | private String username; 14 | private Integer age; 15 | 16 | public User(String username, Integer age) { 17 | this.username = username; 18 | this.age = age; 19 | } 20 | 21 | public String getUsername() { 22 | return username; 23 | } 24 | 25 | public void setUsername(String username) { 26 | this.username = username; 27 | } 28 | 29 | public Integer getAge() { 30 | return age; 31 | } 32 | 33 | public void setAge(Integer age) { 34 | this.age = age; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /samples/security-basic/src/main/java/com/waylau/spring/mvc/vo/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.spring.mvc.vo; 5 | 6 | /** 7 | * User. 8 | * 9 | * @since 1.0.0 2018年2月10日 10 | * @author Way Lau 11 | */ 12 | public class User { 13 | private String username; 14 | private Integer age; 15 | 16 | public User(String username, Integer age) { 17 | this.username = username; 18 | this.age = age; 19 | } 20 | 21 | public String getUsername() { 22 | return username; 23 | } 24 | 25 | public void setUsername(String username) { 26 | this.username = username; 27 | } 28 | 29 | public Integer getAge() { 30 | return age; 31 | } 32 | 33 | public void setAge(Integer age) { 34 | this.age = age; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /docs/草稿.md: -------------------------------------------------------------------------------- 1 | ## 分布式计算的概念 2 | 3 | 把一个大计算任务拆分成多个小计算任务分布到若干台机器上去计算,然后再进行结果汇总。 4 | 5 | ## 目的 6 | 7 | * 可靠性:系统本身也不可能是完美的,随时可能会出错,为了避免故障,需要将业务分散开保留一定的冗余度,或者将系统部署到多台机器上提供相同的功能,这个也称为“集群”。 8 | * 扩展性:系统负载高,单台机器无法承载,希望通过使用多台机器来提高系统的负载能力 9 | 10 | ## 注意点 11 | 12 | * 系统如何拆分为子系统 13 | * 子系统间如何规划通信协议 14 | * 一致性 15 | * 容错 16 | * 安全 17 | 18 | ## 基础设施 19 | 20 | * 缓存 21 | * 异步 22 | * 持久化存储 23 | * 消息队列 24 | * 搜索 25 | * 集群 26 | * 负载均衡:淘宝是LVS(Linux Virtual Server)、CDN节点、PV(Page View,页面访问量)、个UV(Unique Visitor,用户访问) 27 | * 数据压缩 28 | * 分析和挖掘 29 | 30 | 架构是一开始就能设计完美,需要不断优化 31 | 32 | “火车模型”:一个功能没有测试通过,整个系统都不能发布。即任何一个乘客没有上车,都不许发车。 33 | 34 | 超市的运维的抽象 35 | 36 | Memcache: 分布式缓存 37 | Hadoop:离线分析 38 | 39 | jetty tomcat 40 | 41 | :“I hear and I forget. I see and I remember. I do and I understand” 42 | 43 | 荀子说的“不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之。” -------------------------------------------------------------------------------- /samples/cxf-rest/src/main/java/com/waylau/cxf/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package com.waylau.cxf; 2 | import javax.ws.rs.Consumes; 3 | import javax.ws.rs.GET; 4 | import javax.ws.rs.POST; 5 | import javax.ws.rs.Path; 6 | import javax.ws.rs.PathParam; 7 | import javax.ws.rs.Produces; 8 | import javax.ws.rs.core.Response; 9 | 10 | @Path("/hello") 11 | public class HelloWorld { 12 | 13 | @GET 14 | @Path("/echo/{input}") 15 | @Produces("text/plain") 16 | public String ping(@PathParam("input") String input) { 17 | return input; 18 | } 19 | 20 | @POST 21 | @Produces("application/json") 22 | @Consumes("application/json") 23 | @Path("/jsonBean") 24 | public Response modifyJson(JsonBean input) { 25 | input.setVal2(input.getVal1()); 26 | return Response.ok().entity(input).build(); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /samples/java-ws/src/main/java/com/waylau/java/ws/HelloClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.ws; 5 | 6 | import java.net.URL; 7 | import javax.xml.namespace.QName; 8 | import javax.xml.ws.Service; 9 | 10 | /** 11 | * Hello Client. 12 | * 13 | * @since 1.0.0 2020年1月25日 14 | * @author Way Lau 15 | */ 16 | public class HelloClient { 17 | 18 | public static void main(String[] args) throws Exception { 19 | URL url = new URL("http://localhost:9999/ws/hello?wsdl"); 20 | QName qname = new QName("http://ws.java.waylau.com/", 21 | "HelloServiceImplService"); 22 | 23 | Service service = Service.create(url, qname); 24 | 25 | HelloService hello = service.getPort(HelloService.class); 26 | System.out.println(hello.getHelloworld()); 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.repository; 2 | 3 | import java.util.List; 4 | 5 | import com.waylau.spring.cloud.weather.domain.User; 6 | 7 | /** 8 | * 用户仓库. 9 | * 10 | * @since 1.0.0 2017年10月8日 11 | * @author Way Lau 12 | */ 13 | public interface UserRepository { 14 | 15 | /** 16 | * 新增或者修改用户 17 | * 18 | * @param user 19 | * @return 20 | */ 21 | User saveOrUpateUser(User user); 22 | 23 | /** 24 | * 删除用户 25 | * 26 | * @param id 27 | */ 28 | void deleteUser(Long id); 29 | 30 | /** 31 | * 根据用户id获取用户 32 | * 33 | * @param id 34 | * @return 35 | */ 36 | User getUserById(Long id); 37 | 38 | /** 39 | * 获取所有用户的列表 40 | * 41 | * @return 42 | */ 43 | List listUser(); 44 | } 45 | -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/java/com/waylau/axon/cqrs/command/commands/WithdrawMoneyCommand.java: -------------------------------------------------------------------------------- 1 | package com.waylau.axon.cqrs.command.commands; 2 | 3 | import org.axonframework.commandhandling.TargetAggregateIdentifier; 4 | 5 | import com.waylau.axon.cqrs.common.domain.AccountId; 6 | 7 | /** 8 | * Withdraw Money Command. 9 | * 10 | * @since 1.0.0 2020年1月21日 11 | * @author Way Lau 12 | */ 13 | public class WithdrawMoneyCommand { 14 | 15 | @TargetAggregateIdentifier 16 | private AccountId accountId; 17 | private long amount; 18 | 19 | 20 | public WithdrawMoneyCommand(AccountId accountId, long amount) { 21 | this.accountId = accountId; 22 | this.amount = amount; 23 | } 24 | 25 | public AccountId getAccountId() { 26 | return accountId; 27 | } 28 | 29 | public long getAmount() { 30 | return amount; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /samples/spring-rest/src/main/java/com/waylau/spring/mvc/configuration/MvcConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc.configuration; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.converter.HttpMessageConverter; 7 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 8 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 10 | 11 | /** 12 | * MVC Configuration. 13 | * 14 | * @since 1.0.0 2018年3月21日 15 | * @author Way Lau 16 | */ 17 | @EnableWebMvc 18 | @Configuration 19 | public class MvcConfiguration implements WebMvcConfigurer { 20 | 21 | public void extendMessageConverters(List> converters) { 22 | converters.add(new MappingJackson2HttpMessageConverter()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/MvcConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc.configuration; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.converter.HttpMessageConverter; 7 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 8 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 10 | 11 | /** 12 | * MVC Configuration. 13 | * 14 | * @since 1.0.0 2018年3月21日 15 | * @author Way Lau 16 | */ 17 | @EnableWebMvc 18 | @Configuration 19 | public class MvcConfiguration implements WebMvcConfigurer { 20 | 21 | @Override 22 | public void extendMessageConverters(List> converters) { 23 | converters.add(new MappingJackson2HttpMessageConverter()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/java/com/waylau/axon/cqrs/common/events/CreateAccountEvent.java: -------------------------------------------------------------------------------- 1 | package com.waylau.axon.cqrs.common.events; 2 | 3 | import com.waylau.axon.cqrs.common.domain.AccountId; 4 | 5 | /** 6 | * Create Account Event. 7 | * 8 | * @since 1.0.0 2020年1月21日 9 | * @author Way Lau 10 | */ 11 | public class CreateAccountEvent { 12 | private AccountId accountId; 13 | private String accountName; 14 | private long amount; 15 | 16 | public CreateAccountEvent(AccountId accountId, 17 | String accountName, long amount) { 18 | this.accountId = accountId; 19 | this.accountName = accountName; 20 | this.amount = amount; 21 | } 22 | 23 | public AccountId getAccountId() { 24 | return accountId; 25 | } 26 | 27 | public String getAccountName() { 28 | return accountName; 29 | } 30 | 31 | public long getAmount() { 32 | return amount; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/java/com/waylau/axon/cqrs/command/commands/CreateAccountCommand.java: -------------------------------------------------------------------------------- 1 | package com.waylau.axon.cqrs.command.commands; 2 | 3 | import com.waylau.axon.cqrs.common.domain.AccountId; 4 | 5 | /** 6 | * Create Account Command. 7 | * 8 | * @since 1.0.0 2020年1月21日 9 | * @author Way Lau 10 | */ 11 | public class CreateAccountCommand { 12 | 13 | private AccountId accountId; 14 | private String accountName; 15 | private long amount; 16 | 17 | public CreateAccountCommand(AccountId accountId, 18 | String accountName, 19 | long amount) { 20 | this.accountId = accountId; 21 | this.accountName = accountName; 22 | this.amount = amount; 23 | } 24 | 25 | public AccountId getAccountId() { 26 | return accountId; 27 | } 28 | 29 | public String getAccountName() { 30 | return accountName; 31 | } 32 | 33 | public long getAmount() { 34 | return amount; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/queue/ConsumerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.queue; 2 | 3 | 4 | import javax.jms.Destination; 5 | import javax.jms.JMSException; 6 | import javax.jms.TextMessage; 7 | 8 | import org.springframework.jms.core.JmsTemplate; 9 | /** 10 | * Consumer Service. 11 | * 12 | * @since 1.0.0 2018年4月15日 13 | * @author Way Lau 14 | */ 15 | public class ConsumerServiceImpl implements ConsumerService { 16 | 17 | private JmsTemplate jmsTemplate; 18 | 19 | /** 20 | * 接受消息 21 | */ 22 | public void receive(Destination destination) { 23 | TextMessage tm = (TextMessage) jmsTemplate.receive(destination); 24 | try { 25 | System.out.println("ConsumerService从队列" 26 | + destination.toString() + "收到了消息:\t" + tm.getText()); 27 | } catch (JMSException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | public void setJmsTemplate(JmsTemplate jmsTemplate) { 33 | this.jmsTemplate = jmsTemplate; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /samples/java-rmi/src/main/java/com/waylau/java/demo/rmi/RmiEchoClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.rmi; 5 | 6 | import java.rmi.registry.LocateRegistry; 7 | import java.rmi.registry.Registry; 8 | 9 | /** 10 | * RMI Echo Client. 11 | * 12 | * @since 1.0.0 2020年1月18日 13 | * @author Way Lau 14 | */ 15 | public class RmiEchoClient { 16 | 17 | public static void main(String[] args) { 18 | try { 19 | String host = ServerConstant.HOST; 20 | int port = ServerConstant.PORT; 21 | 22 | Registry registry = LocateRegistry.getRegistry(host, port); 23 | Message stub = 24 | (Message) registry.lookup(ServerConstant.REGIRTRY_NAME); 25 | String response = stub.echoMessage(ServerConstant.HELLO_WORLD); 26 | 27 | System.out.println("Server -> Client: " + response); 28 | } catch (Exception e) { 29 | System.err.println("RmiEchoClient exception: " + e.toString()); 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /samples/zk-registry-discovery/src/test/java/com/waylau/zk/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.zk; 5 | 6 | import org.junit.Test; 7 | 8 | import com.waylau.zk.discovery.ZkServiceDiscovery; 9 | import com.waylau.zk.registry.ZkServiceRegistry; 10 | 11 | 12 | /** 13 | * Application Tests. 14 | * 15 | * @since 1.0.0 2018年5月15日 16 | * @author Way Lau 17 | */ 18 | public class ApplicationTests { 19 | 20 | private static final String SERVER_NAME = "waylau.com"; 21 | private static final String SERVER_ADDRESS = "localhost:2181"; 22 | 23 | @Test 24 | public void testClient() throws Exception { 25 | 26 | ZkServiceRegistry registry = new ZkServiceRegistry(); 27 | registry.init(); 28 | registry.registry(SERVER_NAME, SERVER_ADDRESS); 29 | 30 | ZkServiceDiscovery discovery = new ZkServiceDiscovery(); 31 | discovery.init(); 32 | discovery.discover(SERVER_NAME); 33 | 34 | // 永不停止 35 | while(true) { 36 | } 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/queue/ProducerService.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.queue; 2 | 3 | import javax.jms.Destination; 4 | 5 | /** 6 | * Producer Service. 7 | * 8 | * @since 1.0.0 2018年4月15日 9 | * @author Way Lau 10 | */ 11 | public interface ProducerService { 12 | 13 | /** 14 | * 发消息,向默认的 destination 15 | * 16 | * @param msg 17 | * String 消息内容 18 | */ 19 | public void sendMessage(String msg); 20 | 21 | /** 22 | * 发消息,向指定的 destination 23 | * 24 | * @param destination 25 | * 目的地 26 | * @param msg 27 | * String 消息内容 28 | */ 29 | public void sendMessage(Destination destination, String msg); 30 | 31 | /** 32 | * 向指定的destination发送消息,消费者接受消息后,把回复的消息写到response队列 33 | * 34 | * @param destination 35 | * 目的地 36 | * @param msg 37 | * String 消息内容 38 | * @param response 39 | * 回复消息的队列 40 | */ 41 | public void sendMessage(Destination destination, String msg, Destination response); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.domain; 2 | 3 | /** 4 | * User. 5 | * 6 | * @since 1.0.0 2017年10月8日 7 | * @author Way Lau 8 | */ 9 | public class User { 10 | 11 | private Long id; 12 | 13 | private String name; 14 | 15 | private String email; 16 | 17 | public User() { 18 | } 19 | 20 | public User(String name, String email) { 21 | this.name = name; 22 | this.email = email; 23 | } 24 | 25 | public Long getId() { 26 | return id; 27 | } 28 | 29 | public void setId(Long id) { 30 | this.id = id; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | 41 | public String getEmail() { 42 | return email; 43 | } 44 | 45 | public void setEmail(String email) { 46 | this.email = email; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return String.format("User[id=%d, name='%s', email='%s']", id, name, email); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /docs/architecture.md: -------------------------------------------------------------------------------- 1 | # 架构 2 | 3 | ### RMI 架构 4 | 5 | RMI 是一个三层架构(见图)。最上面是 Stub/Skeleton layer(存根/骨架层)。方法调用从 Stub、Remote Reference Layer (远程引用层)和 Transport Layer(传输层)向下,传递给主机,然后再次经传 Transport Layer 层,向上穿过 Remote Reference Layer 和 Skeleton ,到达服务器对象。 Stub 扮演着远程服务器对象的代理的角色,使该对象可被客户激活。Remote Reference Layer 处理语义、管理单一或多重对象的通信,决定调用是应发往一个服务器还是多个。Transport Layer 管理实际的连接,并且追踪可以接受方法调用的远程对象。服务器端的 Skeleton 完成对服务器对象实际的方法调用,并获取返回值。返回值向下经 Remote Reference Layer 、服务器端的 Transport Layer 传递回客户端,再向上经 Transport Layer 和 Remote Reference Layer 返回。最后,Stub 程序获得返回值。 6 | 7 | 要完成以上步骤需要有以下几个步骤: 8 | 9 | * 生成一个远程接口; 10 | * 实现远程对象(服务器端程序); 11 | * 生成 Stub 和 Skeleton(服务器端程序); 12 | * 编写服务器程序 ; 13 | * 编写客户程序 ; 14 | * 注册远程对象; 15 | * 启动远程对象 16 | 17 | ![Java RMI 架构](../images/rpc-rmi_logical.png) 18 | 19 | 20 | 21 | ### RMI 分布式垃圾回收 22 | 23 | 根据 Java 虚拟机的垃圾回收机制原理,在分布式环境下,服务器进程需要知道哪些对象不再由客户端引用,从而可以被删除(垃圾回收)。在 JVM 中,Java 使用引用计数。当引用计数归零时,对象将会垃圾回收。在RMI,Java 支持两种操作 dirty 和 clean。本地 JVM 定期发送一个 dirty 到服务器来说明该对象仍在使用。定期重发 dirty 的周期是由服务器租赁时间来决定的。当客户端没有需要更多的本地引用远程对象时,它发送一个 clean 调用给服务器。不像 DCOM,服务器不需要计算每个客户机使用的对象,只是简单的做下通知。如果它租赁时间到期之前没有接收到任何 dirty 或者 clean 的消息,则可以安排将对象删除。 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Way Lau 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /samples/spark-word-count/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.waylau.spark 5 | spark-word-count 6 | 1.0.0 7 | spark-word-count 8 | jar 9 | 10 | waylau.com 11 | https://waylau.com 12 | 13 | 14 | 15 | UTF-8 16 | 2.4.4 17 | 18 | 19 | 20 | 21 | org.apache.spark 22 | spark-core_2.11 23 | ${spark.version} 24 | 25 | 26 | org.apache.spark 27 | spark-sql_2.11 28 | ${spark.version} 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /samples/jersey-rest/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/topic/TopicProvider.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.topic; 2 | 3 | import javax.jms.Destination; 4 | import javax.jms.JMSException; 5 | import javax.jms.Message; 6 | import javax.jms.Session; 7 | 8 | import org.springframework.jms.core.JmsTemplate; 9 | import org.springframework.jms.core.MessageCreator; 10 | 11 | /** 12 | * Topic Provider. 13 | * 14 | * @since 1.0.0 2018年4月15日 15 | * @author Way Lau 16 | */ 17 | public class TopicProvider { 18 | 19 | private JmsTemplate topicJmsTemplate; 20 | 21 | /** 22 | * 向指定的topic发布消息 23 | * 24 | * @param topic 25 | * @param msg 26 | */ 27 | public void publish(final Destination topic, final String msg) { 28 | 29 | topicJmsTemplate.send(topic, new MessageCreator() { 30 | public Message createMessage(Session session) throws JMSException { 31 | System.out.println("TopicProvider 发布了主题:\t" 32 | + topic.toString() + ",发布消息内容为:\t" + msg); 33 | return session.createTextMessage(msg); 34 | } 35 | }); 36 | } 37 | 38 | public void setTopicJmsTemplate(JmsTemplate topicJmsTemplate) { 39 | this.topicJmsTemplate = topicJmsTemplate; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introduction](README.md) 4 | * [基础概念](docs/basic.md) 5 | * 划分子系统 6 | * 一个“超市”发展的例子 7 | * 分层 8 | * 通信原理 9 | * [IPC](docs/ipc.md) 10 | * [RPC](https://waylau.com/remote-procedure-calls) 11 | * 网络通信基础 12 | * [概述](docs/net-overview.md) 13 | * [Socket](docs/socket.md) 14 | * [BIO](docs/bio.md) 15 | * [NIO](docs/nio.md) 16 | * [AIO](docs/aio.md) 17 | * 分布式对象 Java RMI 18 | * [概述](docs/rmi-overview.md) 19 | * [架构](docs/architecture.md) 20 | * [常用接口](docs/api.md) 21 | * [示例](docs/rmi-example.md) 22 | * 基于消息的通信 23 | * [概述](docs/mq-overview.md) 24 | * [JMS](docs/jms.md) 25 | * [ActiveMQ 示例](docs/actiovemq.md) 26 | * [其他](docs/mq-other.md) 27 | * Web Services 28 | * [概述](docs/web-overview.md) 29 | * [JAX-WS](docs/jax-ws.md) 30 | * [RESTful 概述](docs/rest.md) 31 | * [基于 Jersey 的 JAX-RS 示例 ](docs/jersey.md) 32 | * 微服务 33 | * [概述](docs/mas-overview.md) 34 | * [Spring Boot](docs/spring-boot.md) 35 | * 监控 36 | * [概述](docs/monitor-overview.md) 37 | * [JMX](docs/jmx.md) 38 | * [ZooKeeper](docs/zookeeper.md) 39 | * To be continued ...未完待续... 40 | * [参考文献](docs/Ref.md) 41 | 42 | -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | # 常用接口 2 | 3 | ### 接口和类 4 | 5 | 所有的远程接口都继承自 `java.rmi.Remote` 接口。例如: 6 | 7 | ```java 8 | public interface bankaccount extends Remote 9 | { 10 | public void deposit(float amount) 11 | throws java.rmi.RemoteException; 12 | 13 | public void withdraw(float amount) 14 | throws OverdrawnException, 15 | java.rmi.RemoteException; 16 | } 17 | ``` 18 | 19 | 注意,每个方法必须在 throws 里面声明 `java.rmi.RemoteException` 。 只要客户端调用远程方法出现失败,这个异常就会抛出。 20 | 21 | ### 远程对象类 22 | 23 | `Java.rmi.server.RemoteObject` 类提供了远程对象实现的语义包括hashCode、equals 和 toString。 `java.rmi.server.RemoteServer` 及其子类提供让对象实现远程可见。`java.rmi.server.UnicastRemoteObject` 类定义了客户机与服务器对象实例建立一对一的连接. 24 | 25 | ### 存根 26 | 27 | Java RMI 通过创建存根函数来工作。存根由 rmic 编译器生成。自 Java 1.5 以来,Java 支持在运行时动态生成存根类。编译器 rmic 会提供各种编译选项。 28 | 29 | ### 定位对象 30 | 31 | 引导名称服务提供了用于存储对远程对象的命名引用。一个远程对象引用可以存储使用类 `java.rmi.Naming` 提供的基于 URL 的方法。例如, 32 | 33 | ``` 34 | BankAccount acct = new BankAcctImpl(); 35 | String url = "rmi://java.sun.com/account"; 36 | // bind url to remote object 37 | java.rmi.Naming.bind(url, acct); 38 | 39 | // look up account 40 | acct = (BankAccount)java.rmi.Naming.lookup(url); 41 | ``` 42 | 43 | ![Java RMI 工作流程](../images/rpc-rmi_flow.png) 44 | -------------------------------------------------------------------------------- /samples/cxf-rest/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | JAX-RS Simple Service 7 | JAX-RS Simple Service 8 | 9 | contextConfigLocation 10 | WEB-INF/beans.xml 11 | 12 | 13 | 14 | org.springframework.web.context.ContextLoaderListener 15 | 16 | 17 | 18 | CXFServlet 19 | 20 | org.apache.cxf.transport.servlet.CXFServlet 21 | 22 | 1 23 | 24 | 25 | CXFServlet 26 | /* 27 | 28 | 29 | -------------------------------------------------------------------------------- /samples/cxf-rest/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /samples/java-rmi/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.waylau 7 | java-rmi 8 | 1.0.0 9 | jar 10 | 11 | java-rmi 12 | https://waylau.com 13 | 14 | 15 | UTF-8 16 | 1.8 17 | ${maven.compiler.source} 18 | 5.5.2 19 | 20 | 21 | 22 | 23 | maven-compiler-plugin 24 | 3.8.1 25 | 26 | 27 | 28 | 29 | 30 | 31 | org.junit.jupiter 32 | junit-jupiter 33 | ${junit.jupiter.version} 34 | test 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /samples/java-io-mode/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.waylau 7 | java-io-mode 8 | 1.0.0 9 | jar 10 | 11 | java-io-mode 12 | https://waylau.com 13 | 14 | 15 | UTF-8 16 | 1.8 17 | ${maven.compiler.source} 18 | 5.5.2 19 | 20 | 21 | 22 | 23 | maven-compiler-plugin 24 | 3.8.1 25 | 26 | 27 | 28 | 29 | 30 | 31 | org.junit.jupiter 32 | junit-jupiter 33 | ${junit.jupiter.version} 34 | test 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /samples/java-concurrency/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.waylau 7 | java-concurrency 8 | 1.0.0 9 | jar 10 | 11 | java-concurrency 12 | https://waylau.com 13 | 14 | 15 | UTF-8 16 | 1.8 17 | ${maven.compiler.source} 18 | 5.5.2 19 | 20 | 21 | 22 | 23 | maven-compiler-plugin 24 | 3.8.1 25 | 26 | 27 | 28 | 29 | 30 | 31 | org.junit.jupiter 32 | junit-jupiter 33 | ${junit.jupiter.version} 34 | test 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /docs/mq-overview.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | 面向消息的中间件(MOM)或者消息队列(MQ),提供了以松散耦合的灵活方式集成应用程序的一种机制。它们提供了基于存储和转发的应用程序之间的异步数据发送,即应用程序彼此不直接通信,而是与作为中介的 MOM 通信。MOM 提供了有保证的消息发送,应用程序开发人员无需了解远程过程调用(PRC)和网络/通信协议的细节。 4 | 5 | ## 消息中间件简介 6 | 7 | 远程过程调用有助于隐藏分布式系统中的通信细节,也就是说增强了访问透明性。但这种机制并不一定适合所有场景。特别是当无法保证发出请求时接收端一定正在执行的情况下,就必须有其他的通信服务。同时 RPC 的同步特性也会造成客户在发出请求得到处理之前被阻塞了,因而有时也需要采取其他的办法。而面向消息的通信就是解决了上面提到的种种问题。 8 | 9 | 面向消息的通信一般是由消息队列系统(Message-Queuing System,MQ)或者面向消息中间件( Message-Oriented Middleware,MOM)来提供高效可靠的消息传递机制进行平台无关的数据交流,并可基于数据通信进行分布系统的集成。通过提供消息传递和消息排队模型,可在分布环境下扩展进程间的通信,并支持多种通讽协议、语言、应用程序、硬件和软件平台。 10 | 11 | 通过使用 MQ 或者 MOM,通信双方的程序(称其为消息客户程序)可以在不同的时间运行,程序不在网络上直接通话,而是间接地将消息放入 MQ 或者 MOM 服务器的消息机制中。因为程序间没有直接的联系,所以它们不必同时运行:消息放入适当的队列时,目标程序不需要正在运行;即使目标程序在运行,也不意味着要立即处理该消息。 12 | 13 | 消息客户程序之间通过将消息放入消息队列或从消息队列中取出消息来进行通讯。客户程序不直接与其他程序通信,避免了网络通讯的复杂性。消息队列和网络通信的维护工作由 MQ 或者 MOM 完成。 14 | 15 | 常见的 MQ 或者 MOM 产品有 Java Message Service、Apache ActiveMQ、RocketMQ、RabbitMQ、Apache Kafka 等。 16 | 17 | ## 消息中间件优点 18 | 19 | 消息中间件作为一个中间层软件,它为分布式系统中创建、发送、接收消息提供了一套可靠通用的方法,实现了分布式系统中可靠的、高效的、实时的跨平台数据传输。消息中间件减少了开发跨平台和网络协议软件的复杂性,它屏蔽了不同操作系统和网络协议的具体细节,面对规模和复杂度都越来越高的分布式系统,消息中间件技术显示出了它的优越性: 20 | 21 | 1. 采用异步通信模式:发送消息者可以在发送消息后进行其它的工作,不用等待接收者的回应,而接收者也不必在接到消息后立即对发送者的请求进行处理; 22 | 2. 客户和服务对象生命周期的松耦合关系:客户进程和服务对象进程不要求都正常运行,如果由于服务对象崩溃或者网络故障导致客户的请求不可达,客户不会接收到异常,消息中间件能保证消息不会丢失。 -------------------------------------------------------------------------------- /samples/cxf-rest/src/main/webapp/WEB-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/queue/ConsumerSessionAwareMessageListener.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.queue; 2 | 3 | import javax.jms.Destination; 4 | import javax.jms.JMSException; 5 | import javax.jms.MessageProducer; 6 | import javax.jms.Session; 7 | import javax.jms.TextMessage; 8 | 9 | import org.springframework.jms.listener.SessionAwareMessageListener; 10 | 11 | /** 12 | * Consumer SessionAwareMessageListener. 13 | * SessionAwareMessageListener提供了一个快捷的方法,方便我们在接受消息以后,发送一条回复消息 * 14 | * onMessage()有2个参数,一个是收到的消息,另一个Session可以用于发送回复消息。 15 | * 16 | * @since 1.0.0 2018年4月15日 17 | * @author Way Lau 18 | */ 19 | public class ConsumerSessionAwareMessageListener 20 | implements SessionAwareMessageListener { 21 | 22 | private Destination destination; 23 | 24 | public void onMessage(TextMessage message, Session session) throws JMSException { 25 | // 接受消息 26 | System.out.println("SessionAwareMessageListener收到一条消息:\t" + message.getText()); 27 | 28 | // 发送消息 29 | MessageProducer producer = session.createProducer(destination); 30 | TextMessage tm = 31 | session.createTextMessage("I am ConsumerSessionAwareMessageListener"); 32 | producer.send(tm); 33 | 34 | } 35 | 36 | public void setDestination(Destination destination) { 37 | this.destination = destination; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /samples/java-rmi/src/main/java/com/waylau/java/demo/rmi/RmiEchoServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.rmi; 5 | 6 | import java.rmi.RemoteException; 7 | import java.rmi.registry.LocateRegistry; 8 | import java.rmi.registry.Registry; 9 | import java.rmi.server.UnicastRemoteObject; 10 | 11 | /** 12 | * RMI Echo Server. 13 | * 14 | * @since 1.0.0 2020年1月18日 15 | * @author Way Lau 16 | */ 17 | public class RmiEchoServer implements Message { 18 | 19 | @Override 20 | public String echoMessage(String msg) throws RemoteException { 21 | System.out.println("Client -> Server: " + msg); 22 | return msg; 23 | } 24 | 25 | public static void main(String args[]) { 26 | 27 | try { 28 | int port = ServerConstant.PORT; 29 | 30 | RmiEchoServer obj = new RmiEchoServer(); 31 | Message stub = (Message) UnicastRemoteObject.exportObject(obj, 0); 32 | 33 | // 绑定远程对象的stub到注册中心 34 | Registry registry = 35 | LocateRegistry.getRegistry(port); // 如不指定端口,默认使用1099 36 | registry.rebind(ServerConstant.REGIRTRY_NAME, stub); 37 | 38 | System.err.println("RmiEchoServer started on port: " + port); 39 | } catch (Exception e) { 40 | System.err.println("RmiEchoServer exception: " + e.toString()); 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /samples/javase-rest/src/main/java/com/waylau/rest/App.java: -------------------------------------------------------------------------------- 1 | package com.waylau.rest; 2 | 3 | //import org.glassfish.grizzly.http.server.HttpServer; 4 | //import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; 5 | //import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory; 6 | //import org.glassfish.jersey.simple.SimpleContainerFactory; 7 | 8 | import java.io.IOException; 9 | import java.net.URI; 10 | 11 | import org.glassfish.jersey.jetty.JettyHttpContainerFactory; 12 | 13 | /** 14 | * 主应用 15 | * 16 | */ 17 | public class App { 18 | // HTTP server 所要监听的 uri 19 | public static final String BASE_URI = "http://192.168.11.125:8081/"; 20 | 21 | /** 22 | * Main 方法. 23 | * 24 | * @param args 25 | * @throws IOException 26 | */ 27 | public static void main(String[] args) throws IOException { 28 | 29 | // 若使用 Jdk Http Server请去掉下面的注释 30 | // JdkHttpServerFactory.createHttpServer(URI.create(BASE_URI), new 31 | // RestApplication()); 32 | 33 | // 若使用 Grizzly Http Server请去掉下面的注释 34 | // GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), new 35 | // RestApplication()); 36 | 37 | // 若使用 Simple Http Server请去掉下面的注释 38 | // SimpleContainerFactory.create(URI.create(BASE_URI), new 39 | // RestApplication()); 40 | // 若使用 Jetty Http Server请去掉下面的注释 41 | JettyHttpContainerFactory.createServer(URI.create(BASE_URI), 42 | new RestApplication()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/basic.md: -------------------------------------------------------------------------------- 1 | # 基础概念 2 | 3 | ## 概述 4 | 5 | 本书主要讲解的是关于 Java 在分布式系统中的应用。本书的读者假设都具备了 Java 的基础知识。 6 | 如果你需要了解有关 Java 基础知识,可以参阅笔者的另外一本开源书[《Java 编程要点》](https://github.com/waylau/essential-java)。 7 | 8 | ## 分布式系统的概念 9 | 10 | 《分布式系统原理与范型》一书中是这样定义分布式系统的: 11 | 12 | >分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像是单个相关系统。 13 | 14 | 这里面包含了2个含义: 15 | 16 | * 硬件独立:计算机机器本身是独立的 17 | * 软件统一:对于用户来说,他们就像是跟单个系统打交道 18 | 19 | 分布式系统的扩展和升级都比较容易。分布式系统某些节点故障,不影响整理可用。用户和应用程序交互时,不会察觉哪些部分正在替换或者维修,也不会感知到新部分的加入。 20 | 21 | 万维网就是一个分布式文档模型的简单例子。要查看某个文档,用户只需要电机相关的链接即可,文档就会呈现在屏幕上。用户无需关心文档是位于哪个位置,是由什么服务器处理。概念上讲 Web 看起来就是一个单独的服务器。而实际上,Web 在物理上是分布到非常多的服务器上的。 22 | 23 | ## 如何设计分布式系统 24 | 25 | 设计分布式系统的本质就是 26 | 27 | **“如何合理将一个系统拆分成多个子系统部署到不同机器上”** 28 | 29 | 分布式系统的设计应考虑以下几个问题: 30 | 31 | * 系统如何拆分为子系统? 32 | * 如何规划子系统间的通信? 33 | * 如何让子系统可以扩展? 34 | * 通信过程中的安全如何考虑? 35 | * 子系统的可靠性如何保证? 36 | * 数据的一致性是如何实现的? 37 | 38 | 本书就是针对分布式系统中常见的问题进行探讨。 39 | 40 | ## Java 分布式系统 41 | 42 | 上面讲到的都是分布式系统的通用的概念,那么采用 Java 来实现分布式系统有什么好处呢? 43 | 44 | * Java 编程语言是一种通用的、并行的、基于类的、面向对象的语言。它被设计得非常简单,这样程序员可以在该语言上流畅的交流。Java 编程语言与 C 和 C++ 有关联,但组织却截然不同,其中也省略了其他语言的一些用法,比如指针。它的目的是作为一个生产性语言,而不是一个研究性语言,因此,在设计上避免了包括新的和未经考验的功能。更多可以参考[《Java 编程要点》](https://github.com/waylau/essential-java)。 45 | * Java 天然支持分布式应用。 46 | * Java 分布式系统应用广泛,且久经考验,很多大公司比如 Amazon,Linkedin,阿里巴巴等都提供了很多 Java 分布式系统技术方案。 47 | * Java 拥有丰富的中间件框架,避免了很多底层编码的复杂性,帮助你站在巨人的肩膀上。 48 | 49 | 50 | 本书所讲的示例、代码也是基于 Java 语言或者 Java 框架。 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /samples/spark-word-count/src/main/java/com/waylau/spark/JavaWordCount.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spark; 2 | import scala.Tuple2; 3 | 4 | import org.apache.spark.api.java.JavaPairRDD; 5 | import org.apache.spark.api.java.JavaRDD; 6 | import org.apache.spark.sql.SparkSession; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | import java.util.regex.Pattern; 11 | 12 | /** 13 | * 词频统计 14 | * 15 | * @since 1.0.0 2018年5月14日 16 | * @author Way Lau 17 | */ 18 | public final class JavaWordCount { 19 | private static final Pattern SPACE = Pattern.compile(" "); 20 | 21 | public static void main(String[] args) throws Exception { 22 | 23 | if (args.length < 1) { 24 | System.err.println("Usage: JavaWordCount "); 25 | System.exit(1); 26 | } 27 | 28 | SparkSession spark = SparkSession.builder().appName("JavaWordCount").getOrCreate(); 29 | 30 | JavaRDD lines = spark.read().textFile(args[0]).javaRDD(); 31 | 32 | JavaRDD words = lines.flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()); 33 | 34 | JavaPairRDD ones = words.mapToPair(s -> new Tuple2<>(s, 1)); 35 | 36 | JavaPairRDD counts = ones.reduceByKey((i1, i2) -> i1 + i2); 37 | 38 | List> output = counts.collect(); 39 | for (Tuple2 tuple : output) { 40 | System.out.println(tuple._1() + ": " + tuple._2()); 41 | } 42 | spark.stop(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.repository; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | import java.util.concurrent.ConcurrentMap; 7 | import java.util.concurrent.atomic.AtomicLong; 8 | 9 | import org.springframework.stereotype.Repository; 10 | 11 | import com.waylau.spring.cloud.weather.domain.User; 12 | 13 | /** 14 | * 用户资源库. 15 | * 16 | * @version 1.0.0 2017年10月8日 17 | * @author Way Lau 18 | */ 19 | @Repository 20 | public class UserRepositoryImpl implements UserRepository { 21 | 22 | private static AtomicLong counter = new AtomicLong(); 23 | 24 | private final ConcurrentMap userMap = new ConcurrentHashMap(); 25 | 26 | @Override 27 | public User saveOrUpateUser(User user) { 28 | Long id = user.getId(); 29 | if (id == null || id <= 0) { 30 | id = counter.incrementAndGet(); 31 | user.setId(id); 32 | } 33 | this.userMap.put(id, user); 34 | return this.getUserById(id); 35 | } 36 | 37 | @Override 38 | public void deleteUser(Long id) { 39 | this.userMap.remove(id); 40 | } 41 | 42 | @Override 43 | public User getUserById(Long id) { 44 | return this.userMap.get(id); 45 | } 46 | 47 | @Override 48 | public List listUser() { 49 | return new ArrayList(this.userMap.values()); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /samples/eureka-client/src/test/java/com/waylau/spring/cloud/controller/HelloControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.controller; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 12 | import static org.hamcrest.Matchers.equalTo; 13 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 15 | 16 | /** 17 | * HelloController Test. 18 | * 19 | * @since 1.0.0 2017年9月27日 20 | * @author Way Lau 21 | */ 22 | @RunWith(SpringRunner.class) 23 | @SpringBootTest 24 | @AutoConfigureMockMvc 25 | public class HelloControllerTest { 26 | 27 | @Autowired 28 | private MockMvc mockMvc; 29 | 30 | @Test 31 | public void testHello() throws Exception { 32 | mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) 33 | .andExpect(status().isOk()) 34 | .andExpect(content().string(equalTo("Hello World! Welcome to visit waylau.com!"))); 35 | } 36 | } -------------------------------------------------------------------------------- /samples/eureka-server/src/test/java/com/waylau/spring/cloud/controller/HelloControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.controller; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 12 | import static org.hamcrest.Matchers.equalTo; 13 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 15 | 16 | /** 17 | * HelloController Test. 18 | * 19 | * @since 1.0.0 2017年9月27日 20 | * @author Way Lau 21 | */ 22 | @RunWith(SpringRunner.class) 23 | @SpringBootTest 24 | @AutoConfigureMockMvc 25 | public class HelloControllerTest { 26 | 27 | @Autowired 28 | private MockMvc mockMvc; 29 | 30 | @Test 31 | public void testHello() throws Exception { 32 | mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) 33 | .andExpect(status().isOk()) 34 | .andExpect(content().string(equalTo("Hello World! Welcome to visit waylau.com!"))); 35 | } 36 | } -------------------------------------------------------------------------------- /samples/java-ws/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.waylau 7 | java-ws 8 | 1.0.0 9 | jar 10 | 11 | java-ws 12 | https://waylau.com 13 | 14 | 15 | UTF-8 16 | 1.8 17 | ${maven.compiler.source} 18 | 2.3.1 19 | 5.5.2 20 | 21 | 22 | 23 | 24 | maven-compiler-plugin 25 | 3.8.1 26 | 27 | 28 | 29 | 30 | 31 | 32 | javax.xml.ws 33 | jaxws-api 34 | ${jaxws-api.version} 35 | runtime 36 | 37 | 38 | 39 | org.junit.jupiter 40 | junit-jupiter 41 | ${junit.jupiter.version} 42 | test 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.controller; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 12 | import static org.hamcrest.Matchers.equalTo; 13 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 15 | 16 | /** 17 | * HelloController Test. 18 | * 19 | * @since 1.0.0 2017年9月27日 20 | * @author Way Lau 21 | */ 22 | @RunWith(SpringRunner.class) 23 | @SpringBootTest 24 | @AutoConfigureMockMvc 25 | public class HelloControllerTest { 26 | 27 | @Autowired 28 | private MockMvc mockMvc; 29 | 30 | @Test 31 | public void testHello() throws Exception { 32 | mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) 33 | .andExpect(status().isOk()) 34 | .andExpect(content().string(equalTo("Hello World! Welcome to visit waylau.com!"))); 35 | } 36 | } -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.controller; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 12 | import static org.hamcrest.Matchers.equalTo; 13 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 15 | 16 | /** 17 | * HelloController Test. 18 | * 19 | * @since 1.0.0 2017年9月27日 20 | * @author Way Lau 21 | */ 22 | @RunWith(SpringRunner.class) 23 | @SpringBootTest 24 | @AutoConfigureMockMvc 25 | public class HelloControllerTest { 26 | 27 | @Autowired 28 | private MockMvc mockMvc; 29 | 30 | @Test 31 | public void testHello() throws Exception { 32 | mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) 33 | .andExpect(status().isOk()) 34 | .andExpect(content().string(equalTo("Hello World! Welcome to visit waylau.com!"))); 35 | } 36 | } -------------------------------------------------------------------------------- /samples/zk-registry-discovery/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.waylau.spring5 5 | zk-registry-discovery 6 | 1.0.0 7 | zk-registry-discovery 8 | jar 9 | 10 | waylau.com 11 | https://waylau.com 12 | 13 | 14 | 15 | UTF-8 16 | UTF-8 17 | 1.8 18 | 19 | 20 | 21 | 22 | com.101tec 23 | zkclient 24 | 0.10 25 | 26 | 27 | org.springframework 28 | spring-context 29 | 5.0.6.RELEASE 30 | 31 | 32 | com.google.guava 33 | guava 34 | 25.0-jre 35 | 36 | 37 | junit 38 | junit 39 | 4.13.1 40 | test 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/java/com/waylau/axon/cqrs/common/domain/AccountId.java: -------------------------------------------------------------------------------- 1 | package com.waylau.axon.cqrs.common.domain; 2 | 3 | import org.axonframework.common.Assert; 4 | import org.axonframework.common.IdentifierFactory; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Account Id. 10 | * 11 | * @since 1.0.0 2020年1月21日 12 | * @author Way Lau 13 | */ 14 | public class AccountId implements Serializable { 15 | 16 | private static final long serialVersionUID = 7119961474083133148L; 17 | private final String identifier; 18 | 19 | private final int hashCode; 20 | 21 | public AccountId() { 22 | this.identifier = 23 | IdentifierFactory.getInstance().generateIdentifier(); 24 | this.hashCode = identifier.hashCode(); 25 | } 26 | 27 | public AccountId(String identifier) { 28 | Assert.notNull(identifier, ()->"Identifier may not be null"); 29 | this.identifier = identifier; 30 | this.hashCode = identifier.hashCode(); 31 | } 32 | 33 | @Override 34 | public boolean equals(Object o) { 35 | if (this == o) return true; 36 | if (o == null || getClass() != o.getClass()) return false; 37 | 38 | AccountId accountId = (AccountId) o; 39 | 40 | return identifier.equals(accountId.identifier); 41 | 42 | } 43 | 44 | @Override 45 | public int hashCode() { 46 | return hashCode; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return identifier; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /samples/java-concurrency/src/main/java/com/waylau/java/demo/concurrency/Deadlock.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.concurrency; 5 | 6 | /** 7 | * Deadlock. 8 | * 9 | * @since 1.0.0 2020年1月17日 10 | * @author Way Lau 11 | */ 12 | public class Deadlock { 13 | 14 | public static void main(String[] args) { 15 | final Friend alphonse = new Friend("Alphonse"); 16 | final Friend gaston = new Friend("Gaston"); 17 | new Thread(new Runnable() { 18 | public void run() { 19 | alphonse.bow(gaston); 20 | } 21 | }).start(); 22 | 23 | new Thread(new Runnable() { 24 | public void run() { 25 | gaston.bow(alphonse); 26 | } 27 | }).start(); 28 | } 29 | 30 | static class Friend { 31 | private final String name; 32 | 33 | public Friend(String name) { 34 | this.name = name; 35 | } 36 | 37 | public String getName() { 38 | return this.name; 39 | } 40 | 41 | public synchronized void bow(Friend bower) { 42 | System.out.format("%s: %s" + " has bowed to me!%n", 43 | this.name, bower.getName()); 44 | bower.bowBack(this); 45 | } 46 | 47 | public synchronized void bowBack(Friend bower) { 48 | System.out.format("%s: %s" + " has bowed back to me!%n", 49 | this.name, bower.getName()); 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /samples/jersey-rest/src/test/java/com/waylau/jersey/MyResourceTest.java: -------------------------------------------------------------------------------- 1 | package com.waylau.jersey; 2 | 3 | import javax.ws.rs.client.Client; 4 | import javax.ws.rs.client.ClientBuilder; 5 | import javax.ws.rs.client.WebTarget; 6 | 7 | import org.glassfish.grizzly.http.server.HttpServer; 8 | 9 | import org.junit.After; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import static org.junit.Assert.assertEquals; 13 | 14 | public class MyResourceTest { 15 | 16 | private HttpServer server; 17 | private WebTarget target; 18 | 19 | @Before 20 | public void setUp() throws Exception { 21 | // start the server 22 | server = Main.startServer(); 23 | // create the client 24 | Client c = ClientBuilder.newClient(); 25 | 26 | // uncomment the following line if you want to enable 27 | // support for JSON in the client (you also have to uncomment 28 | // dependency on jersey-media-json module in pom.xml and Main.startServer()) 29 | // -- 30 | // c.configuration().enable(new org.glassfish.jersey.media.json.JsonJaxbFeature()); 31 | 32 | target = c.target(Main.BASE_URI); 33 | } 34 | 35 | @After 36 | public void tearDown() throws Exception { 37 | server.stop(); 38 | } 39 | 40 | /** 41 | * Test to see that the message "Got it!" is sent in the response. 42 | */ 43 | @Test 44 | public void testGetIt() { 45 | String responseMsg = target.path("myresource").request().get(String.class); 46 | assertEquals("Got it!", responseMsg); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /samples/jersey-rest/src/main/java/com/waylau/jersey/Main.java: -------------------------------------------------------------------------------- 1 | package com.waylau.jersey; 2 | 3 | import org.glassfish.grizzly.http.server.HttpServer; 4 | import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; 5 | import org.glassfish.jersey.server.ResourceConfig; 6 | 7 | import java.io.IOException; 8 | import java.net.URI; 9 | 10 | /** 11 | * Main class. 12 | * 13 | */ 14 | public class Main { 15 | // Base URI the Grizzly HTTP server will listen on 16 | public static final String BASE_URI = "http://localhost:8080/myapp/"; 17 | 18 | /** 19 | * Starts Grizzly HTTP server exposing JAX-RS resources defined in this application. 20 | * @return Grizzly HTTP server. 21 | */ 22 | public static HttpServer startServer() { 23 | // create a resource config that scans for JAX-RS resources and providers 24 | // in com.waylau.jersey package 25 | final ResourceConfig rc = new ResourceConfig().packages("com.waylau.jersey"); 26 | 27 | // create and start a new instance of grizzly http server 28 | // exposing the Jersey application at BASE_URI 29 | return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc); 30 | } 31 | 32 | /** 33 | * Main method. 34 | * @param args 35 | * @throws IOException 36 | */ 37 | public static void main(String[] args) throws IOException { 38 | final HttpServer server = startServer(); 39 | System.out.println(String.format("Jersey app started with WADL available at " 40 | + "%sapplication.wadl\nHit enter to stop it...", BASE_URI)); 41 | System.in.read(); 42 | server.stop(); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /samples/eureka-server/build.gradle: -------------------------------------------------------------------------------- 1 | // buildscript 代码块中脚本优先执行 2 | buildscript { 3 | 4 | // ext 用于定义动态属性 5 | ext { 6 | springBootVersion = '2.0.0.RELEASE' 7 | } 8 | 9 | // 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库) 10 | repositories { 11 | //mavenCentral() 12 | maven { url "https://repo.spring.io/snapshot" } 13 | maven { url "https://repo.spring.io/milestone" } 14 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } 15 | } 16 | 17 | // 依赖关系 18 | dependencies { 19 | 20 | // classpath 声明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项 21 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 22 | } 23 | } 24 | 25 | // 使用插件 26 | apply plugin: 'java' 27 | apply plugin: 'eclipse' 28 | apply plugin: 'org.springframework.boot' 29 | apply plugin: 'io.spring.dependency-management' 30 | 31 | // 指定了生成的编译文件的版本,默认是打成了 jar 包 32 | group = 'com.waylau.spring.cloud' 33 | version = '1.0.0' 34 | 35 | // 指定编译 .java 文件的 JDK 版本 36 | sourceCompatibility = 1.8 37 | 38 | // 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库) 39 | repositories { 40 | //mavenCentral() 41 | maven { url "https://repo.spring.io/snapshot" } 42 | maven { url "https://repo.spring.io/milestone" } 43 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } 44 | } 45 | 46 | ext { 47 | springCloudVersion = 'Finchley.M9' 48 | } 49 | 50 | dependencies { 51 | 52 | // 添加 Spring Cloud Netflix Eureka Server 依赖 53 | compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server') 54 | 55 | // 该依赖用于测试阶段 56 | testCompile('org.springframework.boot:spring-boot-starter-test') 57 | } 58 | 59 | dependencyManagement { 60 | imports { 61 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /samples/hello-world-docker/build.gradle: -------------------------------------------------------------------------------- 1 | // buildscript 代码块中脚本优先执行 2 | buildscript { 3 | 4 | // ext 用于定义动态属性 5 | ext { 6 | springBootVersion = '2.0.0.M4' 7 | } 8 | 9 | // 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库) 10 | repositories { 11 | //mavenCentral() 12 | maven { url "https://repo.spring.io/snapshot" } 13 | maven { url "https://repo.spring.io/milestone" } 14 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } 15 | } 16 | 17 | // 依赖关系 18 | dependencies { 19 | 20 | // classpath 声明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项 21 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 22 | 23 | classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.17.2') 24 | } 25 | } 26 | 27 | // 使用插件 28 | apply plugin: 'java' 29 | apply plugin: 'eclipse' 30 | apply plugin: 'org.springframework.boot' 31 | apply plugin: 'io.spring.dependency-management' 32 | 33 | apply plugin: 'com.palantir.docker' 34 | 35 | // 指定了生成的编译文件的版本,默认是打成了 jar 包 36 | group = 'com.waylau.spring.cloud' 37 | version = '1.0.0' 38 | 39 | // 指定编译 .java 文件的 JDK 版本 40 | sourceCompatibility = 1.8 41 | 42 | docker { 43 | name "${project.group}/${jar.baseName}" 44 | files jar.archivePath 45 | buildArgs(['JAR_FILE': "${jar.archiveName}"]) 46 | } 47 | 48 | // 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库) 49 | repositories { 50 | //mavenCentral() 51 | maven { url "https://repo.spring.io/snapshot" } 52 | maven { url "https://repo.spring.io/milestone" } 53 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } 54 | } 55 | 56 | // 依赖关系 57 | dependencies { 58 | 59 | // 该依赖用于编译阶段 60 | compile('org.springframework.boot:spring-boot-starter-web') 61 | 62 | // 该依赖用于测试阶段 63 | testCompile('org.springframework.boot:spring-boot-starter-test') 64 | } 65 | -------------------------------------------------------------------------------- /samples/security-basic/dependency-reduced-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.waylau.spring 5 | security-basic 6 | security-basic 7 | 1.0.0 8 | 9 | waylau.com 10 | https://waylau.com 11 | 12 | 13 | 14 | 15 | maven-shade-plugin 16 | 3.6.0 17 | 18 | 19 | package 20 | 21 | shade 22 | 23 | 24 | 25 | 26 | com.waylau.spring.mvc.Application 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | spring-snapshots 38 | Spring Snapshots 39 | https://repo.spring.io/snapshot 40 | 41 | 42 | 43 | 5.2.15.RELEASE 44 | 5.1.5.RELEASE 45 | 9.4.14.v20181114 46 | 2.9.7 47 | 48 | 49 | -------------------------------------------------------------------------------- /samples/eureka-client/build.gradle: -------------------------------------------------------------------------------- 1 | // buildscript 代码块中脚本优先执行 2 | buildscript { 3 | 4 | // ext 用于定义动态属性 5 | ext { 6 | springBootVersion = '2.0.0.RELEASE' 7 | } 8 | 9 | // 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库) 10 | repositories { 11 | //mavenCentral() 12 | maven { url "https://repo.spring.io/snapshot" } 13 | maven { url "https://repo.spring.io/milestone" } 14 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } 15 | } 16 | 17 | // 依赖关系 18 | dependencies { 19 | 20 | // classpath 声明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项 21 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 22 | } 23 | } 24 | 25 | // 使用插件 26 | apply plugin: 'java' 27 | apply plugin: 'eclipse' 28 | apply plugin: 'org.springframework.boot' 29 | apply plugin: 'io.spring.dependency-management' 30 | 31 | // 指定了生成的编译文件的版本,默认是打成了 jar 包 32 | group = 'com.waylau.spring.cloud' 33 | version = '1.0.0' 34 | 35 | // 指定编译 .java 文件的 JDK 版本 36 | sourceCompatibility = 1.8 37 | 38 | // 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库) 39 | repositories { 40 | //mavenCentral() 41 | maven { url "https://repo.spring.io/snapshot" } 42 | maven { url "https://repo.spring.io/milestone" } 43 | maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } 44 | } 45 | 46 | ext { 47 | springCloudVersion = 'Finchley.M9' 48 | } 49 | 50 | dependencies { 51 | 52 | // 添加 Spring Cloud Starter Netflix Eureka Client 依赖 53 | compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') 54 | 55 | compile('org.springframework.boot:spring-boot-starter-web') 56 | 57 | // 该依赖用于测试阶段 58 | testCompile('org.springframework.boot:spring-boot-starter-test') 59 | } 60 | 61 | dependencyManagement { 62 | imports { 63 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /samples/zk-registry-discovery/src/main/java/com/waylau/zk/registry/ZkServiceRegistry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.zk.registry; 5 | 6 | import org.I0Itec.zkclient.ZkClient; 7 | 8 | import com.waylau.zk.Constant; 9 | 10 | /** 11 | * ZK Service Registry. 12 | * 13 | * @since 1.0.0 2018年5月16日 14 | * @author Way Lau 15 | */ 16 | public class ZkServiceRegistry implements ServiceRegistry { 17 | 18 | /** 19 | * ZK 地址. 20 | */ 21 | private String zkAddress = "localhost"; 22 | 23 | /** 24 | * ZK 客户端. 25 | */ 26 | private ZkClient zkClient; 27 | 28 | public void init() { 29 | zkClient = new ZkClient(zkAddress, 30 | Constant.ZK_SESSION_TIMEOUT, 31 | Constant.ZK_CONNECTION_TIMEOUT); 32 | 33 | System.out.println(">>>connect to zookeeper"); 34 | } 35 | 36 | @Override 37 | public void registry(String serviceName, String serviceAddress) { 38 | // 创建registry节点(持久) 39 | String registryPath = Constant.ZK_REGISTRY; 40 | if (!zkClient.exists(registryPath)) { 41 | zkClient.createPersistent(registryPath); 42 | 43 | System.out.println(">>>create registry node:" + registryPath); 44 | } 45 | 46 | // 创建service节点(持久) 47 | String servicePath = registryPath + "/" + serviceName; 48 | if (!zkClient.exists(servicePath)) { 49 | zkClient.createPersistent(servicePath); 50 | System.out.println(">>>create service node:" + servicePath); 51 | } 52 | 53 | // 创建address节点(临时) 54 | String addressPath = servicePath + "/address-"; 55 | String addressNode = zkClient.createEphemeralSequential(addressPath, serviceAddress); 56 | 57 | System.out.println(">>>create address node:" + addressNode); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/java/com/waylau/axon/cqrs/Application.java: -------------------------------------------------------------------------------- 1 | package com.waylau.axon.cqrs; 2 | 3 | 4 | import static org.slf4j.LoggerFactory.getLogger; 5 | 6 | import org.axonframework.config.Configuration; 7 | import org.axonframework.config.DefaultConfigurer; 8 | import org.axonframework.eventsourcing.eventstore.inmemory.InMemoryEventStorageEngine; 9 | import org.slf4j.Logger; 10 | 11 | import com.waylau.axon.cqrs.command.aggregates.BankAccount; 12 | import com.waylau.axon.cqrs.command.commands.CreateAccountCommand; 13 | import com.waylau.axon.cqrs.command.commands.WithdrawMoneyCommand; 14 | import com.waylau.axon.cqrs.common.domain.AccountId; 15 | 16 | /** 17 | * 主应用入口. 18 | * 19 | * @since 1.0.0 2020年1月21日 20 | * @author Way Lau 21 | */ 22 | public class Application { 23 | private static final Logger LOGGER = getLogger(Application.class); 24 | 25 | public static void main(String args[]) throws InterruptedException{ 26 | LOGGER.info("Application is start."); 27 | Configuration config = DefaultConfigurer.defaultConfiguration() 28 | .configureAggregate(BankAccount.class) 29 | .configureEmbeddedEventStore(c -> 30 | new InMemoryEventStorageEngine()) 31 | .buildConfiguration(); 32 | config.start(); 33 | AccountId id = new AccountId(); 34 | config.commandGateway().send(new CreateAccountCommand(id, 35 | "MyAccount",1000)); 36 | config.commandGateway().send(new WithdrawMoneyCommand(id, 500)); 37 | config.commandGateway().send(new WithdrawMoneyCommand(id, 500)); 38 | config.commandGateway().send(new WithdrawMoneyCommand(id, 500)); 39 | 40 | // 线程先睡五秒,等事件处理完 41 | Thread.sleep(5000L); 42 | 43 | LOGGER.info("Application is shutdown."); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /samples/spring-rest/src/main/java/com/waylau/spring/mvc/JettyServer.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc; 2 | 3 | import org.eclipse.jetty.server.Server; 4 | import org.eclipse.jetty.servlet.ServletContextHandler; 5 | import org.eclipse.jetty.servlet.ServletHolder; 6 | import org.springframework.web.context.ContextLoaderListener; 7 | import org.springframework.web.context.WebApplicationContext; 8 | import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 9 | import org.springframework.web.servlet.DispatcherServlet; 10 | 11 | import com.waylau.spring.mvc.configuration.AppConfiguration; 12 | 13 | /** 14 | * Jetty Server. 15 | * 16 | * @since 1.0.0 2018年3月21日 17 | * @author Way Lau 18 | */ 19 | public class JettyServer { 20 | private static final int DEFAULT_PORT = 8080; 21 | private static final String CONTEXT_PATH = "/"; 22 | private static final String MAPPING_URL = "/*"; 23 | 24 | public void run() throws Exception { 25 | Server server = new Server(DEFAULT_PORT); 26 | server.setHandler(servletContextHandler(webApplicationContext())); 27 | server.start(); 28 | server.join(); 29 | } 30 | 31 | private ServletContextHandler servletContextHandler(WebApplicationContext context) { 32 | ServletContextHandler handler = new ServletContextHandler(); 33 | handler.setContextPath(CONTEXT_PATH); 34 | handler.addServlet(new ServletHolder(new DispatcherServlet(context)), MAPPING_URL); 35 | handler.addEventListener(new ContextLoaderListener(context)); 36 | return handler; 37 | } 38 | 39 | private WebApplicationContext webApplicationContext() { 40 | AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); 41 | context.register(AppConfiguration.class); 42 | return context; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc.configuration; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 7 | import org.springframework.security.core.userdetails.User; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 10 | 11 | /** 12 | * Web Security Configuration. 13 | * 14 | * @since 1.0.0 2018年3月21日 15 | * @author Way Lau 16 | */ 17 | @EnableWebSecurity // 启用Spring Security功能 18 | public class WebSecurityConfig 19 | extends WebSecurityConfigurerAdapter { 20 | 21 | /** 22 | * 自定义配置 23 | */ 24 | @Override 25 | protected void configure(HttpSecurity http) throws Exception { 26 | http.authorizeRequests().anyRequest().authenticated()//所有请求都需认证 27 | .and() 28 | .formLogin() // 使用form表单登录 29 | .and() 30 | .httpBasic(); // HTTP基本认证 31 | } 32 | 33 | @SuppressWarnings("deprecation") 34 | @Bean 35 | @Override 36 | public UserDetailsService userDetailsService() { 37 | InMemoryUserDetailsManager manager = 38 | new InMemoryUserDetailsManager(); 39 | 40 | manager.createUser( 41 | User.withDefaultPasswordEncoder() // 密码编码器 42 | .username("waylau") // 用户名 43 | .password("123") // 密码 44 | .roles("USER") // 角色 45 | .build() 46 | ); 47 | return manager; 48 | } 49 | } -------------------------------------------------------------------------------- /samples/jms-msg/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.waylau.spring5 5 | jms-msg 6 | 1.0.0 7 | jms-msg 8 | jar 9 | 10 | waylau.com 11 | https://waylau.com 12 | 13 | 14 | 15 | UTF-8 16 | 5.2.3.RELEASE 17 | 4.13.1 18 | 5.15.11 19 | 20 | 21 | 22 | 23 | junit 24 | junit 25 | ${junit.version} 26 | test 27 | 28 | 29 | org.apache.activemq 30 | activemq-all 31 | ${activemq.version} 32 | 33 | 34 | org.springframework 35 | spring-core 36 | ${spring.version} 37 | 38 | 39 | org.springframework 40 | spring-aop 41 | ${spring.version} 42 | 43 | 44 | org.springframework 45 | spring-jms 46 | ${spring.version} 47 | 48 | 49 | org.springframework 50 | spring-test 51 | ${spring.version} 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /samples/java-io-mode/src/main/java/com/waylau/java/demo/net/BlockingEchoServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.net; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.PrintWriter; 10 | import java.net.ServerSocket; 11 | import java.net.Socket; 12 | 13 | /** 14 | * Blocking Echo Server. 15 | * 16 | * @since 1.0.0 2019年9月28日 17 | * @author Way Lau 18 | */ 19 | public class BlockingEchoServer { 20 | 21 | public static int DEFAULT_PORT = 7; 22 | 23 | /** 24 | * @param args 25 | */ 26 | public static void main(String[] args) { 27 | 28 | int port; 29 | 30 | try { 31 | port = Integer.parseInt(args[0]); 32 | } catch (RuntimeException ex) { 33 | port = DEFAULT_PORT; 34 | } 35 | 36 | ServerSocket serverSocket = null; 37 | try { 38 | // 服务器监听 39 | serverSocket = new ServerSocket(port); 40 | System.out.println( 41 | "BlockingEchoServer已启动,端口:" + port); 42 | 43 | } catch (IOException e) { 44 | System.out.println( 45 | "BlockingEchoServer启动异常,端口:" + port); 46 | System.out.println(e.getMessage()); 47 | } 48 | 49 | // Java 7 try-with-resource语句 50 | try ( 51 | // 接受客户端建立链接,生成Socket实例 52 | Socket clientSocket = serverSocket.accept(); 53 | PrintWriter out = 54 | new PrintWriter(clientSocket.getOutputStream(), true); 55 | 56 | // 接收客户端的信息 57 | BufferedReader in = 58 | new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));) { 59 | String inputLine; 60 | while ((inputLine = in.readLine()) != null) { 61 | 62 | // 发送信息给客户端 63 | out.println(inputLine); 64 | System.out.println( 65 | "BlockingEchoServer -> " + clientSocket.getRemoteSocketAddress() + ":" + inputLine); 66 | } 67 | } catch (IOException e) { 68 | System.out.println( 69 | "BlockingEchoServer异常!" + e.getMessage()); 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /samples/java-io-mode/src/main/java/com/waylau/java/demo/net/BlockingEchoClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.net; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.PrintWriter; 10 | import java.net.Socket; 11 | import java.net.UnknownHostException; 12 | 13 | /** 14 | * Blocking Echo Client. 15 | * 16 | * @since 1.0.0 2019年9月28日 17 | * @author Way Lau 18 | */ 19 | public class BlockingEchoClient { 20 | 21 | /** 22 | * @param args 23 | */ 24 | public static void main(String[] args) { 25 | if (args.length != 2) { 26 | System.err.println( 27 | "用法: java BlockingEchoClient "); 28 | System.exit(1); 29 | } 30 | 31 | String hostName = args[0]; 32 | int portNumber = Integer.parseInt(args[1]); 33 | 34 | try ( 35 | Socket echoSocket = new Socket(hostName, portNumber); 36 | PrintWriter out = 37 | new PrintWriter(echoSocket.getOutputStream(), true); 38 | BufferedReader in = 39 | new BufferedReader( 40 | new InputStreamReader(echoSocket.getInputStream())); 41 | BufferedReader stdIn = 42 | new BufferedReader( 43 | new InputStreamReader(System.in)) 44 | ) { 45 | String userInput; 46 | while ((userInput = stdIn.readLine()) != null) { 47 | out.println(userInput); 48 | System.out.println("echo: " + in.readLine()); 49 | } 50 | } catch (UnknownHostException e) { 51 | System.err.println("不明主机,主机名为: " + hostName); 52 | System.exit(1); 53 | } catch (IOException e) { 54 | System.err.println("不能从主机中获取I/O,主机名为:" + 55 | hostName); 56 | System.exit(1); 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /samples/cxf-rest/src/test/java/com/waylau/cxf/HelloWorldIT.java: -------------------------------------------------------------------------------- 1 | package com.waylau.cxf; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.io.InputStream; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import javax.ws.rs.core.Response; 10 | 11 | import org.apache.cxf.helpers.IOUtils; 12 | import org.apache.cxf.jaxrs.client.WebClient; 13 | import org.codehaus.jackson.JsonParser; 14 | import org.codehaus.jackson.map.MappingJsonFactory; 15 | import org.junit.BeforeClass; 16 | import org.junit.Test; 17 | 18 | public class HelloWorldIT { 19 | private static String endpointUrl; 20 | 21 | @BeforeClass 22 | public static void beforeClass() { 23 | endpointUrl = System.getProperty("service.url"); 24 | } 25 | 26 | @Test 27 | public void testPing() throws Exception { 28 | WebClient client = 29 | WebClient.create(endpointUrl + "/hello/echo/SierraTangoNevada"); 30 | Response r = client.accept("text/plain").get(); 31 | assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); 32 | String value = IOUtils.toString((InputStream)r.getEntity()); 33 | assertEquals("SierraTangoNevada", value); 34 | } 35 | 36 | @Test 37 | public void testJsonRoundtrip() throws Exception { 38 | List providers = new ArrayList<>(); 39 | providers.add(new org.codehaus.jackson.jaxrs.JacksonJsonProvider()); 40 | JsonBean inputBean = new JsonBean(); 41 | inputBean.setVal1("Maple"); 42 | WebClient client = 43 | WebClient.create(endpointUrl + "/hello/jsonBean", providers); 44 | Response r = client.accept("application/json") 45 | .type("application/json") 46 | .post(inputBean); 47 | assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); 48 | MappingJsonFactory factory = new MappingJsonFactory(); 49 | JsonParser parser = factory.createJsonParser((InputStream)r.getEntity()); 50 | JsonBean output = parser.readValueAs(JsonBean.class); 51 | assertEquals("Maple", output.getVal2()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /samples/spring-rest/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.waylau.spring 6 | spring-rest 7 | 1.0.0 8 | spring-rest 9 | jar 10 | 11 | waylau.com 12 | https://waylau.com 13 | 14 | 15 | 16 | UTF-8 17 | 5.1.0.RELEASE 18 | 9.4.10.v20180503 19 | 2.10.2 20 | 21 | 22 | 23 | org.springframework 24 | spring-webmvc 25 | ${spring.version} 26 | 27 | 28 | org.eclipse.jetty 29 | jetty-servlet 30 | ${jetty.version} 31 | provided 32 | 33 | 34 | com.fasterxml.jackson.core 35 | jackson-core 36 | ${jackson.version} 37 | 38 | 39 | com.fasterxml.jackson.core 40 | jackson-databind 41 | ${jackson.version} 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | 51 | 52 | maven-compiler-plugin 53 | 54 | 3.7.0 55 | 56 | 1.8 57 | 1.8 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /samples/jms-msg/src/main/java/com/waylau/spring/jms/queue/ProducerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms.queue; 2 | 3 | import javax.jms.Destination; 4 | import javax.jms.JMSException; 5 | import javax.jms.Message; 6 | import javax.jms.Session; 7 | import javax.jms.TextMessage; 8 | 9 | import org.springframework.jms.core.JmsTemplate; 10 | import org.springframework.jms.core.MessageCreator; 11 | 12 | /** 13 | * Producer Service. 14 | * 15 | * @since 1.0.0 2018年4月15日 16 | * @author Way Lau 17 | */ 18 | public class ProducerServiceImpl implements ProducerService { 19 | 20 | private JmsTemplate jmsTemplate; 21 | 22 | /** 23 | * 向指定队列发送消息 24 | */ 25 | public void sendMessage(Destination destination, final String msg) { 26 | System.out.println("ProducerService向队列" 27 | + destination.toString() + "发送了消息:\t" + msg); 28 | jmsTemplate.send(destination, new MessageCreator() { 29 | public Message createMessage(Session session) throws JMSException { 30 | return session.createTextMessage(msg); 31 | } 32 | }); 33 | } 34 | 35 | /** 36 | * 向默认队列发送消息 37 | */ 38 | public void sendMessage(final String msg) { 39 | String destination = jmsTemplate.getDefaultDestination().toString(); 40 | System.out.println("ProducerService向队列" 41 | + destination + "发送了消息:\t" + msg); 42 | jmsTemplate.send(new MessageCreator() { 43 | public Message createMessage(Session session) throws JMSException { 44 | return session.createTextMessage(msg); 45 | } 46 | }); 47 | 48 | } 49 | 50 | public void sendMessage(Destination destination, 51 | final String msg, final Destination response) { 52 | System.out.println("ProducerService向队列" 53 | + destination + "发送了消息:\t" + msg); 54 | jmsTemplate.send(destination, new MessageCreator() { 55 | public Message createMessage(Session session) throws JMSException { 56 | TextMessage textMessage = session.createTextMessage(msg); 57 | textMessage.setJMSReplyTo(response); 58 | return textMessage; 59 | } 60 | }); 61 | } 62 | 63 | public void setJmsTemplate(JmsTemplate jmsTemplate) { 64 | this.jmsTemplate = jmsTemplate; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /samples/java-io-mode/src/main/java/com/waylau/java/demo/nio/NonBlockingEchoClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.nio; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.net.InetSocketAddress; 10 | import java.net.UnknownHostException; 11 | import java.nio.ByteBuffer; 12 | import java.nio.channels.SocketChannel; 13 | 14 | /** 15 | * Non Blocking Echo Client. 16 | * 17 | * @since 1.0.0 2019年9月28日 18 | * @author Way Lau 19 | */ 20 | public class NonBlockingEchoClient { 21 | 22 | /** 23 | * @param args 24 | */ 25 | public static void main(String[] args) { 26 | if (args.length != 2) { 27 | System.err.println("用法: java NonBlockingEchoClient "); 28 | System.exit(1); 29 | } 30 | 31 | String hostName = args[0]; 32 | int portNumber = Integer.parseInt(args[1]); 33 | 34 | SocketChannel socketChannel = null; 35 | try { 36 | socketChannel = SocketChannel.open(); 37 | socketChannel.connect(new InetSocketAddress(hostName, portNumber)); 38 | } catch (IOException e) { 39 | System.err.println("NonBlockingEchoClient异常: " + e.getMessage()); 40 | System.exit(1); 41 | } 42 | 43 | ByteBuffer writeBuffer = ByteBuffer.allocate(32); 44 | ByteBuffer readBuffer = ByteBuffer.allocate(32); 45 | 46 | try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { 47 | String userInput; 48 | while ((userInput = stdIn.readLine()) != null) { 49 | writeBuffer.put(userInput.getBytes()); 50 | writeBuffer.flip(); 51 | writeBuffer.rewind(); 52 | 53 | // 写消息到管道 54 | socketChannel.write(writeBuffer); 55 | 56 | // 管道读消息 57 | socketChannel.read(readBuffer); 58 | 59 | // 清理缓冲区 60 | writeBuffer.clear(); 61 | readBuffer.clear(); 62 | System.out.println("echo: " + userInput); 63 | } 64 | } catch (UnknownHostException e) { 65 | System.err.println("不明主机,主机名为: " + hostName); 66 | System.exit(1); 67 | } catch (IOException e) { 68 | System.err.println("不能从主机中获取I/O,主机名为:" + hostName); 69 | System.exit(1); 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /docs/jms.md: -------------------------------------------------------------------------------- 1 | # JMS 2 | 3 | Java Message Service (JMS) API是一个 Java 面向消息中间件的 API,用于两个或者多个客户端之间发送消息。 4 | 5 | JMS 的目标包括: 6 | 7 | * 包含实现复杂企业应用所需要的功能特性; 8 | * 定义了企业消息概念和功能的一组通用集合; 9 | * 最小化这些 Java 程序员必须学习以使用企业消息产品的概念集合; 10 | * 最大化消息应用的可移植性。 11 | 12 | JMS 支持企业消息产品提供两种主要的消息风格: 13 | 14 | * 点对点(Point-to-Point,PTP)消息风格:允许一个客户端通过一个叫“队列(queue)”的中间抽象发送一个消息给另一个客户端。发送消息的客户端将一个消息发送到指定的队列中,接收消息的客户端从这个队列中抽取消息。 15 | * 发布订阅(Publish/Subscribe,Pub/Sub)消息风:则允许一个客户端通过一个叫“主题(topic)”的中间抽象发送一个消息给多个客户端。发送消息的客户端将一个消息发布到指定的主题中,然后这个消息将被投递到所有订阅了这个主题的客户端。 16 | 17 | ### JMS API 18 | 19 | 由于历史的原因,JMS 提供四组用于发送和接收消息的接口。 20 | 21 | * JMS1.0 定义了两个特定领域相关的API,一个用于点对点的消息处理(queue),一个用于发布订阅的消息处理(topic)。尽管由于向后兼容的理由这些接口一直被保留在 JMS 中,但是在以后的 API 中应该考虑被废弃掉。 22 | * JMS1.1 引入了一个新的统一的一组 API,可以同时用于点对点和发布订阅消息模式。这也被称作标准(standard) API。 23 | * JMS2.0引入了一组简化 API,它拥有标准 API 的全部特性,同时接口更少、使用更方便。 24 | 25 | 以上每组 API 提供一组不同的接口集合,用于连接到 JMS 提供者、发送和接收消息。因此,它们共享一组代表消息、消息目的地和其他各方面功能特性的通用接口。 26 | 27 | 下面是使用标准 API 来发送信息的例子: 28 | 29 | ```java 30 | @Resource(lookup = "jms/connectionFactory ") 31 | ConnectionFactory connectionFactory; 32 | 33 | @Resource(lookup="jms/inboundQueue") 34 | Queue inboundQueue; 35 | 36 | public void sendMessageOld (String payload) throws JMSException{ 37 | try (Connection connection = connectionFactory.createConnection()) { 38 | Session session = connection.createSession(); 39 | MessageProducer messageProducer = 40 | session.createProducer(inboundQueue); 41 | TextMessage textMessage = 42 | session.createTextMessage(payload); 43 | messageProducer.send(textMessage); 44 | } 45 | } 46 | ``` 47 | 48 | 下面是使用简化 API 来发送信息的例子: 49 | 50 | ```java 51 | @Resource(lookup = "jms/connectionFactory") 52 | ConnectionFactory connectionFactory; 53 | 54 | @Resource(lookup="jms/inboundQueue") 55 | Queue inboundQueue; 56 | 57 | public void sendMessageNew (String payload) { 58 | try (MessagingContext context = connectionFactory.createMessagingContext();){ 59 | context.send(inboundQueue,payload); 60 | } 61 | } 62 | ``` 63 | 64 | 所有的接口都在 [javax.jms](http://docs.oracle.com/javaee/7/api/javax/jms/package-summary.html) 包下。 65 | 66 | 如果读者想了解更多有关 JMS 的规范,可以在线查阅 。 -------------------------------------------------------------------------------- /samples/java-io-mode/src/main/java/com/waylau/java/demo/aio/AsyncEchoClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.aio; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.net.InetSocketAddress; 10 | import java.net.UnknownHostException; 11 | import java.nio.ByteBuffer; 12 | import java.nio.channels.AsynchronousSocketChannel; 13 | 14 | /** 15 | * Async Echo Client. 16 | * 17 | * @since 1.0.0 2019年9月30日 18 | * @author Way Lau 19 | */ 20 | public class AsyncEchoClient { 21 | 22 | /** 23 | * @param args 24 | */ 25 | public static void main(String[] args) { 26 | if (args.length != 2) { 27 | System.err.println("用法: java AsyncEchoClient "); 28 | System.exit(1); 29 | } 30 | 31 | String hostName = args[0]; 32 | int portNumber = Integer.parseInt(args[1]); 33 | 34 | AsynchronousSocketChannel socketChannel = null; 35 | try { 36 | socketChannel = AsynchronousSocketChannel.open(); 37 | socketChannel.connect(new InetSocketAddress(hostName, portNumber)); 38 | } catch (IOException e) { 39 | System.err.println("AsyncEchoClient异常: " + e.getMessage()); 40 | System.exit(1); 41 | } 42 | 43 | ByteBuffer writeBuffer = ByteBuffer.allocate(32); 44 | ByteBuffer readBuffer = ByteBuffer.allocate(32); 45 | 46 | try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { 47 | String userInput; 48 | while ((userInput = stdIn.readLine()) != null) { 49 | writeBuffer.put(userInput.getBytes()); 50 | writeBuffer.flip(); 51 | writeBuffer.rewind(); 52 | 53 | // 写消息到管道 54 | socketChannel.write(writeBuffer); 55 | 56 | // 管道读消息 57 | socketChannel.read(readBuffer); 58 | 59 | // 清理缓冲区 60 | writeBuffer.clear(); 61 | readBuffer.clear(); 62 | System.out.println("echo: " + userInput); 63 | } 64 | } catch (UnknownHostException e) { 65 | System.err.println("不明主机,主机名为: " + hostName); 66 | System.exit(1); 67 | } catch (IOException e) { 68 | System.err.println("不能从主机中获取I/O,主机名为:" + hostName); 69 | System.exit(1); 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /docs/rmi-overview.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | 在基于对象的分布式系统中,对象的概念在分布式实现中起着极其关键的作用。从原理上来讲,所有的一切都被作为对象抽象出来,而客户端将以调用对象的方式来获得服务和资源。 4 | 5 | 分布式对象之所以成为重要的范型,是因为它相对比较容易的把分布的特性隐藏在对象接口后面。此外,因为对象实际上可以是任何事务,所以它也是构建系统的强大范型。 6 | 7 | 面向对象技术于20世纪80年代开始用于开发分布式系统。同样,在达到高度分布式透明性的同时,通过远程服务器宿主独立对象的理念构成了开发新一代分布式系统的稳固的基础。在本节中,我们将看到基于对象的分布式系统的常用体系结构。 8 | 9 | ## 分布式对象 10 | 11 | 软件世界中的对象和现实世界中的对象类似,对象存储状态在字段(field)里,而通过方法(methods)暴露其行为。方法对对象的内部状态进行操作,并作为对象与对象之间通信主要机制。隐藏对象内部状态,通过方法进行所有的交互,这个面向对象编程的一个基本原则——数据封装(data encapsulation)。可以通过接口(interface)来使用方法。一个对象可能实现多个接口,而给定的一个接口定义,可能有多个对象为其提供实现。 12 | 13 | 把接口与实现这些接口的对象进行分隔开,对于分布式系统是至关重要的。严格的隔离允许我们把接口放在一台机器上,而使对象本身驻留在另外一台机器上。这种组织通常称为分布式对象(distributed object)。 14 | 15 | ![带有客户端代理的远程对象的常见组织](../images/distributed-object.jpg) 16 | 17 | (注:该图片引用自《分布式系统原理与范式》一书) 18 | 19 | 当客户绑定(bind)到一个分布式对象时,就会把这个对象的接口的实现——称为代理(proxy)——加载近客户的地址空间中。代理类似于 RPC 系统中的客户存根(client stub)。它所做的事,是把方法调用编组进消息中,以及对应答消息进行解组,把方法调用的结果返回给客户。实际的对象驻留在服务器计算机上,它在这里提供了与它在客户机上提供的相同的接口。进入的调用请求首先被传递给服务器存根,服务器存根对它们进行解码,在服务器中的对象接口上进行方法的调用。服务器存根还负责对应答进行编码,并把应答消息转发给客户端代理。 20 | 21 | 服务器端存根通常被称为骨架(skeleton),因为它提供了明确的方式,允许服务器中间件来访问用户定义的对象。实际上,它通常以特定于语言的类的形式包含不完整的代码,需要开发人员来对一步对其进行特殊化处理。 22 | 23 | 大多数分布式对象的一个特性是它们的状态不是分布式的。状态驻留在单台机器上。在其他机器上,智能地使用被对象实现的接口。这样的对象也被称为远程对象(remote object)。分布式对象的状态本身可能物理地分布在多台机器上,但是这种分布对于对象接口背后的客户来说是透明的。 24 | 25 | ## Java RMI 26 | 27 | 目前,常用的分布式对象常用技术有微软 DCOM(COM+)、CORBA 以及 Java RMI 等。 28 | 29 | 30 | CORBA 旨在提供一组全面的服务来管理在异构环境中(不同语言、操作系统、网络)的对象。Java 在其最初只支持通过 socket 来实现分布式通信。1995年,作为 Java 的缔造者,Sun 公司开始创建一个 Java 的扩展,称为 Java RMI(Remote Method Invocation,远程方法调用)。Java RMI 允许程序员创建分布式应用程序时,可以从其他 Java 虚拟机(JVM)调用远程对象的方法。 31 | 32 | 一旦应用程序(客户端)引用了远程对象,就可以进行远程调用了。这是通过 RMI 提供的命名服务(RMI 注册中心)来查找远程对象,来接收作为返回值的引用。Java RMI 在概念上类似于 RPC,但能在不同地址空间支持对象调用的语义。 33 | 34 | 与大多数其他诸如 CORBA 的 RPC 系统不同,RMI 只支持基于 Java 来构建,但也正是这个原因, RMI 对于语言来说更加整洁,无需做额外的数据序列化工作。Java RMI 的设计目标应该是: 35 | 36 | * 能够适应语言、集成到语言、易于使用; 37 | * 支持无缝的远程调用对象; 38 | * 支持服务器到 applet 的回调; 39 | * 保障 Java 对象的安全环境; 40 | * 支持分布式垃圾回收; 41 | * 支持多种传输。 42 | 43 | 44 | 分布式对象模型与本地 Java 对象模型相似点在于: 45 | 46 | * 引用一个对象可以作为参数传递或作为返回的结果; 47 | * 远程对象可以投到任何使用 Java 语法实现的远程接口的集合上; 48 | * 内置 Java instanceof 操作符可以用来测试远程对象是否支持远程接口。 49 | 50 | 不同点在于: 51 | 52 | * 远程对象的类是与远程接口进行交互,而不是与这些接口的实现类交互; 53 | * Non-remote 参数对于远程方法调用来说是通过复制,而不是通过引用; 54 | * 远程对象是通过引用来传递,而不是复制实际的远程实现; 55 | * 客户端必须处理额外的异常。 -------------------------------------------------------------------------------- /samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.cloud.weather.controller; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.DeleteMapping; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.PutMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import com.waylau.spring.cloud.weather.domain.User; 16 | import com.waylau.spring.cloud.weather.repository.UserRepository; 17 | 18 | /** 19 | * User Controller. 20 | * 21 | * @author Way Lau 22 | * @date 2017年10月8日 23 | */ 24 | @RestController 25 | @RequestMapping("/users") 26 | public class UserController { 27 | 28 | @Autowired 29 | private UserRepository userRepository; 30 | 31 | /** 32 | * 获取用户列表 33 | * 34 | * @return 35 | */ 36 | @GetMapping 37 | public List getUsers() { 38 | return userRepository.listUser(); 39 | } 40 | 41 | /** 42 | * 获取用户信息 43 | * 44 | * @param id 45 | * @return 46 | */ 47 | @GetMapping("/{id}") 48 | public User getUser(@PathVariable("id") Long id) { 49 | return userRepository.getUserById(id); 50 | } 51 | 52 | /** 53 | * 保存用户 54 | * 55 | * @param user 56 | */ 57 | @PostMapping 58 | public User createUser(@RequestBody User user) { 59 | return userRepository.saveOrUpateUser(user); 60 | } 61 | 62 | /** 63 | * 修改用户 64 | * 65 | * @param id 66 | * @param user 67 | */ 68 | @PutMapping("/{id}") 69 | public void updateUser(@PathVariable("id") Long id, @RequestBody User user) { 70 | User oldUser = this.getUser(id); 71 | 72 | if (oldUser != null) { 73 | user.setId(id); 74 | userRepository.saveOrUpateUser(user); 75 | } 76 | 77 | } 78 | 79 | /** 80 | * 删除用户 81 | * 82 | * @param id 83 | * @return 84 | */ 85 | @DeleteMapping("/{id}") 86 | public void deleteUser(@PathVariable("id") Long id) { 87 | userRepository.deleteUser(id); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /samples/axon-cqrs/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.waylau.spring 6 | axon-cqrs 7 | 1.0.0 8 | axon-cqrs 9 | jar 10 | 11 | waylau.com 12 | https://waylau.com 13 | 14 | 15 | 16 | UTF-8 17 | 5.2.3.RELEASE 18 | 3.4.3 19 | 2.13.3 20 | 21 | 22 | 23 | org.springframework 24 | spring-context 25 | ${spring.version} 26 | 27 | 28 | org.axonframework 29 | axon-core 30 | ${axon.version} 31 | 32 | 33 | org.axonframework 34 | axon-spring 35 | ${axon.version} 36 | 37 | 38 | org.apache.logging.log4j 39 | log4j-core 40 | ${log4j.version} 41 | 42 | 43 | org.apache.logging.log4j 44 | log4j-jcl 45 | ${log4j.version} 46 | 47 | 48 | org.apache.logging.log4j 49 | log4j-slf4j-impl 50 | ${log4j.version} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.apache.maven.plugins 60 | 61 | 62 | maven-compiler-plugin 63 | 64 | 3.7.0 65 | 66 | 1.8 67 | 1.8 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /samples/javase-rest/src/main/java/com/waylau/rest/resource/MyResource.java: -------------------------------------------------------------------------------- 1 | package com.waylau.rest.resource; 2 | 3 | import javax.ws.rs.Consumes; 4 | import javax.ws.rs.DELETE; 5 | import javax.ws.rs.GET; 6 | import javax.ws.rs.Path; 7 | import javax.ws.rs.PathParam; 8 | import javax.ws.rs.Produces; 9 | import javax.ws.rs.QueryParam; 10 | import javax.ws.rs.core.MediaType; 11 | 12 | import com.waylau.rest.bean.MyBean; 13 | 14 | /** 15 | * 根资源 (暴露在"myresource"路径) 16 | * 17 | * @author waylau.com 18 | * 2015-3-1 19 | */ 20 | @Path("myresource") 21 | public class MyResource { 22 | 23 | /** 24 | * 方法处理 HTTP GET 请求。返回的对象以"text/plain"媒体类型 25 | * 给客户端 26 | * 27 | * @return String 以 text/plain 形式响应 28 | */ 29 | @GET 30 | @Produces(MediaType.TEXT_PLAIN) 31 | public String getIt() { 32 | return "Got it!"; 33 | } 34 | 35 | 36 | /** 37 | * 方法处理 HTTP GET 请求。返回的对象以"application/xml"媒体类型 38 | * 给客户端 39 | * 40 | * @return MyPojo 以 application/xml 形式响应 41 | */ 42 | @GET 43 | @Path("pojoxml") 44 | @Produces(MediaType.APPLICATION_XML) 45 | public MyBean getPojoXml() { 46 | MyBean pojo = new MyBean(); 47 | pojo.setName("waylau.com"); 48 | pojo.setAge(28); 49 | return pojo; 50 | } 51 | 52 | /** 53 | * 方法处理 HTTP GET 请求。返回的对象以"application/json"媒体类型 54 | * 给客户端 55 | * 56 | * @return MyPojo 以 application/json 形式响应 57 | */ 58 | @GET 59 | @Path("pojojson") 60 | @Produces(MediaType.APPLICATION_JSON) 61 | public MyBean getPojoJson() { 62 | MyBean pojo = new MyBean(); 63 | pojo.setName("waylau.com"); 64 | pojo.setAge(28); 65 | return pojo; 66 | } 67 | 68 | @DELETE 69 | @Path("pojojson") 70 | @Produces(MediaType.TEXT_PLAIN) 71 | public String deletePojoJson(@QueryParam("name") String name ) { 72 | return "You delete " + name; 73 | } 74 | 75 | @DELETE 76 | @Path("pojojson/{name}") 77 | @Produces(MediaType.TEXT_PLAIN) 78 | public String deletePojoJsonPath(@PathParam("name") String name ) { 79 | return "You delete " + name; 80 | } 81 | 82 | //下面的例子是无法接收到 body 作为参数的反面例子 83 | // @DELETE 84 | // @Path("pojojson") 85 | // @Consumes(MediaType.APPLICATION_JSON) 86 | // public String deletePojoJsonBody(@QueryParam("name") String name ) { 87 | // return "You delete " + name; 88 | // } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /samples/security-basic/src/main/java/com/waylau/spring/mvc/JettyServer.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.mvc; 2 | 3 | import java.util.EnumSet; 4 | import javax.servlet.DispatcherType; 5 | import org.eclipse.jetty.server.Server; 6 | import org.eclipse.jetty.servlet.FilterHolder; 7 | import org.eclipse.jetty.servlet.ServletContextHandler; 8 | import org.eclipse.jetty.servlet.ServletHolder; 9 | import org.springframework.web.context.ContextLoaderListener; 10 | import org.springframework.web.context.WebApplicationContext; 11 | import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 12 | import org.springframework.web.filter.DelegatingFilterProxy; 13 | import org.springframework.web.servlet.DispatcherServlet; 14 | import com.waylau.spring.mvc.configuration.AppConfiguration; 15 | 16 | /** 17 | * Jetty Server. 18 | * 19 | * @since 1.0.0 2018年3月21日 20 | * @author Way Lau 21 | */ 22 | public class JettyServer { 23 | private static final int DEFAULT_PORT = 8080; 24 | private static final String CONTEXT_PATH = "/"; 25 | private static final String MAPPING_URL = "/*"; 26 | 27 | public void run() throws Exception { 28 | Server server = new Server(DEFAULT_PORT); 29 | server.setHandler(servletContextHandler(webApplicationContext())); 30 | server.start(); 31 | server.join(); 32 | } 33 | 34 | private ServletContextHandler servletContextHandler(WebApplicationContext ct) { 35 | // 启用Session管理器 36 | ServletContextHandler handler = 37 | new ServletContextHandler(ServletContextHandler.SESSIONS); 38 | 39 | handler.setContextPath(CONTEXT_PATH); 40 | handler.addServlet(new ServletHolder(new DispatcherServlet(ct)), 41 | MAPPING_URL); 42 | handler.addEventListener(new ContextLoaderListener(ct)); 43 | 44 | // 添加Spring Security过滤器 45 | FilterHolder filterHolder=new FilterHolder(DelegatingFilterProxy.class); 46 | filterHolder.setName("springSecurityFilterChain"); 47 | handler.addFilter(filterHolder, MAPPING_URL, 48 | EnumSet.of(DispatcherType.REQUEST)); 49 | 50 | return handler; 51 | } 52 | 53 | private WebApplicationContext webApplicationContext() { 54 | AnnotationConfigWebApplicationContext context = 55 | new AnnotationConfigWebApplicationContext(); 56 | context.register(AppConfiguration.class); 57 | return context; 58 | } 59 | } -------------------------------------------------------------------------------- /samples/eureka-client/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /samples/eureka-server/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /samples/spring-boot-rest/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /samples/hello-world-docker/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Distributed Java.《分布式 Java》 2 | 3 | Distributed Java.Let's [READ](SUMMARY.md)! 4 | 5 | 《分布式 Java》是一本关于 Java 分布式应用的学习教程,是对市面上基于 Java 的分布式系统最佳实践的技术总结。图文并茂,并通过大量实例让你走近 Java 的世界! 6 | 7 | 本书业余时间所著,水平有限、时间紧张,难免疏漏,欢迎指正,[点此](https://github.com/waylau/distributed-java/issues)提问。感谢您的参与! 8 | 9 | 书中所有实例,在 的 `samples` 目录下,代码遵循《[Java 编码规范]()》。另外有 GitBook 的版本方便阅读 。 10 | 11 | 从[目录](SUMMARY.md)开始阅读吧! 12 | 13 | 14 | ## 本书所涉及的技术和相关版本 15 | 16 | 涉及的相关技术及版本如下。 17 | 18 | * JDK 13 19 | * Apache Maven 3.6.3 20 | * Eclipse 2019-12 (4.14) 21 | * JUnit 5.5.2 22 | * Jersey 2.30 23 | * Apache CXF 3.3.5 24 | * Spring 5.2.3.RELEASE 25 | * ActiveMQ 5.15.11 26 | * Spring Boot 2.1.2.RELEASE 27 | * Axon Framework 3.4.3 28 | * Docker 17.09.1-ce-win42 29 | * Spark 2.3.0 30 | * MongoDB 3.4.6 31 | * ZooKeeper 3.5.6 32 | * Spring Security 5.2.0.BUILD-SNAPSHOT 33 | * NGINX 1.15.8 34 | * Spring Cloud Finchley.M9 35 | 36 | 37 | 包含示例如下: 38 | 39 | * [在Java中实现常用网络I/O模型](samples/java-io-mode) 40 | * [并发带来的风险——死锁](samples/java-concurrency) 41 | * [基于Java RMI实现分布式对象通信](samples/java-rmi) 42 | * [基于JAX-WS实现Web服务](samples/java-ws) 43 | * [基于JMS的消息发送和接收](samples/jms-msg) 44 | * [基于Jersey来构建REST服务](samples/jersey-rest) 45 | * [基于Apache CXF来构建REST服务](samples/cxf-rest) 46 | * [基于Spring Web MVC来构建REST服务](samples/spring-rest) 47 | * [Jetty HTTP Server](samples/javase-rest) 48 | * [基于Spring Boot实现微服务](samples/spring-boot-rest) 49 | * [基于CQRS微服务通信](samples/axon-cqrs) 50 | * [使用AWS平台实现Serverless架构](samples/game-server) 51 | * [基于Spark词频统计](samples/spark-word-count) 52 | * [基于MongoDB文件服务器](https://github.com/waylau/mongodb-file-server) 53 | * [基于ZooKeeper的服务注册和发现](samples/zk-registry-discovery) 54 | * [基于Spring Cloud的服务器](samples/eureka-server) 55 | * [基于Spring Cloud的客户端](samples/eureka-client) 56 | * 陆续整理中... 57 | 58 | 59 | ## 相关书籍 60 | 61 | 与本书配套的书籍已经出版: 62 | 63 | * [《分布式系统开发实战》](https://github.com/waylau/distributed-system-tutorial-samples) 64 | 65 | 66 | ## 联系作者 67 | 68 | 您也可以直接联系我: 69 | 70 | * 博客:https://waylau.com 71 | * 邮箱:[waylau521(at)gmail.com](mailto:waylau521@gmail.com) 72 | * 微博:http://weibo.com/waylau521 73 | * 开源:https://github.com/waylau 74 | 75 | ## 其他书籍 76 | 77 | 若您对本书不感冒,笔者还写了其他方面的超过一打的书籍(可见),多是开源电子书。 78 | 79 | 本人也维护了一个[books-collection](https://github.com/waylau/books-collection)项目,里面提供了优质的专门给程序员的开源、免费图书集合。 80 | 81 | ## 开源捐赠 82 | 83 | 84 | ![开源捐赠](https://waylau.com/images/showmethemoney-sm.jpg) 85 | 86 | 捐赠所得所有款项将用于开源事业!见[捐赠列表](https://waylau.com/donate/)。 87 | -------------------------------------------------------------------------------- /samples/game-server/aws_game_server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by waylau on 2016/8/6. 3 | */ 4 | var AWS = require('aws-sdk'); 5 | exports.handler = function (event, context) { 6 | console.log("Received data as:", event); 7 | var ec2 = new AWS.EC2({region: 'ap-northeast-1'}); 8 | var params = { 9 | ImageId: 'ami-29160d47', 10 | InstanceType: 't2.micro', 11 | KeyName: 'Tech-labs', 12 | SecurityGroupIds: ['sg-d0aa1bb4'], 13 | IamInstanceProfile: {Name: 'EC2-Admin'}, 14 | MinCount: 1, 15 | MaxCount: 1 16 | }; 17 | 18 | // 创建实例 19 | ec2.runInstances(params, function (err, data) { 20 | if (err) { 21 | console.log("Could not create instance", err); 22 | context.fail(err); 23 | } 24 | var instanceId = data.Instances[0].InstanceId; 25 | console.log("Created instance", instanceId); 26 | 27 | //TODO(待完成)持久化示例 id 并设置状态为启动状态 28 | context.succeed(instanceId); 29 | }); 30 | }; 31 | 32 | 33 | var AWS = require('aws-sdk'); 34 | exports.handler = function (event, context) { 35 | console.log("Received data as:", event); 36 | var instanceId = event.instanceId; 37 | var region = event.region; 38 | var publicIp = event.publicIp; 39 | var version = event.version; 40 | // ... 41 | 42 | //TODO(待完成)检测示例 id 并更新示例状态到线上 43 | }; 44 | 45 | 46 | var AWS = require('aws-sdk'); 47 | exports.handler = function (event, context) { 48 | console.log("Received data as:", event); 49 | var message = JSON.parse(event.Records[0].Sns.Message); 50 | var region = event.Records[0].EventSubscriptionArn.split(":")[3]; 51 | console.log("Need to terminate the server in region:", region); 52 | var ec2 = new AWS.EC2({region: region}); 53 | console.log("Need to terminate the server:", message); 54 | var instanceId = message.Trigger.Dimensions[0].value; 55 | console.log("Need to terminate the server:", instanceId); 56 | 57 | //TODO(待完成)检测实例是否可被从 DynamoDB 终止,而后更新示例为终止状态 58 | var params = {InstanceIds: [instanceId]}; 59 | 60 | //终止实例 61 | ec2.terminateInstances(params, function (err, data) { 62 | if (err) { 63 | console.log("Could not terminate instance", err); 64 | 65 | //TODO 回滚终止实例 66 | context.fail(err); 67 | } 68 | for (var i in data.TerminatingInstances) { 69 | var instance = data.TerminatingInstances[i]; 70 | console.log('TERM:\t' + instance.InstanceId); 71 | 72 | //TODO 删除终止的实例 73 | } 74 | context.succeed(data.TerminatingInstances); 75 | }); 76 | }; -------------------------------------------------------------------------------- /samples/axon-cqrs/src/main/java/com/waylau/axon/cqrs/command/aggregates/BankAccount.java: -------------------------------------------------------------------------------- 1 | package com.waylau.axon.cqrs.command.aggregates; 2 | 3 | import static org.axonframework.commandhandling.model.AggregateLifecycle.apply; 4 | import static org.slf4j.LoggerFactory.getLogger; 5 | 6 | import java.math.BigDecimal; 7 | 8 | import org.axonframework.commandhandling.CommandHandler; 9 | import org.axonframework.commandhandling.model.AggregateIdentifier; 10 | import org.axonframework.eventhandling.EventHandler; 11 | import org.slf4j.Logger; 12 | 13 | import com.waylau.axon.cqrs.command.commands.CreateAccountCommand; 14 | import com.waylau.axon.cqrs.command.commands.WithdrawMoneyCommand; 15 | import com.waylau.axon.cqrs.common.domain.AccountId; 16 | import com.waylau.axon.cqrs.common.events.CreateAccountEvent; 17 | import com.waylau.axon.cqrs.common.events.WithdrawMoneyEvent; 18 | 19 | /** 20 | * Bank Account. 21 | * 22 | * @since 1.0.0 2020年1月21日 23 | * @author Way Lau 24 | */ 25 | public class BankAccount { 26 | 27 | private static final Logger LOGGER = getLogger(BankAccount.class); 28 | 29 | @AggregateIdentifier 30 | private AccountId accountId; 31 | private String accountName; 32 | private BigDecimal balance; 33 | 34 | public BankAccount() { 35 | } 36 | 37 | @CommandHandler 38 | public BankAccount(CreateAccountCommand command){ 39 | LOGGER.debug("Construct a new BankAccount"); 40 | apply(new CreateAccountEvent(command.getAccountId(), 41 | command.getAccountName(), 42 | command.getAmount())); 43 | } 44 | 45 | @CommandHandler 46 | public void handle(WithdrawMoneyCommand command){ 47 | apply(new WithdrawMoneyEvent(command.getAccountId(), 48 | command.getAmount())); 49 | } 50 | 51 | @EventHandler 52 | public void on(CreateAccountEvent event){ 53 | this.accountId = event.getAccountId(); 54 | this.accountName = event.getAccountName(); 55 | this.balance = new BigDecimal(event.getAmount()); 56 | LOGGER.info("Account {} is created with balance {}", 57 | accountId, 58 | this.balance); 59 | } 60 | 61 | @EventHandler 62 | public void on(WithdrawMoneyEvent event){ 63 | BigDecimal result = this.balance.subtract( 64 | new BigDecimal(event.getAmount())); 65 | if(result.compareTo(BigDecimal.ZERO)<0) 66 | LOGGER.error("Cannot withdraw more money than the balance!"); 67 | else { 68 | this.balance = result; 69 | LOGGER.info("Withdraw {} from account {}, balance result: {}", 70 | event.getAmount(), accountId, balance); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /samples/java-io-mode/src/main/java/com/waylau/java/demo/aio/AsyncEchoServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.aio; 5 | 6 | import java.io.IOException; 7 | import java.net.InetSocketAddress; 8 | import java.net.StandardSocketOptions; 9 | import java.nio.ByteBuffer; 10 | import java.nio.channels.AsynchronousServerSocketChannel; 11 | import java.nio.channels.AsynchronousSocketChannel; 12 | import java.util.concurrent.ExecutionException; 13 | import java.util.concurrent.Future; 14 | 15 | /** 16 | * Async Echo Server. 17 | * 18 | * @since 1.0.0 2019年9月29日 19 | * @author Way Lau 20 | */ 21 | public class AsyncEchoServer { 22 | public static int DEFAULT_PORT = 7; 23 | 24 | /** 25 | * @param args 26 | */ 27 | public static void main(String[] args) { 28 | int port; 29 | 30 | try { 31 | port = Integer.parseInt(args[0]); 32 | } catch (RuntimeException ex) { 33 | port = DEFAULT_PORT; 34 | } 35 | 36 | AsynchronousServerSocketChannel serverChannel; 37 | try { 38 | serverChannel = AsynchronousServerSocketChannel.open(); 39 | InetSocketAddress address = new InetSocketAddress(port); 40 | serverChannel.bind(address); 41 | 42 | // 设置阐述 43 | serverChannel.setOption(StandardSocketOptions.SO_RCVBUF, 4 * 1024); 44 | serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true); 45 | 46 | System.out.println("AsyncEchoServer已启动,端口:" + port); 47 | } catch (IOException ex) { 48 | ex.printStackTrace(); 49 | return; 50 | } 51 | 52 | while (true) { 53 | 54 | // 可连接 55 | Future future = serverChannel.accept(); 56 | AsynchronousSocketChannel socketChannel = null; 57 | try { 58 | socketChannel = future.get(); 59 | } catch (InterruptedException | ExecutionException e) { 60 | System.out.println("AsyncEchoServer异常!" + e.getMessage()); 61 | } 62 | 63 | System.out.println("AsyncEchoServer接受客户端的连接:" + socketChannel); 64 | 65 | // 分配缓存区 66 | ByteBuffer buffer = ByteBuffer.allocate(100); 67 | 68 | try { 69 | while (socketChannel.read(buffer).get() != -1) { 70 | buffer.flip(); 71 | socketChannel.write(buffer).get(); 72 | 73 | 74 | System.out.println("AsyncEchoServer -> " 75 | + socketChannel.getRemoteAddress() + ":" + buffer.toString()); 76 | 77 | 78 | if (buffer.hasRemaining()) { 79 | buffer.compact(); 80 | } else { 81 | buffer.clear(); 82 | } 83 | } 84 | 85 | socketChannel.close(); 86 | } catch (InterruptedException | ExecutionException | IOException e) { 87 | System.out.println("AsyncEchoServer异常!" + e.getMessage()); 88 | 89 | } 90 | 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /samples/security-basic/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.waylau.spring 6 | security-basic 7 | 1.0.0 8 | security-basic 9 | jar 10 | 11 | waylau.com 12 | https://waylau.com 13 | 14 | 15 | 16 | 17 | 18 | spring-snapshots 19 | Spring Snapshots 20 | https://repo.spring.io/snapshot 21 | 22 | 23 | 24 | 25 | 5.1.5.RELEASE 26 | 9.4.14.v20181114 27 | 2.9.7 28 | 5.2.15.RELEASE 29 | 30 | 31 | 32 | 33 | org.springframework 34 | spring-webmvc 35 | ${spring.version} 36 | 37 | 38 | org.eclipse.jetty 39 | jetty-servlet 40 | ${jetty.version} 41 | 42 | 43 | com.fasterxml.jackson.core 44 | jackson-core 45 | ${jackson.version} 46 | 47 | 48 | com.fasterxml.jackson.core 49 | jackson-databind 50 | ${jackson.version} 51 | 52 | 53 | 54 | 55 | org.springframework.security 56 | spring-security-web 57 | ${spring-security.version} 58 | 59 | 60 | org.springframework.security 61 | spring-security-config 62 | ${spring-security.version} 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.apache.maven.plugins 70 | maven-shade-plugin 71 | 3.6.0 72 | 73 | 74 | package 75 | 76 | shade 77 | 78 | 79 | 80 | 82 | com.waylau.spring.mvc.Application 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /samples/jersey-rest/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | 8 | com.waylau.jersey 9 | jersey-rest 10 | jar 11 | 1.0-SNAPSHOT 12 | jersey-rest 13 | 14 | 15 | 16 | 17 | org.glassfish.jersey 18 | jersey-bom 19 | ${jersey.version} 20 | pom 21 | import 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.glassfish.jersey.containers 29 | jersey-container-grizzly2-http 30 | 31 | 32 | org.glassfish.jersey.inject 33 | jersey-hk2 34 | 35 | 36 | 42 | 43 | junit 44 | junit 45 | 4.13.1 46 | test 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.apache.maven.plugins 54 | maven-compiler-plugin 55 | 2.5.1 56 | true 57 | 58 | 1.7 59 | 1.7 60 | 61 | 62 | 63 | org.codehaus.mojo 64 | exec-maven-plugin 65 | 1.2.1 66 | 67 | 68 | 69 | java 70 | 71 | 72 | 73 | 74 | com.waylau.jersey.Main 75 | 76 | 77 | 78 | 79 | 80 | 81 | 2.30 82 | UTF-8 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/net-overview.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | ## 网络基础 4 | 5 | 在互联网上之间的通信交流,一般是基于 TCP (Transmission Control Protocol,传输控制协议) 或者 UDP (User Datagram Protocol,用户数据报协议) ,如下图: 6 | 7 | ![](../images/net-1netw.gif) 8 | 9 | 编写 Java 应用,我们只需关注于应用层 (application layer),而不用关心 TCP 和 UDP 所在的传输层是如何实现的。java.net 包含了你编程所需的类,这些类是与操作系统无关的。比如 URL, URLConnection, Socket, 和 ServerSocket 类是使用 TCP 连接网络的, DatagramPacket, DatagramSocket, 和 MulticastSocket 类是用于 UDP 的。 10 | 11 | Java 支持的协议只有 TCP 和 UDP ,以及在建立在 TCP 和 UDP 之上其他应用层协议。所有其他传输层、网际层和更底层的协议,如 ICMP、IGMP、ARP、RARP、RSVP 和其他协议 在 Java 中只能链接到原生代码来实现。 12 | 13 | ## TCP 14 | 15 | TCP (Transmission Control Protocol) 是面向连接的、提供端到端可靠的数据流(flow of data)。TCP 提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 16 | 17 | “面向连接”就是在正式通信前必须要与对方建立起连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。 18 | 19 | ### 三次握手 20 | 21 | TCP 是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个 TCP 连接必须要经过三次“握手”才能建立起来,简单的讲就是: 22 | 23 | 1. 主机 A 向主机 B 发出连接请求数据包:“我想给你发数据,可以吗?”; 24 | 2. 主机 B 向主机 A 发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你来吧”; 25 | 3. 主机 A 再发出一个数据包确认主机 B 的要求同步:“好的,我来也,你接着吧!” 26 | 27 | 三次“握手”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机 A 才向主机 B 正式发送数据。 28 | 29 | 可以详见我的另外一篇博客[《TCP 协议的三次握手、四次分手》](https://waylau.com/tcp-connect-and-close/)。 30 | 31 | ### 如何保证数据的可靠 32 | 33 | TCP 通过下列方式来提供可靠性: 34 | 35 | * 应用数据被分割成 TCP 认为最适合发送的数据块。这和 UDP 完全不同,应用程序产生的数据报长度将保持不变。由 TCP 传递给 IP 的信息单位称为报文段或段(segment)。 36 | * 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。(可自行了解 TCP 协议中自适应的超时及重传策略)。 37 | * 当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。 38 | * TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错, TCP 将丢弃这个报文段和不确认收到此报文段(希望发送端超时并重发)。 39 | * 既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。如果必要, TCP 将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。 40 | * 既然 IP 数据报会发生重复, TCP 的接收端必须丢弃重复的数据。 41 | * TCP 还能提供流量控制。TCP 连接的每一方都有固定大小的缓冲空间。 TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。 42 | 43 | ## UDP 44 | 45 | UDP (User Datagram Protocol) 不是面向连接的,主机发送独立的数据报(datagram)给其他主机,不保证数据到达。由于 UDP 在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。 46 | 47 | 而无连接是一开始就发送信息(严格说来,这是没有开始、结束的),只是一次性的传递,是先不需要接受方的响应,因而在一定程度上也无法保证信息传递的可靠性了,就像写信一样,我们只是将信寄出去,却不能保证收信人一定可以收到。 48 | 49 | ### TCP 和 UDP 如何抉择 50 | 51 | TCP 是面向连接的,有比较高的可靠性, 一些要求比较高的服务一般使用这个协议,如FTP、Telnet、SMTP、HTTP、POP3 等,而 UDP 是面向无连接的,使用这个协议的常见服务有 DNS、SNMP、QQ 等。对于 QQ 必须另外说明一下,QQ2003 以前是只使用UDP协议的,其服务器使用8000端口,侦听是否有信息传来,客户端使用 4000 端口,向外发送信息(这也就不难理解在一般的显IP的QQ版本中显示好友的IP地址信息中端口常为4000或其后续端口的原因了),即QQ程序既接受服务又提供服务,在以后的 QQ 版本中也支持使用 TCP 协议了。 52 | 53 | ## 端口 54 | 55 | 一般来说,一台计算机具有单个物理连接到网络。数据通过这个连接去往特定的计算机。然而,该数据可以被用于在计算机上运行的不同应用。那么,计算机知道哪个应用程序转发数据?通过使用端口。 56 | 57 | 在互联网上传输的数据是通过计算机的标识和端口来定位的。计算机的标识是 32-bit 的 IP 地址。端口由一个 16-bit 的数字。 58 | 59 | 在诸如面向连接的通信如 TCP,服务器应用将套接字绑定到一个特定端口号。这是向系统注册服务用来接受该端口的数据。然后,客户端可以在与服务器在服务器端口会合,如下图所示: 60 | 61 | ![](../images/net-2tcp.gif) 62 | 63 | TCP 和 UDP 协议使用的端口来将接收到的数据映射到一个计算机上运行的进程。 64 | 65 | 在基于数据报的通信,如 UDP,数据报包中包含它的目的地的端口号,然后 UDP 将数据包路由到相应的应用程序,如本图所示的端口号: 66 | 67 | ![](../images/net-3tcpudp.gif) 68 | 69 | 端口号取值范围是从 0 到 65535 (16-bit 长度),其中范围从 0 到 1023 是受限的,它们是被知名的服务所保留使用,例如 HTTP (端口是 80)和 FTP (端口是20、21)等系统服务。这些端口被称为众所周知的端口(well-known ports)。您的应用程序不应该试图绑定到他们。你可以访问 来查询各种常用的已经分配的端口号列表。 -------------------------------------------------------------------------------- /samples/zk-registry-discovery/src/main/java/com/waylau/zk/discovery/ZkServiceDiscovery.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.zk.discovery; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.ThreadLocalRandom; 8 | 9 | import org.I0Itec.zkclient.ZkClient; 10 | import org.springframework.util.CollectionUtils; 11 | 12 | import com.google.common.collect.Lists; 13 | import com.waylau.zk.Constant; 14 | 15 | /** 16 | * ZooKeeper Service Discovery. 17 | * 18 | * @since 1.0.0 2018年5月16日 19 | * @author Way Lau 20 | */ 21 | public class ZkServiceDiscovery implements ServiceDiscovery { 22 | 23 | /** 24 | * ZK 地址. 25 | */ 26 | private String zkAddress = "localhost"; 27 | 28 | /** 29 | * 缓存所有的服务 IP 和 端口. 30 | */ 31 | private final List addressCache = Lists.newCopyOnWriteArrayList(); 32 | 33 | /** 34 | * ZK 客户端. 35 | */ 36 | private ZkClient zkClient; 37 | 38 | public void init() { 39 | zkClient = new ZkClient(zkAddress, 40 | Constant.ZK_SESSION_TIMEOUT, 41 | Constant.ZK_CONNECTION_TIMEOUT); 42 | 43 | System.out.println(">>>connect to zookeeper"); 44 | } 45 | 46 | @Override 47 | public String discover(String name) { 48 | try { 49 | String servicePath = Constant.ZK_REGISTRY + "/" + name; 50 | 51 | // 获取服务节点 52 | if (!zkClient.exists(servicePath)) { 53 | throw new RuntimeException( 54 | String.format(">>>can't find any service node on path {}", 55 | servicePath)); 56 | } 57 | 58 | // 从本地缓存获取某个服务地址 59 | String address; 60 | int addressCacheSize = addressCache.size(); 61 | if (addressCacheSize > 0) { 62 | if (addressCacheSize == 1) { 63 | address = addressCache.get(0); 64 | } else { 65 | address = addressCache.get(ThreadLocalRandom.current().nextInt(addressCacheSize)); 66 | 67 | System.out.println(">>>get only address node:" + address); 68 | } 69 | 70 | // 从zk服务注册中心获取某个服务地址 71 | } else { 72 | List addressList = zkClient.getChildren(servicePath); 73 | addressCache.addAll(addressList); 74 | 75 | // 监听servicePath下的子文件是否发生变化 76 | zkClient.subscribeChildChanges(servicePath, (parentPath, currentChilds) -> { 77 | System.out.println(">>>servicePath is changed:" + parentPath); 78 | 79 | addressCache.clear(); 80 | addressCache.addAll(currentChilds); 81 | }); 82 | 83 | if (CollectionUtils.isEmpty(addressList)) { 84 | throw new RuntimeException( 85 | String.format(">>>can’t find any address node on path {}", servicePath)); 86 | } 87 | 88 | int nodes = addressList.size(); 89 | if (nodes == 1) { 90 | address = addressList.get(0); 91 | } else { 92 | 93 | // 如果多个,随机取一个 94 | address = addressList.get(ThreadLocalRandom.current().nextInt(nodes)); 95 | } 96 | 97 | System.out.println(">>>get address node:" + address); 98 | } 99 | 100 | // 获取ip和端口号 101 | String addressPath = servicePath + "/" + address; 102 | String hostAndPort = zkClient.readData(addressPath); 103 | return hostAndPort; 104 | } catch (Exception e) { 105 | 106 | System.out.println(">>>service discovery exception" + e.getMessage()); 107 | 108 | zkClient.close(); 109 | } 110 | return null; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /samples/jms-msg/src/test/java/com/waylau/spring/jms/SpringJmsTest.java: -------------------------------------------------------------------------------- 1 | package com.waylau.spring.jms; 2 | 3 | import javax.jms.Destination; 4 | 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.test.context.ContextConfiguration; 10 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 | 12 | import com.waylau.spring.jms.queue.ConsumerService; 13 | import com.waylau.spring.jms.queue.ProducerService; 14 | import com.waylau.spring.jms.topic.TopicProvider; 15 | 16 | /** 17 | * Spring JMS Test. 18 | * 19 | * @since 1.0.0 2018年4月15日 20 | * @author Way Lau 21 | */ 22 | @RunWith(SpringJUnit4ClassRunner.class) 23 | @ContextConfiguration("/spring.xml") 24 | public class SpringJmsTest { 25 | 26 | /** 27 | * 队列名queue1 28 | */ 29 | @Autowired 30 | private Destination queueDestination; 31 | 32 | /** 33 | * 队列名queue2 34 | */ 35 | @Autowired 36 | private Destination queueDestination2; 37 | 38 | /** 39 | * 队列名sessionAwareQueue 40 | */ 41 | @Autowired 42 | private Destination sessionAwareQueue; 43 | 44 | /** 45 | * 队列名adapterQueue 46 | */ 47 | @Autowired 48 | private Destination adapterQueue; 49 | 50 | /** 51 | * 主题 guo_topic 52 | */ 53 | @Autowired 54 | @Qualifier("topicDestination") 55 | private Destination topic; 56 | 57 | /** 58 | * 主题消息发布者 59 | */ 60 | @Autowired 61 | private TopicProvider topicProvider; 62 | 63 | /** 64 | * 队列消息生产者 65 | */ 66 | @Autowired 67 | @Qualifier("producerService") 68 | private ProducerService producer; 69 | 70 | /** 71 | * 队列消息生产者 72 | */ 73 | @Autowired 74 | @Qualifier("consumerService") 75 | private ConsumerService consumer; 76 | 77 | /** 78 | * 测试生产者向queue1发送消息 79 | */ 80 | @Test 81 | public void testProduce() { 82 | String msg = "Hello world!"; 83 | producer.sendMessage(msg); 84 | } 85 | 86 | /** 87 | * 测试消费者从queue1接受消息 88 | */ 89 | @Test 90 | public void testConsume() { 91 | consumer.receive(queueDestination); 92 | } 93 | 94 | /** 95 | * 测试消息监听 96 | * 1.生产者向队列queue2发送消息 97 | * 2.ConsumerMessageListener监听队列,并消费消息 98 | */ 99 | @Test 100 | public void testSend() { 101 | producer.sendMessage(queueDestination2, "Hello R2"); 102 | } 103 | 104 | /** 105 | * 测试主题监听 106 | * 1.生产者向主题发布消息 107 | * 2.ConsumerMessageListener监听主题,并消费消息 108 | */ 109 | @Test 110 | public void testTopic() { 111 | topicProvider.publish(topic, "Hello Topic!"); 112 | } 113 | 114 | /** 115 | * 测试SessionAwareMessageListener 116 | * 1. 生产者向队列sessionAwareQueue发送消息 117 | * 2. SessionAwareMessageListener接受消息,并向queue1队列发送回复消息 118 | * 3. 消费者从queue1消费消息 119 | * 120 | */ 121 | @Test 122 | public void testAware() { 123 | producer.sendMessage(sessionAwareQueue, "Hello sessionAware"); 124 | consumer.receive(queueDestination); 125 | } 126 | 127 | /** 128 | * 测试MessageListenerAdapter 129 | * 1. 生产者向队列adapterQueue发送消息 130 | * 2. MessageListenerAdapter使ConsumerListener接受消息,并向queue1队列发送回复消息 131 | * 3. 消费者从queue1消费消息 132 | * 133 | */ 134 | @Test 135 | public void testAdapter() { 136 | producer.sendMessage(adapterQueue, "Hello adapterQueue", queueDestination); 137 | consumer.receive(queueDestination); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /samples/javase-rest/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | 8 | com.waylau 9 | javase-rest 10 | jar 11 | 1.0.0 12 | javase-rest 13 | 14 | 15 | 16 | 17 | org.glassfish.jersey 18 | jersey-bom 19 | ${jersey.version} 20 | pom 21 | import 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.glassfish.jersey.containers 45 | jersey-container-jetty-http 46 | 47 | 48 | org.glassfish.jersey.media 49 | jersey-media-multipart 50 | 51 | 52 | org.glassfish.jersey.media 53 | jersey-media-moxy 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.glassfish.jersey.media 62 | jersey-media-sse 63 | 64 | 65 | 66 | junit 67 | junit 68 | 4.13.1 69 | test 70 | 71 | 72 | 73 | 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-compiler-plugin 78 | 2.5.1 79 | true 80 | 81 | 1.7 82 | 1.7 83 | 84 | 85 | 86 | org.codehaus.mojo 87 | exec-maven-plugin 88 | 1.2.1 89 | 90 | 91 | 92 | java 93 | 94 | 95 | 96 | 97 | com.waylau.rest.App 98 | 99 | 100 | 101 | 102 | 103 | 104 | 2.30 105 | UTF-8 106 | 107 | 108 | -------------------------------------------------------------------------------- /samples/java-io-mode/src/main/java/com/waylau/java/demo/nio/NonBlokingEchoServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to https://waylau.com 3 | */ 4 | package com.waylau.java.demo.nio; 5 | 6 | import java.io.IOException; 7 | import java.net.InetSocketAddress; 8 | import java.nio.ByteBuffer; 9 | import java.nio.channels.SelectionKey; 10 | import java.nio.channels.Selector; 11 | import java.nio.channels.ServerSocketChannel; 12 | import java.nio.channels.SocketChannel; 13 | import java.util.Iterator; 14 | import java.util.Set; 15 | 16 | /** 17 | * Non Bloking Echo Server. 18 | * 19 | * @since 1.0.0 2019年9月28日 20 | * @author Way Lau 21 | */ 22 | public class NonBlokingEchoServer { 23 | public static int DEFAULT_PORT = 7; 24 | 25 | /** 26 | * @param args 27 | */ 28 | public static void main(String[] args) { 29 | int port; 30 | 31 | try { 32 | port = Integer.parseInt(args[0]); 33 | } catch (RuntimeException ex) { 34 | port = DEFAULT_PORT; 35 | } 36 | 37 | ServerSocketChannel serverChannel; 38 | Selector selector; 39 | try { 40 | serverChannel = ServerSocketChannel.open(); 41 | InetSocketAddress address = new InetSocketAddress(port); 42 | serverChannel.bind(address); 43 | serverChannel.configureBlocking(false); 44 | selector = Selector.open(); 45 | serverChannel.register(selector, SelectionKey.OP_ACCEPT); 46 | 47 | System.out.println("NonBlokingEchoServer已启动,端口:" + port); 48 | } catch (IOException ex) { 49 | ex.printStackTrace(); 50 | return; 51 | } 52 | 53 | while (true) { 54 | try { 55 | selector.select(); 56 | } catch (IOException e) { 57 | System.out.println("NonBlockingEchoServer异常!" + e.getMessage()); 58 | } 59 | Set readyKeys = selector.selectedKeys(); 60 | Iterator iterator = readyKeys.iterator(); 61 | while (iterator.hasNext()) { 62 | SelectionKey key = iterator.next(); 63 | iterator.remove(); 64 | try { 65 | // 可连接 66 | if (key.isAcceptable()) { 67 | ServerSocketChannel server = (ServerSocketChannel) key.channel(); 68 | SocketChannel socketChannel = server.accept(); 69 | 70 | System.out.println("NonBlokingEchoServer接受客户端的连接:" + socketChannel); 71 | 72 | // 设置为非阻塞 73 | socketChannel.configureBlocking(false); 74 | 75 | // 客户端注册到Selector 76 | SelectionKey clientKey = socketChannel.register(selector, 77 | SelectionKey.OP_WRITE | SelectionKey.OP_READ); 78 | 79 | // 分配缓存区 80 | ByteBuffer buffer = ByteBuffer.allocate(100); 81 | clientKey.attach(buffer); 82 | } 83 | 84 | // 可读 85 | if (key.isReadable()) { 86 | SocketChannel client = (SocketChannel) key.channel(); 87 | ByteBuffer output = (ByteBuffer) key.attachment(); 88 | client.read(output); 89 | 90 | System.out.println(client.getRemoteAddress() 91 | + " -> NonBlokingEchoServer:" + output.toString()); 92 | 93 | key.interestOps(SelectionKey.OP_WRITE); 94 | } 95 | 96 | // 可写 97 | if (key.isWritable()) { 98 | SocketChannel client = (SocketChannel) key.channel(); 99 | ByteBuffer output = (ByteBuffer) key.attachment(); 100 | output.flip(); 101 | client.write(output); 102 | 103 | System.out.println("NonBlokingEchoServer -> " 104 | + client.getRemoteAddress() + ":" + output.toString()); 105 | 106 | output.compact(); 107 | 108 | key.interestOps(SelectionKey.OP_READ); 109 | } 110 | } catch (IOException ex) { 111 | key.cancel(); 112 | try { 113 | key.channel().close(); 114 | } catch (IOException cex) { 115 | System.out.println( 116 | "NonBlockingEchoServer异常!" + cex.getMessage()); 117 | } 118 | } 119 | } 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /docs/socket.md: -------------------------------------------------------------------------------- 1 | # Socket 2 | 3 | 4 | ## 什么是 Socket 5 | 6 | Socket(套接字):是在网络上运行两个程序之间的双向通信链路的一个端点。socket绑定到一个端口号,使得 TCP 层可以标识数据最终要被发送到哪个应用程序。 7 | 8 | 正常情况下,一台服务器在特定计算机上运行,​​并具有被绑定到特定端口号的 socket。服务器只是等待,并监听用于客户发起的连接请求的 socket 。 9 | 10 | 在客户端:客户端知道服务器所运行的主机名称以及服务器正在侦听的端口号。建立连接请求时,客户端尝试与主机服务器和端口会合。客户端也需要在连接中将自己绑定到本地端口以便于给服务器做识别。本地端口号通常是由系统分配的。 11 | 12 | ![](../images/socket-5connect.gif) 13 | 14 | 如果一切顺利的话,服务器接受连接。一旦接受,服务器获取绑定到相同的本地端口的新 socket ,并且还具有其远程端点设定为客户端的地址和端口。它需要一个新的socket,以便它可以继续监听原来用于客户端连接请求的 socket 。 15 | 16 | ![](../images/socket-6connect.gif) 17 | 18 | 在客户端,如果连接被接受,则成功地创建一个套接字和客户端可以使用该 socket 与服务器进行通信。 19 | 20 | 客户机和服务器现在可以通过 socket 写入或读取来交互了。 21 | 22 | 端点是IP地址和端口号的组合。每个 TCP 连接可以通过它的两个端点被唯一标识。这样,你的主机和服务器之间可以有多个连接。 23 | 24 | java.net 包中提供了一个类 Socket,实现您的 Java 程序和网络上的其他程序之间的双向连接。 Socket 类隐藏任何特定系统的细节。通过使用 java.net.Socket 类,而不是依赖于原生代码,Java 程序可以用独立于平台的方式与网络进行通信。 25 | 26 | 此外,java.net 包含了 ServerSocket 类,它实现了服务器的 socket 可以侦监听和接受客户端的连接。下文将展示如何使用 Socket 和 ServerSocket 类。 27 | 28 | ## 实现一个 echo 服务器 29 | 30 | 让我们来看看这个例子,程序可以建立使用 Socket 类连接到服务器程序,客户端可以通过 socket 向服务器发送数据和接收数据。 31 | 32 | EchoClient 示例程序实现了一个客户端,连接到回声服务器。回声服务器从它的客户端接收数据并原样返回回来。EchoServer 实现了 echo 服务器。 (客户端可以连接到支持 [Echo 协议](http://tools.ietf.org/html/rfc862)的任何主机) 33 | 34 | EchoClient 创建一个 socket,从而得到回声服务器的连接。它从标准输入流中读取用户输入,然后通过 socket 转发该文本给回声服务器。服务器通过该 socket 将文本原样输入回给客户端。客户机程序读取并显示从服务器传递回给它的数据。 35 | 36 | 注意,EchoClient 例子既从 socket 写入又从 socket 中读取数据。 37 | 38 | EchoClient 代码: 39 | 40 | ```java 41 | public class EchoClient { 42 | public static void main(String[] args) throws IOException { 43 | 44 | if (args.length != 2) { 45 | System.err.println( 46 | "Usage: java EchoClient "); 47 | System.exit(1); 48 | } 49 | 50 | String hostName = args[0]; 51 | int portNumber = Integer.parseInt(args[1]); 52 | 53 | try ( 54 | Socket echoSocket = new Socket(hostName, portNumber); 55 | PrintWriter out = 56 | new PrintWriter(echoSocket.getOutputStream(), true); 57 | BufferedReader in = 58 | new BufferedReader( 59 | new InputStreamReader(echoSocket.getInputStream())); 60 | BufferedReader stdIn = 61 | new BufferedReader( 62 | new InputStreamReader(System.in)) 63 | ) { 64 | String userInput; 65 | while ((userInput = stdIn.readLine()) != null) { 66 | out.println(userInput); 67 | System.out.println("echo: " + in.readLine()); 68 | } 69 | } catch (UnknownHostException e) { 70 | System.err.println("Don't know about host " + hostName); 71 | System.exit(1); 72 | } catch (IOException e) { 73 | System.err.println("Couldn't get I/O for the connection to " + 74 | hostName); 75 | System.exit(1); 76 | } 77 | } 78 | } 79 | ``` 80 | 81 | EchoServer 代码: 82 | 83 | ```java 84 | public class EchoServer { 85 | public static void main(String[] args) throws IOException { 86 | 87 | if (args.length != 1) { 88 | System.err.println("Usage: java EchoServer "); 89 | System.exit(1); 90 | } 91 | 92 | int portNumber = Integer.parseInt(args[0]); 93 | 94 | try ( 95 | ServerSocket serverSocket = 96 | new ServerSocket(Integer.parseInt(args[0])); 97 | Socket clientSocket = serverSocket.accept(); 98 | PrintWriter out = 99 | new PrintWriter(clientSocket.getOutputStream(), true); 100 | BufferedReader in = new BufferedReader( 101 | new InputStreamReader(clientSocket.getInputStream())); 102 | ) { 103 | String inputLine; 104 | while ((inputLine = in.readLine()) != null) { 105 | out.println(inputLine); 106 | } 107 | } catch (IOException e) { 108 | System.out.println("Exception caught when trying to listen on port " 109 | + portNumber + " or listening for a connection"); 110 | System.out.println(e.getMessage()); 111 | } 112 | } 113 | } 114 | ``` 115 | 116 | 首先启动服务器,在命令行输入如下,设定一个端口号,比如 7(Echo 协议指定端口是 7): 117 | 118 | java EchoServer 7 119 | 120 | 而后启动客户端,echoserver.example.com 是你主机的名称,如果是本机的话,主机名称可以是 localhost 121 | 122 | java EchoClient echoserver.example.com 7 123 | 124 | 输出效果如下: 125 | 126 | 你好吗? 127 | echo: 你好吗? 128 | 我很好哦 129 | echo: 我很好哦 130 | 要过年了,waylau.com 祝你 猴年大吉,身体健康哦! 131 | echo: 要过年了,waylau.com 祝你 猴年大吉,身体健康哦! 132 | 133 | -------------------------------------------------------------------------------- /samples/eureka-client/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /samples/eureka-server/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /samples/hello-world-docker/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | --------------------------------------------------------------------------------