diff --git a/.gitignore b/.gitignore
index 1d963a9..fd6098f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,27 @@
-*.class
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
.project
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
+.settings
+.springBeans
-# Package Files #
-*.jar
-*.war
-*.ear
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+/bin/
+/target/
diff --git a/README.md b/README.md
index 5ef8b38..db31f5a 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ Distributed Java.Let's [READ](SUMMARY.md)!
与本书配套的书籍已经出版:
-* [《分布式系统常用技术及案例分析》](https://github.com/waylau/distributed-systems-technologies-and-cases-analysis)
+* [《分布式系统开发实战》](https://github.com/waylau/distributed-system-tutorial-samples)
## 联系作者
diff --git a/samples/axon-cqrs/pom.xml b/samples/axon-cqrs/pom.xml
index 73bbb7f..50e0531 100644
--- a/samples/axon-cqrs/pom.xml
+++ b/samples/axon-cqrs/pom.xml
@@ -16,7 +16,7 @@
UTF-8
5.2.3.RELEASE
3.4.3
- 2.13.0
+ 2.13.3
diff --git a/samples/cxf-rest/pom.xml b/samples/cxf-rest/pom.xml
index 3ff726f..ab5c7f6 100644
--- a/samples/cxf-rest/pom.xml
+++ b/samples/cxf-rest/pom.xml
@@ -47,7 +47,7 @@
junit
junit
- 4.12
+ 4.13.1
test
diff --git a/samples/hello-world-docker/.gitignore b/samples/hello-world-docker/.gitignore
new file mode 100644
index 0000000..4c6eb77
--- /dev/null
+++ b/samples/hello-world-docker/.gitignore
@@ -0,0 +1,26 @@
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+/bin/
diff --git a/samples/hello-world-docker/Dockerfile b/samples/hello-world-docker/Dockerfile
new file mode 100644
index 0000000..1c2d5cb
--- /dev/null
+++ b/samples/hello-world-docker/Dockerfile
@@ -0,0 +1,5 @@
+FROM openjdk:8-jdk-alpine
+VOLUME /tmp
+ARG JAR_FILE
+ADD ${JAR_FILE} app.jar
+ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
\ No newline at end of file
diff --git a/samples/hello-world-docker/build.gradle b/samples/hello-world-docker/build.gradle
new file mode 100644
index 0000000..302871a
--- /dev/null
+++ b/samples/hello-world-docker/build.gradle
@@ -0,0 +1,64 @@
+// buildscript 代码块中脚本优先执行
+buildscript {
+
+ // ext 用于定义动态属性
+ ext {
+ springBootVersion = '2.0.0.M4'
+ }
+
+ // 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
+ repositories {
+ //mavenCentral()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
+ }
+
+ // 依赖关系
+ dependencies {
+
+ // classpath 声明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项
+ classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+
+ classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.17.2')
+ }
+}
+
+// 使用插件
+apply plugin: 'java'
+apply plugin: 'eclipse'
+apply plugin: 'org.springframework.boot'
+apply plugin: 'io.spring.dependency-management'
+
+apply plugin: 'com.palantir.docker'
+
+// 指定了生成的编译文件的版本,默认是打成了 jar 包
+group = 'com.waylau.spring.cloud'
+version = '1.0.0'
+
+// 指定编译 .java 文件的 JDK 版本
+sourceCompatibility = 1.8
+
+docker {
+ name "${project.group}/${jar.baseName}"
+ files jar.archivePath
+ buildArgs(['JAR_FILE': "${jar.archiveName}"])
+}
+
+// 使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
+repositories {
+ //mavenCentral()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
+}
+
+// 依赖关系
+dependencies {
+
+ // 该依赖用于编译阶段
+ compile('org.springframework.boot:spring-boot-starter-web')
+
+ // 该依赖用于测试阶段
+ testCompile('org.springframework.boot:spring-boot-starter-test')
+}
diff --git a/samples/hello-world-docker/gradle/wrapper/gradle-wrapper.jar b/samples/hello-world-docker/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8e4144d
Binary files /dev/null and b/samples/hello-world-docker/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/samples/hello-world-docker/gradle/wrapper/gradle-wrapper.properties b/samples/hello-world-docker/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..6f37a7e
--- /dev/null
+++ b/samples/hello-world-docker/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+#Fri Jul 28 13:37:07 BST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+#distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-bin.zip
+distributionUrl=file\:/D:/software/webdev/java/gradle-4.0-all.zip
\ No newline at end of file
diff --git a/samples/hello-world-docker/gradlew b/samples/hello-world-docker/gradlew
new file mode 100644
index 0000000..4453cce
--- /dev/null
+++ b/samples/hello-world-docker/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/samples/hello-world-docker/gradlew.bat b/samples/hello-world-docker/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/samples/hello-world-docker/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/Application.java b/samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/Application.java
new file mode 100644
index 0000000..ba49587
--- /dev/null
+++ b/samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/Application.java
@@ -0,0 +1,18 @@
+package com.waylau.spring.cloud.weather;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * 主应用程序.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java b/samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java
new file mode 100644
index 0000000..3a9dfd1
--- /dev/null
+++ b/samples/hello-world-docker/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java
@@ -0,0 +1,20 @@
+package com.waylau.spring.cloud.weather.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Hello Controller.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@RestController
+public class HelloController {
+
+ @RequestMapping("/hello")
+ public String hello() {
+ return "Hello World! Welcome to visit waylau.com!";
+ }
+
+}
diff --git a/samples/hello-world-docker/src/main/resources/application.properties b/samples/hello-world-docker/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java b/samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java
new file mode 100644
index 0000000..71072b0
--- /dev/null
+++ b/samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java
@@ -0,0 +1,22 @@
+package com.waylau.spring.cloud.weather;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * 主应用测试用例.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class ApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java b/samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java
new file mode 100644
index 0000000..0dd9e77
--- /dev/null
+++ b/samples/hello-world-docker/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java
@@ -0,0 +1,36 @@
+package com.waylau.spring.cloud.weather.controller;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import static org.hamcrest.Matchers.equalTo;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * HelloController Test.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@AutoConfigureMockMvc
+public class HelloControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void testHello() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(content().string(equalTo("Hello World! Welcome to visit waylau.com!")));
+ }
+}
\ No newline at end of file
diff --git a/samples/javase-rest/pom.xml b/samples/javase-rest/pom.xml
index 28d7a44..6d14555 100644
--- a/samples/javase-rest/pom.xml
+++ b/samples/javase-rest/pom.xml
@@ -65,7 +65,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
junit
junit
- 4.12
+ 4.13.1
test
diff --git a/samples/jersey-rest/pom.xml b/samples/jersey-rest/pom.xml
index 2b26444..f9cc48b 100644
--- a/samples/jersey-rest/pom.xml
+++ b/samples/jersey-rest/pom.xml
@@ -42,7 +42,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
junit
junit
- 4.12
+ 4.13.1
test
diff --git a/samples/jms-msg/pom.xml b/samples/jms-msg/pom.xml
index e6b81bf..dd02384 100644
--- a/samples/jms-msg/pom.xml
+++ b/samples/jms-msg/pom.xml
@@ -14,7 +14,7 @@
UTF-8
5.2.3.RELEASE
- 4.12
+ 4.13.1
5.15.11
diff --git a/samples/security-basic/.gitignore b/samples/security-basic/.gitignore
new file mode 100644
index 0000000..fd6098f
--- /dev/null
+++ b/samples/security-basic/.gitignore
@@ -0,0 +1,27 @@
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+/bin/
+/target/
diff --git a/samples/security-basic/dependency-reduced-pom.xml b/samples/security-basic/dependency-reduced-pom.xml
new file mode 100644
index 0000000..47d9e53
--- /dev/null
+++ b/samples/security-basic/dependency-reduced-pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+ com.waylau.spring
+ security-basic
+ security-basic
+ 1.0.0
+
+ waylau.com
+ https://waylau.com
+
+
+
+
+ maven-shade-plugin
+ 3.6.0
+
+
+ package
+
+ shade
+
+
+
+
+ com.waylau.spring.mvc.Application
+
+
+
+
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+
+
+ 5.2.15.RELEASE
+ 5.1.5.RELEASE
+ 9.4.14.v20181114
+ 2.9.7
+
+
diff --git a/samples/security-basic/pom.xml b/samples/security-basic/pom.xml
new file mode 100644
index 0000000..f887935
--- /dev/null
+++ b/samples/security-basic/pom.xml
@@ -0,0 +1,92 @@
+
+ 4.0.0
+ com.waylau.spring
+ security-basic
+ 1.0.0
+ security-basic
+ jar
+
+ waylau.com
+ https://waylau.com
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+
+
+
+ 5.1.5.RELEASE
+ 9.4.14.v20181114
+ 2.9.7
+ 5.2.15.RELEASE
+
+
+
+
+ org.springframework
+ spring-webmvc
+ ${spring.version}
+
+
+ org.eclipse.jetty
+ jetty-servlet
+ ${jetty.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+
+
+ org.springframework.security
+ spring-security-web
+ ${spring-security.version}
+
+
+ org.springframework.security
+ spring-security-config
+ ${spring-security.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.6.0
+
+
+ package
+
+ shade
+
+
+
+
+ com.waylau.spring.mvc.Application
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/security-basic/src/main/java/com/waylau/spring/mvc/Application.java b/samples/security-basic/src/main/java/com/waylau/spring/mvc/Application.java
new file mode 100644
index 0000000..c50bcec
--- /dev/null
+++ b/samples/security-basic/src/main/java/com/waylau/spring/mvc/Application.java
@@ -0,0 +1,18 @@
+/**
+ * Welcome to https://waylau.com
+ */
+package com.waylau.spring.mvc;
+
+/**
+ * Application Main.
+ *
+ * @since 1.0.0 2018年3月21日
+ * @author Way Lau
+ */
+public class Application {
+
+ public static void main(String[] args) throws Exception {
+ new JettyServer().run();
+ }
+
+}
diff --git a/samples/security-basic/src/main/java/com/waylau/spring/mvc/JettyServer.java b/samples/security-basic/src/main/java/com/waylau/spring/mvc/JettyServer.java
new file mode 100644
index 0000000..889c40c
--- /dev/null
+++ b/samples/security-basic/src/main/java/com/waylau/spring/mvc/JettyServer.java
@@ -0,0 +1,59 @@
+package com.waylau.spring.mvc;
+
+import java.util.EnumSet;
+import javax.servlet.DispatcherType;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.springframework.web.context.ContextLoaderListener;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
+import org.springframework.web.filter.DelegatingFilterProxy;
+import org.springframework.web.servlet.DispatcherServlet;
+import com.waylau.spring.mvc.configuration.AppConfiguration;
+
+/**
+ * Jetty Server.
+ *
+ * @since 1.0.0 2018年3月21日
+ * @author Way Lau
+ */
+public class JettyServer {
+ private static final int DEFAULT_PORT = 8080;
+ private static final String CONTEXT_PATH = "/";
+ private static final String MAPPING_URL = "/*";
+
+ public void run() throws Exception {
+ Server server = new Server(DEFAULT_PORT);
+ server.setHandler(servletContextHandler(webApplicationContext()));
+ server.start();
+ server.join();
+ }
+
+ private ServletContextHandler servletContextHandler(WebApplicationContext ct) {
+ // 启用Session管理器
+ ServletContextHandler handler =
+ new ServletContextHandler(ServletContextHandler.SESSIONS);
+
+ handler.setContextPath(CONTEXT_PATH);
+ handler.addServlet(new ServletHolder(new DispatcherServlet(ct)),
+ MAPPING_URL);
+ handler.addEventListener(new ContextLoaderListener(ct));
+
+ // 添加Spring Security过滤器
+ FilterHolder filterHolder=new FilterHolder(DelegatingFilterProxy.class);
+ filterHolder.setName("springSecurityFilterChain");
+ handler.addFilter(filterHolder, MAPPING_URL,
+ EnumSet.of(DispatcherType.REQUEST));
+
+ return handler;
+ }
+
+ private WebApplicationContext webApplicationContext() {
+ AnnotationConfigWebApplicationContext context =
+ new AnnotationConfigWebApplicationContext();
+ context.register(AppConfiguration.class);
+ return context;
+ }
+}
\ No newline at end of file
diff --git a/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/AppConfiguration.java b/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/AppConfiguration.java
new file mode 100644
index 0000000..7166073
--- /dev/null
+++ b/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/AppConfiguration.java
@@ -0,0 +1,18 @@
+package com.waylau.spring.mvc.configuration;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * App Configuration.
+ *
+ * @since 1.0.0 2018年3月21日
+ * @author Way Lau
+ */
+@Configuration
+@ComponentScan(basePackages = { "com.waylau.spring" })
+@Import({ WebSecurityConfig.class, MvcConfiguration.class })
+public class AppConfiguration {
+
+}
diff --git a/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/MvcConfiguration.java b/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/MvcConfiguration.java
new file mode 100644
index 0000000..e0d5290
--- /dev/null
+++ b/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/MvcConfiguration.java
@@ -0,0 +1,25 @@
+package com.waylau.spring.mvc.configuration;
+
+import java.util.List;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * MVC Configuration.
+ *
+ * @since 1.0.0 2018年3月21日
+ * @author Way Lau
+ */
+@EnableWebMvc
+@Configuration
+public class MvcConfiguration implements WebMvcConfigurer {
+
+ @Override
+ public void extendMessageConverters(List> converters) {
+ converters.add(new MappingJackson2HttpMessageConverter());
+ }
+}
diff --git a/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/WebSecurityConfig.java b/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/WebSecurityConfig.java
new file mode 100644
index 0000000..61fe249
--- /dev/null
+++ b/samples/security-basic/src/main/java/com/waylau/spring/mvc/configuration/WebSecurityConfig.java
@@ -0,0 +1,49 @@
+package com.waylau.spring.mvc.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
+
+/**
+ * Web Security Configuration.
+ *
+ * @since 1.0.0 2018年3月21日
+ * @author Way Lau
+ */
+@EnableWebSecurity // 启用Spring Security功能
+public class WebSecurityConfig
+ extends WebSecurityConfigurerAdapter {
+
+ /**
+ * 自定义配置
+ */
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests().anyRequest().authenticated()//所有请求都需认证
+ .and()
+ .formLogin() // 使用form表单登录
+ .and()
+ .httpBasic(); // HTTP基本认证
+ }
+
+ @SuppressWarnings("deprecation")
+ @Bean
+ @Override
+ public UserDetailsService userDetailsService() {
+ InMemoryUserDetailsManager manager =
+ new InMemoryUserDetailsManager();
+
+ manager.createUser(
+ User.withDefaultPasswordEncoder() // 密码编码器
+ .username("waylau") // 用户名
+ .password("123") // 密码
+ .roles("USER") // 角色
+ .build()
+ );
+ return manager;
+ }
+}
\ No newline at end of file
diff --git a/samples/security-basic/src/main/java/com/waylau/spring/mvc/controller/HelloController.java b/samples/security-basic/src/main/java/com/waylau/spring/mvc/controller/HelloController.java
new file mode 100644
index 0000000..9d7cab7
--- /dev/null
+++ b/samples/security-basic/src/main/java/com/waylau/spring/mvc/controller/HelloController.java
@@ -0,0 +1,27 @@
+package com.waylau.spring.mvc.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.waylau.spring.mvc.vo.User;
+
+
+/**
+ * Hello 控制器.
+ *
+ * @since 1.0.0 2018年3月21日
+ * @author Way Lau
+ */
+@RestController
+public class HelloController {
+
+ @RequestMapping("/hello")
+ public String hello() {
+ return "Hello World! Welcome to visit waylau.com!";
+ }
+
+ @RequestMapping("/hello/way")
+ public User helloWay() {
+ return new User("Way Lau", 30);
+ }
+}
diff --git a/samples/security-basic/src/main/java/com/waylau/spring/mvc/vo/User.java b/samples/security-basic/src/main/java/com/waylau/spring/mvc/vo/User.java
new file mode 100644
index 0000000..208153b
--- /dev/null
+++ b/samples/security-basic/src/main/java/com/waylau/spring/mvc/vo/User.java
@@ -0,0 +1,37 @@
+/**
+ * Welcome to https://waylau.com
+ */
+package com.waylau.spring.mvc.vo;
+
+/**
+ * User.
+ *
+ * @since 1.0.0 2018年2月10日
+ * @author Way Lau
+ */
+public class User {
+ private String username;
+ private Integer age;
+
+ public User(String username, Integer age) {
+ this.username = username;
+ this.age = age;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+}
diff --git a/samples/spring-boot-rest/.gitignore b/samples/spring-boot-rest/.gitignore
new file mode 100644
index 0000000..4c6eb77
--- /dev/null
+++ b/samples/spring-boot-rest/.gitignore
@@ -0,0 +1,26 @@
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+/bin/
diff --git a/samples/spring-boot-rest/build.gradle b/samples/spring-boot-rest/build.gradle
new file mode 100644
index 0000000..bfa75dd
--- /dev/null
+++ b/samples/spring-boot-rest/build.gradle
@@ -0,0 +1,54 @@
+// buildscript нűִ
+buildscript {
+
+ // ext ڶ嶯̬
+ ext {
+ springBootVersion = '2.0.0.M4'
+ }
+
+ // ʹMavenֿ⼰SpringԼIJֿ⣨Ҳָֿ⣩
+ repositories {
+ //mavenCentral()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
+ }
+
+ // ϵ
+ dependencies {
+
+ // classpath ִĽűʱClassLoader ʹЩ
+ classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+ }
+}
+
+// ʹò
+apply plugin: 'java'
+apply plugin: 'eclipse'
+apply plugin: 'org.springframework.boot'
+apply plugin: 'io.spring.dependency-management'
+
+// ָɵıļİ汾ĬǴ jar
+group = 'com.waylau.spring.cloud'
+version = '1.0.0'
+
+// ָ .java ļ JDK 汾
+sourceCompatibility = 1.8
+
+// ʹMavenֿ⼰SpringԼIJֿ⣨Ҳָֿ⣩
+repositories {
+ //mavenCentral()
+ maven { url "https://repo.spring.io/snapshot" }
+ maven { url "https://repo.spring.io/milestone" }
+ maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
+}
+
+// ϵ
+dependencies {
+
+ // ڱ
+ compile('org.springframework.boot:spring-boot-starter-web')
+
+ // ڲԽ
+ testCompile('org.springframework.boot:spring-boot-starter-test')
+}
diff --git a/samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.jar b/samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8e4144d
Binary files /dev/null and b/samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.properties b/samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..6f37a7e
--- /dev/null
+++ b/samples/spring-boot-rest/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+#Fri Jul 28 13:37:07 BST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+#distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.2-bin.zip
+distributionUrl=file\:/D:/software/webdev/java/gradle-4.0-all.zip
\ No newline at end of file
diff --git a/samples/spring-boot-rest/gradlew b/samples/spring-boot-rest/gradlew
new file mode 100644
index 0000000..4453cce
--- /dev/null
+++ b/samples/spring-boot-rest/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/samples/spring-boot-rest/gradlew.bat b/samples/spring-boot-rest/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/samples/spring-boot-rest/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/Application.java b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/Application.java
new file mode 100644
index 0000000..ba49587
--- /dev/null
+++ b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/Application.java
@@ -0,0 +1,18 @@
+package com.waylau.spring.cloud.weather;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * 主应用程序.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java
new file mode 100644
index 0000000..3a9dfd1
--- /dev/null
+++ b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/HelloController.java
@@ -0,0 +1,20 @@
+package com.waylau.spring.cloud.weather.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Hello Controller.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@RestController
+public class HelloController {
+
+ @RequestMapping("/hello")
+ public String hello() {
+ return "Hello World! Welcome to visit waylau.com!";
+ }
+
+}
diff --git a/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/UserController.java b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/UserController.java
new file mode 100644
index 0000000..6235e20
--- /dev/null
+++ b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/controller/UserController.java
@@ -0,0 +1,89 @@
+package com.waylau.spring.cloud.weather.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.waylau.spring.cloud.weather.domain.User;
+import com.waylau.spring.cloud.weather.repository.UserRepository;
+
+/**
+ * User Controller.
+ *
+ * @author Way Lau
+ * @date 2017年10月8日
+ */
+@RestController
+@RequestMapping("/users")
+public class UserController {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ /**
+ * 获取用户列表
+ *
+ * @return
+ */
+ @GetMapping
+ public List getUsers() {
+ return userRepository.listUser();
+ }
+
+ /**
+ * 获取用户信息
+ *
+ * @param id
+ * @return
+ */
+ @GetMapping("/{id}")
+ public User getUser(@PathVariable("id") Long id) {
+ return userRepository.getUserById(id);
+ }
+
+ /**
+ * 保存用户
+ *
+ * @param user
+ */
+ @PostMapping
+ public User createUser(@RequestBody User user) {
+ return userRepository.saveOrUpateUser(user);
+ }
+
+ /**
+ * 修改用户
+ *
+ * @param id
+ * @param user
+ */
+ @PutMapping("/{id}")
+ public void updateUser(@PathVariable("id") Long id, @RequestBody User user) {
+ User oldUser = this.getUser(id);
+
+ if (oldUser != null) {
+ user.setId(id);
+ userRepository.saveOrUpateUser(user);
+ }
+
+ }
+
+ /**
+ * 删除用户
+ *
+ * @param id
+ * @return
+ */
+ @DeleteMapping("/{id}")
+ public void deleteUser(@PathVariable("id") Long id) {
+ userRepository.deleteUser(id);
+ }
+}
diff --git a/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/domain/User.java b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/domain/User.java
new file mode 100644
index 0000000..5c05e9c
--- /dev/null
+++ b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/domain/User.java
@@ -0,0 +1,53 @@
+package com.waylau.spring.cloud.weather.domain;
+
+/**
+ * User.
+ *
+ * @since 1.0.0 2017年10月8日
+ * @author Way Lau
+ */
+public class User {
+
+ private Long id;
+
+ private String name;
+
+ private String email;
+
+ public User() {
+ }
+
+ public User(String name, String email) {
+ this.name = name;
+ this.email = email;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("User[id=%d, name='%s', email='%s']", id, name, email);
+ }
+}
diff --git a/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepository.java b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepository.java
new file mode 100644
index 0000000..937f51f
--- /dev/null
+++ b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepository.java
@@ -0,0 +1,44 @@
+package com.waylau.spring.cloud.weather.repository;
+
+import java.util.List;
+
+import com.waylau.spring.cloud.weather.domain.User;
+
+/**
+ * 用户仓库.
+ *
+ * @since 1.0.0 2017年10月8日
+ * @author Way Lau
+ */
+public interface UserRepository {
+
+ /**
+ * 新增或者修改用户
+ *
+ * @param user
+ * @return
+ */
+ User saveOrUpateUser(User user);
+
+ /**
+ * 删除用户
+ *
+ * @param id
+ */
+ void deleteUser(Long id);
+
+ /**
+ * 根据用户id获取用户
+ *
+ * @param id
+ * @return
+ */
+ User getUserById(Long id);
+
+ /**
+ * 获取所有用户的列表
+ *
+ * @return
+ */
+ List listUser();
+}
diff --git a/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepositoryImpl.java b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepositoryImpl.java
new file mode 100644
index 0000000..be59679
--- /dev/null
+++ b/samples/spring-boot-rest/src/main/java/com/waylau/spring/cloud/weather/repository/UserRepositoryImpl.java
@@ -0,0 +1,52 @@
+package com.waylau.spring.cloud.weather.repository;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.springframework.stereotype.Repository;
+
+import com.waylau.spring.cloud.weather.domain.User;
+
+/**
+ * 用户资源库.
+ *
+ * @version 1.0.0 2017年10月8日
+ * @author Way Lau
+ */
+@Repository
+public class UserRepositoryImpl implements UserRepository {
+
+ private static AtomicLong counter = new AtomicLong();
+
+ private final ConcurrentMap userMap = new ConcurrentHashMap();
+
+ @Override
+ public User saveOrUpateUser(User user) {
+ Long id = user.getId();
+ if (id == null || id <= 0) {
+ id = counter.incrementAndGet();
+ user.setId(id);
+ }
+ this.userMap.put(id, user);
+ return this.getUserById(id);
+ }
+
+ @Override
+ public void deleteUser(Long id) {
+ this.userMap.remove(id);
+ }
+
+ @Override
+ public User getUserById(Long id) {
+ return this.userMap.get(id);
+ }
+
+ @Override
+ public List listUser() {
+ return new ArrayList(this.userMap.values());
+ }
+
+}
diff --git a/samples/spring-boot-rest/src/main/resources/application.properties b/samples/spring-boot-rest/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java b/samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java
new file mode 100644
index 0000000..71072b0
--- /dev/null
+++ b/samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/ApplicationTests.java
@@ -0,0 +1,22 @@
+package com.waylau.spring.cloud.weather;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * 主应用测试用例.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class ApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java b/samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java
new file mode 100644
index 0000000..0dd9e77
--- /dev/null
+++ b/samples/spring-boot-rest/src/test/java/com/waylau/spring/cloud/weather/controller/HelloControllerTest.java
@@ -0,0 +1,36 @@
+package com.waylau.spring.cloud.weather.controller;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import static org.hamcrest.Matchers.equalTo;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * HelloController Test.
+ *
+ * @since 1.0.0 2017年9月27日
+ * @author Way Lau
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@AutoConfigureMockMvc
+public class HelloControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void testHello() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(content().string(equalTo("Hello World! Welcome to visit waylau.com!")));
+ }
+}
\ No newline at end of file
diff --git a/samples/zk-registry-discovery/pom.xml b/samples/zk-registry-discovery/pom.xml
index 5de6bfc..336e525 100644
--- a/samples/zk-registry-discovery/pom.xml
+++ b/samples/zk-registry-discovery/pom.xml
@@ -36,7 +36,7 @@
junit
junit
- 4.12
+ 4.13.1
test