diff --git a/Chapter2-1-2/pom.xml b/Chapter2-1-2/pom.xml
new file mode 100644
index 00000000..f869ccfc
--- /dev/null
+++ b/Chapter2-1-2/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+ com.didispace
+ Chapter2-1-2
+ 1.0.0
+ jar
+
+ Chapter2-1-2
+ Spring Boot 2.0 features : Application Events and Listeners
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter2-1-2/src/main/java/com/didispace/Application.java b/Chapter2-1-2/src/main/java/com/didispace/Application.java
new file mode 100755
index 00000000..bcfd43a8
--- /dev/null
+++ b/Chapter2-1-2/src/main/java/com/didispace/Application.java
@@ -0,0 +1,31 @@
+package com.didispace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+@Slf4j
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @Bean
+ public DataLoader dataLoader() {
+ return new DataLoader();
+ }
+
+ @Slf4j
+ static class DataLoader implements CommandLineRunner {
+
+ @Override
+ public void run(String... strings) throws Exception {
+ log.info("Loading data...");
+ }
+ }
+
+}
diff --git a/Chapter2-1-2/src/main/java/com/didispace/ApplicationEnvironmentPreparedEventListener.java b/Chapter2-1-2/src/main/java/com/didispace/ApplicationEnvironmentPreparedEventListener.java
new file mode 100644
index 00000000..da2a47cb
--- /dev/null
+++ b/Chapter2-1-2/src/main/java/com/didispace/ApplicationEnvironmentPreparedEventListener.java
@@ -0,0 +1,15 @@
+package com.didispace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
+import org.springframework.context.ApplicationListener;
+
+@Slf4j
+public class ApplicationEnvironmentPreparedEventListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
+ log.info("......ApplicationEnvironmentPreparedEvent......");
+ }
+
+}
diff --git a/Chapter2-1-2/src/main/java/com/didispace/ApplicationFailedEventListener.java b/Chapter2-1-2/src/main/java/com/didispace/ApplicationFailedEventListener.java
new file mode 100644
index 00000000..457ff47f
--- /dev/null
+++ b/Chapter2-1-2/src/main/java/com/didispace/ApplicationFailedEventListener.java
@@ -0,0 +1,15 @@
+package com.didispace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.event.ApplicationFailedEvent;
+import org.springframework.context.ApplicationListener;
+
+@Slf4j
+public class ApplicationFailedEventListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(ApplicationFailedEvent event) {
+ log.info("......ApplicationFailedEvent......");
+ }
+
+}
diff --git a/Chapter2-1-2/src/main/java/com/didispace/ApplicationPreparedEventListener.java b/Chapter2-1-2/src/main/java/com/didispace/ApplicationPreparedEventListener.java
new file mode 100644
index 00000000..5b529617
--- /dev/null
+++ b/Chapter2-1-2/src/main/java/com/didispace/ApplicationPreparedEventListener.java
@@ -0,0 +1,15 @@
+package com.didispace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.event.ApplicationPreparedEvent;
+import org.springframework.context.ApplicationListener;
+
+@Slf4j
+public class ApplicationPreparedEventListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(ApplicationPreparedEvent event) {
+ log.info("......ApplicationPreparedEvent......");
+ }
+
+}
diff --git a/Chapter2-1-2/src/main/java/com/didispace/ApplicationReadyEventListener.java b/Chapter2-1-2/src/main/java/com/didispace/ApplicationReadyEventListener.java
new file mode 100644
index 00000000..9193a750
--- /dev/null
+++ b/Chapter2-1-2/src/main/java/com/didispace/ApplicationReadyEventListener.java
@@ -0,0 +1,15 @@
+package com.didispace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.ApplicationListener;
+
+@Slf4j
+public class ApplicationReadyEventListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(ApplicationReadyEvent event) {
+ log.info("......ApplicationReadyEvent......");
+ }
+
+}
diff --git a/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartedEventListener.java b/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartedEventListener.java
new file mode 100644
index 00000000..3b47eba6
--- /dev/null
+++ b/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartedEventListener.java
@@ -0,0 +1,16 @@
+package com.didispace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.ApplicationListener;
+
+@Slf4j
+public class ApplicationStartedEventListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(ApplicationStartedEvent event) {
+ log.info("......ApplicationStartedEvent......");
+ }
+
+}
diff --git a/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartingEventListener.java b/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartingEventListener.java
new file mode 100644
index 00000000..effcb14f
--- /dev/null
+++ b/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartingEventListener.java
@@ -0,0 +1,15 @@
+package com.didispace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.event.ApplicationStartingEvent;
+import org.springframework.context.ApplicationListener;
+
+@Slf4j
+public class ApplicationStartingEventListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(ApplicationStartingEvent event) {
+ log.info("......ApplicationStartingEvent......");
+ }
+
+}
diff --git a/Chapter2-1-2/src/main/resources/META-INF/spring.factories b/Chapter2-1-2/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..15177da6
--- /dev/null
+++ b/Chapter2-1-2/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,6 @@
+org.springframework.context.ApplicationListener=com.didispace.ApplicationEnvironmentPreparedEventListener,\
+ com.didispace.ApplicationFailedEventListener,\
+ com.didispace.ApplicationPreparedEventListener,\
+ com.didispace.ApplicationReadyEventListener,\
+ com.didispace.ApplicationStartedEventListener,\
+ com.didispace.ApplicationStartingEventListener
\ No newline at end of file
diff --git a/Chapter2-1-2/src/main/resources/application.properties b/Chapter2-1-2/src/main/resources/application.properties
new file mode 100755
index 00000000..e69de29b
diff --git a/Chapter2-2-1/pom.xml b/Chapter2-2-1/pom.xml
new file mode 100644
index 00000000..c7eddd26
--- /dev/null
+++ b/Chapter2-2-1/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+ com.didispace
+ Chapter2-2-1
+ 1.0.0
+ jar
+
+ Chapter2-2-1
+ Spring Boot 2 : Relaxed Binding
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.0.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.20
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter2-2-1/src/main/java/com/didispace/Application.java b/Chapter2-2-1/src/main/java/com/didispace/Application.java
new file mode 100755
index 00000000..f06a4a25
--- /dev/null
+++ b/Chapter2-2-1/src/main/java/com/didispace/Application.java
@@ -0,0 +1,44 @@
+package com.didispace;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
+import org.springframework.boot.context.properties.bind.Bindable;
+import org.springframework.boot.context.properties.bind.Binder;
+import org.springframework.context.ApplicationContext;
+
+import java.util.List;
+
+/**
+ *
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog http://blog.didispace.com
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ ApplicationContext context = SpringApplication.run(Application.class, args);
+
+ Binder binder = Binder.get(context.getEnvironment());
+
+ // 绑定简单配置
+ FooProperties foo = binder.bind("com.didispace", Bindable.of(FooProperties.class)).get();
+ System.out.println(foo.getFoo());
+
+ // 绑定List配置
+ List post = binder.bind("com.didispace.post", Bindable.listOf(String.class)).get();
+ System.out.println(post);
+
+ List posts = binder.bind("com.didispace.posts", Bindable.listOf(PostInfo.class)).get();
+ System.out.println(posts);
+
+ // 读取配置
+ System.out.println(context.getEnvironment().containsProperty("com.didispace.database-platform"));
+ System.out.println(context.getEnvironment().containsProperty("com.didispace.databasePlatform"));
+
+ }
+
+}
diff --git a/Chapter2-2-1/src/main/java/com/didispace/FooProperties.java b/Chapter2-2-1/src/main/java/com/didispace/FooProperties.java
new file mode 100644
index 00000000..9fdf6e22
--- /dev/null
+++ b/Chapter2-2-1/src/main/java/com/didispace/FooProperties.java
@@ -0,0 +1,14 @@
+package com.didispace;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "com.didispace")
+public class FooProperties {
+
+ private String foo;
+
+ private String databasePlatform;
+
+}
\ No newline at end of file
diff --git a/Chapter2-2-1/src/main/java/com/didispace/PostInfo.java b/Chapter2-2-1/src/main/java/com/didispace/PostInfo.java
new file mode 100644
index 00000000..6df554fe
--- /dev/null
+++ b/Chapter2-2-1/src/main/java/com/didispace/PostInfo.java
@@ -0,0 +1,13 @@
+package com.didispace;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties
+public class PostInfo {
+
+ private String title;
+ private String content;
+
+}
diff --git a/Chapter2-2-1/src/main/resources/application.properties b/Chapter2-2-1/src/main/resources/application.properties
new file mode 100755
index 00000000..df1d5f5a
--- /dev/null
+++ b/Chapter2-2-1/src/main/resources/application.properties
@@ -0,0 +1,10 @@
+com.didispace.foo=bar
+com.didispace.database-platform=sql
+
+com.didispace.post[0]=Why Spring Boot
+com.didispace.post[1]=Why Spring Cloud
+
+com.didispace.posts[0].title=Why Spring Boot
+com.didispace.posts[0].content=It is perfect!
+com.didispace.posts[1].title=Why Spring Cloud
+com.didispace.posts[1].content=It is perfect too!
diff --git a/Chapter3-1-5/src/main/java/com/didispace/web/UserController.java b/Chapter3-1-5/src/main/java/com/didispace/web/UserController.java
index 1a504faf..3363bfd9 100755
--- a/Chapter3-1-5/src/main/java/com/didispace/web/UserController.java
+++ b/Chapter3-1-5/src/main/java/com/didispace/web/UserController.java
@@ -36,7 +36,7 @@ public String postUser(@RequestBody User user) {
}
@ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息")
- @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
+ @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "path")
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public User getUser(@PathVariable Long id) {
return users.get(id);
@@ -44,7 +44,7 @@ public User getUser(@PathVariable Long id) {
@ApiOperation(value="更新用户详细信息", notes="根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
@ApiImplicitParams({
- @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"),
+ @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "path"),
@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
})
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
@@ -57,7 +57,7 @@ public String putUser(@PathVariable Long id, @RequestBody User user) {
}
@ApiOperation(value="删除用户", notes="根据url的id来指定删除对象")
- @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
+ @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "path")
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public String deleteUser(@PathVariable Long id) {
users.remove(id);
diff --git a/Chapter3-1-7/pom.xml b/Chapter3-1-7/pom.xml
new file mode 100644
index 00000000..660637b3
--- /dev/null
+++ b/Chapter3-1-7/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+ com.didispace
+ Chapter3-1-7
+ 1.0.0
+ jar
+
+ Chapter3-1-7
+ Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.10.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.20
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter3-1-7/src/main/java/com/didispace/Application.java b/Chapter3-1-7/src/main/java/com/didispace/Application.java
new file mode 100755
index 00000000..7ac57d25
--- /dev/null
+++ b/Chapter3-1-7/src/main/java/com/didispace/Application.java
@@ -0,0 +1,58 @@
+package com.didispace;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDate;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog http://blog.didispace.com
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @RestController
+ class HelloController {
+
+ @PostMapping("/user")
+ public UserDto user(@RequestBody UserDto userDto) throws Exception {
+ return userDto;
+ }
+
+ }
+
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ static class UserDto {
+
+ private String userName;
+ private LocalDate birthday;
+
+ }
+
+ @Bean
+ public ObjectMapper serializingObjectMapper() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ objectMapper.registerModule(new JavaTimeModule());
+ return objectMapper;
+ }
+
+}
diff --git a/Chapter3-1-7/src/main/resources/application.properties b/Chapter3-1-7/src/main/resources/application.properties
new file mode 100755
index 00000000..e69de29b
diff --git a/Chapter3-2-11/pom.xml b/Chapter3-2-11/pom.xml
new file mode 100755
index 00000000..d9ac4cf1
--- /dev/null
+++ b/Chapter3-2-11/pom.xml
@@ -0,0 +1,68 @@
+
+
+ 4.0.0
+
+ com.didispace
+ Chapter3-2-11
+ 1.0.0
+ jar
+
+ Chapter3-2-11
+ Spring Boot project
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.10.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+
+ com.spring4all
+ mongodb-plus-spring-boot-starter
+ 1.0.0.RELEASE
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.12
+ provided
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/Chapter3-2-11/src/main/java/com/didispace/Application.java b/Chapter3-2-11/src/main/java/com/didispace/Application.java
new file mode 100755
index 00000000..89042041
--- /dev/null
+++ b/Chapter3-2-11/src/main/java/com/didispace/Application.java
@@ -0,0 +1,15 @@
+package com.didispace;
+
+import com.spring4all.mongodb.EnableMongoPlus;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@EnableMongoPlus
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/Chapter3-2-11/src/main/resources/application.properties b/Chapter3-2-11/src/main/resources/application.properties
new file mode 100644
index 00000000..e3f19a14
--- /dev/null
+++ b/Chapter3-2-11/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+spring.data.mongodb.uri=mongodb://localhost:27017/test
+
+spring.data.mongodb.option.min-connection-per-host=20
+spring.data.mongodb.option.max-connection-per-host=200
diff --git a/Chapter3-2-11/src/test/java/com/didispace/ApplicationTests.java b/Chapter3-2-11/src/test/java/com/didispace/ApplicationTests.java
new file mode 100755
index 00000000..b3671364
--- /dev/null
+++ b/Chapter3-2-11/src/test/java/com/didispace/ApplicationTests.java
@@ -0,0 +1,27 @@
+package com.didispace;
+
+import com.mongodb.MongoClient;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Slf4j
+public class ApplicationTests {
+
+ @Autowired
+ private MongoClient mongoClient;
+
+ @Test
+ public void test() throws Exception {
+ log.info("MinConnectionsPerHost = {}, MaxConnectionsPerHost = {}",
+ mongoClient.getMongoClientOptions().getMinConnectionsPerHost(),
+ mongoClient.getMongoClientOptions().getConnectionsPerHost());
+ }
+
+}
diff --git a/Chapter4-1-3/pom.xml b/Chapter4-1-3/pom.xml
new file mode 100644
index 00000000..b72b7802
--- /dev/null
+++ b/Chapter4-1-3/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ com.didispace
+ Chapter4-1-3
+ 1.0.0
+ jar
+
+ Chapter4-1-3
+ Spring Boot project
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.10.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.20
+ provided
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter4-1-3/src/main/java/com/didispace/Application.java b/Chapter4-1-3/src/main/java/com/didispace/Application.java
new file mode 100644
index 00000000..84d84ef2
--- /dev/null
+++ b/Chapter4-1-3/src/main/java/com/didispace/Application.java
@@ -0,0 +1,38 @@
+package com.didispace;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @EnableAsync
+ @Configuration
+ class TaskPoolConfig {
+
+ @Bean("taskExecutor")
+ public Executor taskExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(10);
+ executor.setMaxPoolSize(20);
+ executor.setQueueCapacity(200);
+ executor.setKeepAliveSeconds(60);
+ executor.setThreadNamePrefix("taskExecutor-");
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ return executor;
+ }
+ }
+
+}
diff --git a/Chapter4-1-3/src/main/java/com/didispace/async/Task.java b/Chapter4-1-3/src/main/java/com/didispace/async/Task.java
new file mode 100644
index 00000000..07891f82
--- /dev/null
+++ b/Chapter4-1-3/src/main/java/com/didispace/async/Task.java
@@ -0,0 +1,48 @@
+package com.didispace.async;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.Random;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @date 16/5/16 下午12:58.
+ * @blog http://blog.didispace.com
+ */
+@Slf4j
+@Component
+public class Task {
+
+ public static Random random = new Random();
+
+ @Async("taskExecutor")
+ public void doTaskOne() throws Exception {
+ log.info("开始做任务一");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务一,耗时:" + (end - start) + "毫秒");
+ }
+
+ @Async("taskExecutor")
+ public void doTaskTwo() throws Exception {
+ log.info("开始做任务二");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务二,耗时:" + (end - start) + "毫秒");
+ }
+
+ @Async("taskExecutor")
+ public void doTaskThree() throws Exception {
+ log.info("开始做任务三");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务三,耗时:" + (end - start) + "毫秒");
+ }
+
+}
diff --git a/Chapter4-1-3/src/main/resources/application.properties b/Chapter4-1-3/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/Chapter4-1-3/src/test/java/com/didispace/ApplicationTests.java b/Chapter4-1-3/src/test/java/com/didispace/ApplicationTests.java
new file mode 100644
index 00000000..03d3fab7
--- /dev/null
+++ b/Chapter4-1-3/src/test/java/com/didispace/ApplicationTests.java
@@ -0,0 +1,28 @@
+package com.didispace;
+
+import com.didispace.async.Task;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest
+public class ApplicationTests {
+
+ @Autowired
+ private Task task;
+
+ @Test
+ public void test() throws Exception {
+
+ task.doTaskOne();
+ task.doTaskTwo();
+ task.doTaskThree();
+
+ Thread.currentThread().join();
+ }
+
+}
diff --git a/Chapter4-1-4/pom.xml b/Chapter4-1-4/pom.xml
new file mode 100644
index 00000000..c8b4be29
--- /dev/null
+++ b/Chapter4-1-4/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+ com.didispace
+ Chapter4-1-4
+ 1.0.0
+ jar
+
+ Chapter4-1-4
+ Spring Boot project
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.10.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.20
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter4-1-4/src/main/java/com/didispace/Application.java b/Chapter4-1-4/src/main/java/com/didispace/Application.java
new file mode 100644
index 00000000..5de0f631
--- /dev/null
+++ b/Chapter4-1-4/src/main/java/com/didispace/Application.java
@@ -0,0 +1,36 @@
+package com.didispace;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+
+import java.util.concurrent.Executor;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @EnableAsync
+ @Configuration
+ class TaskPoolConfig {
+
+ @Bean("taskExecutor")
+ public Executor taskExecutor() {
+ ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
+ executor.setPoolSize(20);
+ executor.setThreadNamePrefix("taskExecutor-");
+
+ executor.setWaitForTasksToCompleteOnShutdown(true);
+ executor.setAwaitTerminationSeconds(60);
+ return executor;
+ }
+
+ }
+
+}
diff --git a/Chapter4-1-4/src/main/java/com/didispace/async/Task.java b/Chapter4-1-4/src/main/java/com/didispace/async/Task.java
new file mode 100644
index 00000000..ac0b102c
--- /dev/null
+++ b/Chapter4-1-4/src/main/java/com/didispace/async/Task.java
@@ -0,0 +1,49 @@
+package com.didispace.async;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @date 16/5/16 下午12:58.
+ * @blog http://blog.didispace.com
+ */
+@Slf4j
+@Component
+public class Task {
+
+ @Autowired
+ private StringRedisTemplate stringRedisTemplate;
+
+ @Async("taskExecutor")
+ public void doTaskOne() throws Exception {
+ log.info("开始做任务一");
+ long start = System.currentTimeMillis();
+ log.info(stringRedisTemplate.randomKey());
+ long end = System.currentTimeMillis();
+ log.info("完成任务一,耗时:" + (end - start) + "毫秒");
+ }
+
+ @Async("taskExecutor")
+ public void doTaskTwo() throws Exception {
+ log.info("开始做任务二");
+ long start = System.currentTimeMillis();
+ log.info(stringRedisTemplate.randomKey());
+ long end = System.currentTimeMillis();
+ log.info("完成任务二,耗时:" + (end - start) + "毫秒");
+ }
+
+ @Async("taskExecutor")
+ public void doTaskThree() throws Exception {
+ log.info("开始做任务三");
+ long start = System.currentTimeMillis();
+ log.info(stringRedisTemplate.randomKey());
+ long end = System.currentTimeMillis();
+ log.info("完成任务三,耗时:" + (end - start) + "毫秒");
+ }
+
+}
diff --git a/Chapter4-1-4/src/main/resources/application.properties b/Chapter4-1-4/src/main/resources/application.properties
new file mode 100644
index 00000000..806eddf3
--- /dev/null
+++ b/Chapter4-1-4/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+spring.redis.pool.max-wait=5000
+spring.redis.pool.max-active=10
diff --git a/Chapter4-1-4/src/test/java/com/didispace/ApplicationTests.java b/Chapter4-1-4/src/test/java/com/didispace/ApplicationTests.java
new file mode 100644
index 00000000..61107f29
--- /dev/null
+++ b/Chapter4-1-4/src/test/java/com/didispace/ApplicationTests.java
@@ -0,0 +1,34 @@
+package com.didispace;
+
+import com.didispace.async.Task;
+import lombok.SneakyThrows;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest
+public class ApplicationTests {
+
+ @Autowired
+ private Task task;
+
+ @Test
+ @SneakyThrows
+ public void test() {
+
+ for (int i = 0; i < 10000; i++) {
+ task.doTaskOne();
+ task.doTaskTwo();
+ task.doTaskThree();
+
+ if (i == 9999) {
+ System.exit(0);
+ }
+ }
+ }
+
+}
diff --git a/Chapter4-1-5/pom.xml b/Chapter4-1-5/pom.xml
new file mode 100644
index 00000000..524627d6
--- /dev/null
+++ b/Chapter4-1-5/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ com.didispace
+ Chapter4-1-5
+ 1.0.0
+ jar
+
+ Chapter4-1-5
+ Spring Boot project
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.10.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.20
+ provided
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter4-1-5/src/main/java/com/didispace/Application.java b/Chapter4-1-5/src/main/java/com/didispace/Application.java
new file mode 100644
index 00000000..84d84ef2
--- /dev/null
+++ b/Chapter4-1-5/src/main/java/com/didispace/Application.java
@@ -0,0 +1,38 @@
+package com.didispace;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @EnableAsync
+ @Configuration
+ class TaskPoolConfig {
+
+ @Bean("taskExecutor")
+ public Executor taskExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(10);
+ executor.setMaxPoolSize(20);
+ executor.setQueueCapacity(200);
+ executor.setKeepAliveSeconds(60);
+ executor.setThreadNamePrefix("taskExecutor-");
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ return executor;
+ }
+ }
+
+}
diff --git a/Chapter4-1-5/src/main/java/com/didispace/async/Task.java b/Chapter4-1-5/src/main/java/com/didispace/async/Task.java
new file mode 100644
index 00000000..49f5f7e0
--- /dev/null
+++ b/Chapter4-1-5/src/main/java/com/didispace/async/Task.java
@@ -0,0 +1,32 @@
+package com.didispace.async;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Component;
+
+import java.util.Random;
+import java.util.concurrent.Future;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @date 16/5/16 下午12:58.
+ * @blog http://blog.didispace.com
+ */
+@Slf4j
+@Component
+public class Task {
+
+ public static Random random = new Random();
+
+ @Async("taskExecutor")
+ public Future run() throws Exception {
+ long sleep = random.nextInt(10000);
+ log.info("开始任务,需耗时:" + sleep + "毫秒");
+ Thread.sleep(sleep);
+ log.info("完成任务");
+ return new AsyncResult<>("test");
+ }
+
+}
diff --git a/Chapter4-1-5/src/main/resources/application.properties b/Chapter4-1-5/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/Chapter4-1-5/src/test/java/com/didispace/ApplicationTests.java b/Chapter4-1-5/src/test/java/com/didispace/ApplicationTests.java
new file mode 100644
index 00000000..c9cd12fd
--- /dev/null
+++ b/Chapter4-1-5/src/test/java/com/didispace/ApplicationTests.java
@@ -0,0 +1,29 @@
+package com.didispace;
+
+import com.didispace.async.Task;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest
+public class ApplicationTests {
+
+ @Autowired
+ private Task task;
+
+ @Test
+ public void test() throws Exception {
+ Future futureResult = task.run();
+ String result = futureResult.get(5, TimeUnit.SECONDS);
+ log.info(result);
+ }
+
+}
diff --git a/Chapter4-4-2/src/main/resources/application.properties b/Chapter4-4-2/src/main/resources/application.properties
index 1a9d0255..248f22c4 100644
--- a/Chapter4-4-2/src/main/resources/application.properties
+++ b/Chapter4-4-2/src/main/resources/application.properties
@@ -3,6 +3,7 @@ spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop
spring.jpa.properties.hibernate.show_sql=true
diff --git a/README.md b/README.md
index 0acc6f5a..ec90bff8 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,30 @@
- GitHub:https://github.com/dyc87112/SpringBoot-Learning
- Gitee:https://gitee.com/didispace/SpringBoot-Learning
- Spring For All社区:http://spring4all.com/
-- Spring Boot系列博文:http://blog.didispace.com/categories/Spring-Boot/
-- Spring Cloud系列博文:http://blog.didispace.com/categories/Spring-Cloud/
+- Spring Boot基础教程:http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/
+- Spring Cloud基础教程:http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/
**声明:本人已放弃"Spring Cloud中国社区",该社区的任何行为均与本人无关。[Spring For All社区](http://spring4all.com/)是新组建的关于Spring的纯技术交流社区(涵盖Spring Boot、Spring Cloud等内容),集诸多开源爱好者和技术大牛贡献内容和交流问题。我们不夸大、不装逼、做最纯粹的技术分享!!!**
-## 样例列表
+**优惠云服务推荐**
+
+- [腾讯云:3年时长最低265元/年](https://cloud.tencent.com/redirect.php?redirect=1005&cps_key=f6a8af1297bfac40b9d10ffa1270029a)
+- [阿里云:ECS云服务器2折起](https://s.click.taobao.com/t?e=m%3D2%26s%3Dzj4kbQ5lKukcQipKwQzePCperVdZeJviEViQ0P1Vf2kguMN8XjClAq9GNeKfy2AD4SaRmc4YmqYCxNLxWxqxDPY8Eqzf%2BUWbOTauL6DcROffvu81lbXO1DDVuRn8ddiDsEVVC24eqozO54LQ%2FVw1L9X5LHh3Z8M%2BWS6ALZVeqlk9XUfbPSJC%2F06deTzTIbffYpyF7ku%2BxKgGargQjSAC4C6cUF%2FXAmem)
+
+## Spring Boot 2.0 新特性学习
+
+**简介与概览**
+
+- [Spring Boot 2.0 正式发布,升还是不升呢?](http://blog.didispace.com/spring-boot-2-release/)
+- [Spring Boot 2.0 新特性和发展方向](http://blog.didispace.com/Spring-Boot-2-0-%E6%96%B0%E7%89%B9%E6%80%A7%E5%92%8C%E5%8F%91%E5%B1%95%E6%96%B9%E5%90%91/)
+- [Spring Boot 2.0 与 Java 9](http://blog.didispace.com/Spring-Boot-2.0%E4%B8%8EJava-9/)
+
+**新特性详解**
+
+- [Spring Boot 2.0 新特性(一):配置绑定 2.0 全解析](http://blog.didispace.com/Spring-Boot-2-0-feature-1-relaxed-binding-2/)
+- [Spring Boot 2.0 新特性(二):新增事件ApplicationStartedEvent](http://blog.didispace.com/Spring-Boot-2-0-feature-2-ApplicationStartedEvent/)
+
+## Spring Boot 基础教程(基于1.3.x-1.5.x)
#### 快速入门
@@ -22,6 +40,8 @@
#### 工程配置
- chapter2-1-1:[配置文件详解:自定义属性、随机数、多环境配置等](http://blog.didispace.com/springbootproperties/)
+- chapter2-1-2:[2.0 新特性(一):配置绑定全解析](http://blog.didispace.com/Spring-Boot-2-0-feature-1-relaxed-binding-2/)
+- chapter2-2-1:[2.0 新特性(二):新增事件ApplicationStartedEvent](http://blog.didispace.com/Spring-Boot-2-0-feature-2-ApplicationStartedEvent/)
#### Web开发
@@ -44,6 +64,7 @@
- chapter3-2-8:[MyBatis注解配置详解](http://blog.didispace.com/mybatisinfo/)
- chapter3-2-9:[使用Flyway来管理数据库版本](http://blog.didispace.com/spring-boot-flyway-db-version/)
- chapter3-2-10:[使用LDAP来统一管理用户信息](http://blog.didispace.com/spring-boot-ldap-user/)
+- chapter3-2-11:[Spring Boot中增强对MongoDB的配置(连接池等)](http://blog.didispace.com/springbootmongodb-plus/)
#### 事务管理
@@ -51,8 +72,12 @@
- chapter3-3-2:[分布式事务(未完成)]
#### 其他内容
+
- chapter4-1-1:[使用@Scheduled创建定时任务](http://blog.didispace.com/springbootscheduled/)
- chapter4-1-2:[使用@Async实现异步调用](http://blog.didispace.com/springbootasync/)
+- chapter4-1-3:[使用@Async实现异步调用:自定义线程池](http://blog.didispace.com/springbootasync-2/)
+- chapter4-1-4:[使用@Async实现异步调用:资源优雅关闭](http://blog.didispace.com/springbootasync-3/)
+- chapter4-1-5:[使用@Async实现异步调用:使用Future以及定义超时](http://blog.didispace.com/springbootasync-4/)
#### 日志管理