[
  {
    "path": ".gitignore",
    "content": ".class\n.classpath\n.project\nbuild\nbin\n.bak\n.settings\nThumbs.db\n.DS_Store\n._.DS_Store\nlogs\ntarget\n*.iml\n.idea\n"
  },
  {
    "path": ".gitmodules",
    "content": ""
  },
  {
    "path": "1.x/Chapter1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter1</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter1</name>\r\n\t<description>The first Spring Boot project</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\r\n\t\t</dependency>\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter1/src/main/java/com/didispace/Chapter1Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter1Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter1Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter1/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class HelloController {\n\n    @RequestMapping(\"/hello\")\n    public String index() {\n        return \"Hello World\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter1/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter1/src/test/java/com/didispace/Chapter1ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.HelloController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class Chapter1ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter2-1-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter2-1-1</name>\n\t<description></description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter2-1-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-1/src/main/java/com/didispace/service/BlogProperties.java",
    "content": "package com.didispace.service;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/5 下午12:16.\n * @blog http://blog.didispace.com\n */\n@Component\npublic class BlogProperties {\n\n    @Value(\"${com.didispace.blog.name}\")\n    private String name;\n    @Value(\"${com.didispace.blog.title}\")\n    private String title;\n    @Value(\"${com.didispace.blog.desc}\")\n    private String desc;\n\n    @Value(\"${com.didispace.blog.value}\")\n    private String value;\n    @Value(\"${com.didispace.blog.number}\")\n    private Integer number;\n    @Value(\"${com.didispace.blog.bignumber}\")\n    private Long bignumber;\n    @Value(\"${com.didispace.blog.test1}\")\n    private Integer test1;\n    @Value(\"${com.didispace.blog.test2}\")\n    private Integer test2;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getTitle() {\n        return title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public Integer getNumber() {\n        return number;\n    }\n\n    public void setNumber(Integer number) {\n        this.number = number;\n    }\n\n    public Long getBignumber() {\n        return bignumber;\n    }\n\n    public void setBignumber(Long bignumber) {\n        this.bignumber = bignumber;\n    }\n\n    public Integer getTest1() {\n        return test1;\n    }\n\n    public void setTest1(Integer test1) {\n        this.test1 = test1;\n    }\n\n    public Integer getTest2() {\n        return test2;\n    }\n\n    public void setTest2(Integer test2) {\n        this.test2 = test2;\n    }\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-1/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RestController\npublic class HelloController {\n\n    @RequestMapping(\"/hello\")\n    public String index() {\n        return \"Hello World\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter2-1-1/src/main/resources/application-dev.properties",
    "content": "# 服务端口\nserver.port=1111"
  },
  {
    "path": "1.x/Chapter2-1-1/src/main/resources/application-prod.properties",
    "content": "# 服务端口\nserver.port=3333"
  },
  {
    "path": "1.x/Chapter2-1-1/src/main/resources/application-test.properties",
    "content": "# 服务端口\nserver.port=2222"
  },
  {
    "path": "1.x/Chapter2-1-1/src/main/resources/application.properties",
    "content": "com.didispace.blog.name=程序猿DD\ncom.didispace.blog.title=Spring Boot教程\ncom.didispace.blog.desc=${com.didispace.blog.name}正在努力写《${com.didispace.blog.title}》\n\n# 随机字符串\ncom.didispace.blog.value=${random.value}\n# 随机int\ncom.didispace.blog.number=${random.int}\n# 随机long\ncom.didispace.blog.bignumber=${random.long}\n# 10以内的随机数\ncom.didispace.blog.test1=${random.int(10)}\n# 10-20的随机数\ncom.didispace.blog.test2=${random.int[10,20]}\n\n# 多环境配置文件激活属性\nspring.profiles.active=dev"
  },
  {
    "path": "1.x/Chapter2-1-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.service.BlogProperties;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\tprivate static final Log log = LogFactory.getLog(ApplicationTests.class);\n\n\t@Autowired\n\tprivate BlogProperties blogProperties;\n\n\n\t@Test\n\tpublic void test1() throws Exception {\n\t\tAssert.assertEquals(\"程序猿DD\", blogProperties.getName());\n\t\tAssert.assertEquals(\"Spring Boot教程\", blogProperties.getTitle());\n\t\tAssert.assertEquals(\"程序猿DD正在努力写《Spring Boot教程》\", blogProperties.getDesc());\n\n\t\tlog.info(\"随机数测试输出：\");\n\t\tlog.info(\"随机字符串 : \" + blogProperties.getValue());\n\t\tlog.info(\"随机int : \" + blogProperties.getNumber());\n\t\tlog.info(\"随机long : \" + blogProperties.getBignumber());\n\t\tlog.info(\"随机10以下 : \" + blogProperties.getTest1());\n\t\tlog.info(\"随机10-20 : \" + blogProperties.getTest2());\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>Chapter2-1-2</artifactId>\n    <version>1.0.0</version>\n    <packaging>jar</packaging>\n\n    <name>Chapter2-1-2</name>\n    <description>Spring Boot 2.0 features : Application Events and Listeners</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.0.0.RELEASE</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\n\n@Slf4j\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n    @Bean\n    public DataLoader dataLoader() {\n        return new DataLoader();\n    }\n\n    @Slf4j\n    static class DataLoader implements CommandLineRunner {\n\n        @Override\n        public void run(String... strings) throws Exception {\n            log.info(\"Loading data...\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/java/com/didispace/ApplicationEnvironmentPreparedEventListener.java",
    "content": "package com.didispace;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;\nimport org.springframework.context.ApplicationListener;\n\n@Slf4j\npublic class ApplicationEnvironmentPreparedEventListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {\n\n    @Override\n    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {\n        log.info(\"......ApplicationEnvironmentPreparedEvent......\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/java/com/didispace/ApplicationFailedEventListener.java",
    "content": "package com.didispace;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.context.event.ApplicationFailedEvent;\nimport org.springframework.context.ApplicationListener;\n\n@Slf4j\npublic class ApplicationFailedEventListener implements ApplicationListener<ApplicationFailedEvent> {\n\n    @Override\n    public void onApplicationEvent(ApplicationFailedEvent event) {\n        log.info(\"......ApplicationFailedEvent......\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/java/com/didispace/ApplicationPreparedEventListener.java",
    "content": "package com.didispace;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.context.event.ApplicationPreparedEvent;\nimport org.springframework.context.ApplicationListener;\n\n@Slf4j\npublic class ApplicationPreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> {\n\n    @Override\n    public void onApplicationEvent(ApplicationPreparedEvent event) {\n        log.info(\"......ApplicationPreparedEvent......\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/java/com/didispace/ApplicationReadyEventListener.java",
    "content": "package com.didispace;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.context.event.ApplicationReadyEvent;\nimport org.springframework.context.ApplicationListener;\n\n@Slf4j\npublic class ApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {\n\n    @Override\n    public void onApplicationEvent(ApplicationReadyEvent event) {\n        log.info(\"......ApplicationReadyEvent......\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartedEventListener.java",
    "content": "package com.didispace;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.event.ApplicationStartedEvent;\nimport org.springframework.context.ApplicationListener;\n\n@Slf4j\npublic class ApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {\n\n    @Override\n    public void onApplicationEvent(ApplicationStartedEvent event) {\n        log.info(\"......ApplicationStartedEvent......\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/java/com/didispace/ApplicationStartingEventListener.java",
    "content": "package com.didispace;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.context.event.ApplicationStartingEvent;\nimport org.springframework.context.ApplicationListener;\n\n@Slf4j\npublic class ApplicationStartingEventListener implements ApplicationListener<ApplicationStartingEvent> {\n\n    @Override\n    public void onApplicationEvent(ApplicationStartingEvent event) {\n        log.info(\"......ApplicationStartingEvent......\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.context.ApplicationListener=com.didispace.ApplicationEnvironmentPreparedEventListener,\\\n  com.didispace.ApplicationFailedEventListener,\\\n  com.didispace.ApplicationPreparedEventListener,\\\n  com.didispace.ApplicationReadyEventListener,\\\n  com.didispace.ApplicationStartedEventListener,\\\n  com.didispace.ApplicationStartingEventListener"
  },
  {
    "path": "1.x/Chapter2-1-2/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter2-2-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter2-2-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter2-2-1</name>\n\t<description>Spring Boot 2 : Relaxed Binding</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.0.0.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<version>1.16.20</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter2-2-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.context.properties.ConfigurationPropertiesBinding;\nimport org.springframework.boot.context.properties.bind.Bindable;\nimport org.springframework.boot.context.properties.bind.Binder;\nimport org.springframework.context.ApplicationContext;\n\nimport java.util.List;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tApplicationContext context = SpringApplication.run(Application.class, args);\n\n\t\tBinder binder = Binder.get(context.getEnvironment());\n\n\t\t// 绑定简单配置\n\t\tFooProperties foo = binder.bind(\"com.didispace\", Bindable.of(FooProperties.class)).get();\n\t\tSystem.out.println(foo.getFoo());\n\n\t\t// 绑定List配置\n\t\tList<String> post = binder.bind(\"com.didispace.post\", Bindable.listOf(String.class)).get();\n\t\tSystem.out.println(post);\n\n\t\tList<PostInfo> posts = binder.bind(\"com.didispace.posts\", Bindable.listOf(PostInfo.class)).get();\n\t\tSystem.out.println(posts);\n\n\t\t// 读取配置\n\t\tSystem.out.println(context.getEnvironment().containsProperty(\"com.didispace.database-platform\"));\n\t\tSystem.out.println(context.getEnvironment().containsProperty(\"com.didispace.databasePlatform\"));\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-2-1/src/main/java/com/didispace/FooProperties.java",
    "content": "package com.didispace;\n\nimport lombok.Data;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\n@Data\n@ConfigurationProperties(prefix = \"com.didispace\")\npublic class FooProperties {\n\n    private String foo;\n\n    private String databasePlatform;\n\n}"
  },
  {
    "path": "1.x/Chapter2-2-1/src/main/java/com/didispace/PostInfo.java",
    "content": "package com.didispace;\n\nimport lombok.Data;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\n@Data\n@ConfigurationProperties\npublic class PostInfo {\n\n    private String title;\n    private String content;\n\n}\n"
  },
  {
    "path": "1.x/Chapter2-2-1/src/main/resources/application.properties",
    "content": "com.didispace.foo=bar\ncom.didispace.database-platform=sql\n\ncom.didispace.post[0]=Why Spring Boot\ncom.didispace.post[1]=Why Spring Cloud\n\ncom.didispace.posts[0].title=Why Spring Boot\ncom.didispace.posts[0].content=It is perfect!\ncom.didispace.posts[1].title=Why Spring Cloud\ncom.didispace.posts[1].content=It is perfect too!\n"
  },
  {
    "path": "1.x/Chapter3-1-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter3-1-1</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter3-1-1</name>\r\n\t<description>RESTful API Project</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\r\n\t\t</dependency>\r\n\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter3-1-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-1/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\npublic class User {\n\n    private Long id;\n    private String name;\n    private Integer age;\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-1/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RestController\npublic class HelloController {\n\n    @RequestMapping(\"/hello\")\n    public String index() {\n        return \"Hello World\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-1-1/src/main/java/com/didispace/web/UserController.java",
    "content": "package com.didispace.web;\n\nimport com.didispace.domain.User;\n\nimport java.util.*;\n\nimport org.springframework.web.bind.annotation.*;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RestController\n@RequestMapping(value=\"/users\")     // 通过这里配置使下面的映射都在/users下，可去除\npublic class UserController {\n\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());\n\n    @RequestMapping(value=\"/\", method=RequestMethod.GET)\n    public List<User> getUserList() {\n        // 处理\"/users/\"的GET请求，用来获取用户列表\n        // 还可以通过@RequestParam从页面中传递参数来进行查询条件或者翻页信息的传递\n        List<User> r = new ArrayList<User>(users.values());\n        return r;\n    }\n\n    @RequestMapping(value=\"/\", method=RequestMethod.POST)\n    public String postUser(@ModelAttribute User user) {\n        // 处理\"/users/\"的POST请求，用来创建User\n        // 除了@ModelAttribute绑定参数之外，还可以通过@RequestParam从页面中传递参数\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    @RequestMapping(value=\"/{id}\", method=RequestMethod.GET)\n    public User getUser(@PathVariable Long id) {\n        // 处理\"/users/{id}\"的GET请求，用来获取url中id值的User信息\n        // url中的id可通过@PathVariable绑定到函数的参数中\n        return users.get(id);\n    }\n\n    @RequestMapping(value=\"/{id}\", method=RequestMethod.PUT)\n    public String putUser(@PathVariable Long id, @ModelAttribute User user) {\n        // 处理\"/users/{id}\"的PUT请求，用来更新User信息\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    @RequestMapping(value=\"/{id}\", method=RequestMethod.DELETE)\n    public String deleteUser(@PathVariable Long id) {\n        // 处理\"/users/{id}\"的DELETE请求，用来删除User\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-1-1/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-1-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.web.HelloController;\nimport com.didispace.web.UserController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.RequestBuilder;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(\n\t\t\t\tnew HelloController(),\n\t\t\t\tnew UserController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n\t@Test\n\tpublic void testUserController() throws Exception {\n//  \t测试UserController\n\t\tRequestBuilder request = null;\n\n\t\t// 1、get查一下user列表，应该为空\n\t\trequest = get(\"/users/\");\n\t\tmvc.perform(request)\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"[]\")));\n\n\t\t// 2、post提交一个user\n\t\trequest = post(\"/users/\")\n\t\t\t\t.param(\"id\", \"1\")\n\t\t\t\t.param(\"name\", \"测试大师\")\n\t\t\t\t.param(\"age\", \"20\");\n\t\tmvc.perform(request)\n//\t\t\t\t.andDo(MockMvcResultHandlers.print())\n\t\t\t\t.andExpect(content().string(equalTo(\"success\")));\n\n\t\t// 3、get获取user列表，应该有刚才插入的数据\n\t\trequest = get(\"/users/\");\n\t\tmvc.perform(request)\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"[{\\\"id\\\":1,\\\"name\\\":\\\"测试大师\\\",\\\"age\\\":20}]\")));\n\n\t\t// 4、put修改id为1的user\n\t\trequest = put(\"/users/1\")\n\t\t\t\t.param(\"name\", \"测试终极大师\")\n\t\t\t\t.param(\"age\", \"30\");\n\t\tmvc.perform(request)\n\t\t\t\t.andExpect(content().string(equalTo(\"success\")));\n\n\t\t// 5、get一个id为1的user\n\t\trequest = get(\"/users/1\");\n\t\tmvc.perform(request)\n\t\t\t\t.andExpect(content().string(equalTo(\"{\\\"id\\\":1,\\\"name\\\":\\\"测试终极大师\\\",\\\"age\\\":30}\")));\n\n\t\t// 6、del删除id为1的user\n\t\trequest = delete(\"/users/1\");\n\t\tmvc.perform(request)\n\t\t\t\t.andExpect(content().string(equalTo(\"success\")));\n\n\t\t// 7、get查一下user列表，应该为空\n\t\trequest = get(\"/users/\");\n\t\tmvc.perform(request)\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"[]\")));\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter3-1-2</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter3-1-2</name>\r\n\t<description>Spring Boot with Thymeleaf</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\r\n\t\t</dependency>\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t\t<configuration>\r\n\t\t\t\t\t<fork>true</fork>\r\n\t\t\t\t</configuration>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter3-1-2/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-2/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\r\n\r\nimport org.springframework.stereotype.Controller;\r\nimport org.springframework.ui.ModelMap;\r\nimport org.springframework.web.bind.annotation.RequestMapping;\r\nimport org.springframework.web.bind.annotation.RestController;\r\n\r\n/**\r\n *\r\n * @author 程序猿DD\r\n * @version 1.0.0\r\n * @blog http://blog.didispace.com\r\n *\r\n */\r\n@Controller\r\npublic class HelloController {\r\n    \r\n    @ResponseBody\r\n    @RequestMapping(\"/hello\")\r\n    public String hello() {\r\n        return \"Hello World\";\r\n    }\r\n\r\n    @RequestMapping(\"/\")\r\n    public String index(ModelMap map) {\r\n        map.addAttribute(\"host\", \"http://blog.didispace.com\");\r\n        return \"index\";\r\n    }\r\n\r\n}"
  },
  {
    "path": "1.x/Chapter3-1-2/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-1-2/src/main/resources/templates/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title></title>\n</head>\n<body>\n<h1 th:text=\"${host}\">Hello World</h1>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter3-1-2/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.HelloController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(\n\t\t\t\tnew HelloController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>demo</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>demo</name>\n\t<description>Spring Boot Web project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-freemarker</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\n</project>\n"
  },
  {
    "path": "1.x/Chapter3-1-3/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-3/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\r\n\r\nimport org.springframework.stereotype.Controller;\r\nimport org.springframework.ui.ModelMap;\r\nimport org.springframework.web.bind.annotation.RequestMapping;\r\nimport org.springframework.web.bind.annotation.RestController;\r\n\r\n/**\r\n *\r\n * @author 程序猿DD\r\n * @version 1.0.0\r\n * @blog http://blog.didispace.com\r\n *\r\n */\r\n@Controller\r\npublic class HelloController {\r\n\r\n    @RequestMapping(\"/hello\")\r\n    @ResponseBody\r\n    public String hello() {\r\n        return \"Hello World\";\r\n    }\r\n\r\n    @RequestMapping(\"/\")\r\n    public String index(ModelMap map) {\r\n        map.addAttribute(\"host\", \"http://blog.didispace.com\");\r\n        return \"index\";\r\n    }\r\n\r\n}"
  },
  {
    "path": "1.x/Chapter3-1-3/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-1-3/src/main/resources/templates/index.ftl",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title></title>\n</head>\n<body>\nFreeMarker模板引擎\n<h1>${host}</h1>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter3-1-3/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.HelloController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(\n\t\t\t\tnew HelloController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>demo</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>demo</name>\n\t<description>Spring Boot Web project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-velocity</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\n</project>\n"
  },
  {
    "path": "1.x/Chapter3-1-4/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-4/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\r\n\r\nimport org.springframework.stereotype.Controller;\r\nimport org.springframework.ui.ModelMap;\r\nimport org.springframework.web.bind.annotation.RequestMapping;\r\nimport org.springframework.web.bind.annotation.RestController;\r\n\r\n/**\r\n *\r\n * @author 程序猿DD\r\n * @version 1.0.0\r\n * @blog http://blog.didispace.com\r\n *\r\n */\r\n@Controller\r\npublic class HelloController {\r\n\r\n    @RequestMapping(\"/hello\")\r\n    @ResponseBody\r\n    public String hello() {\r\n        return \"Hello World\";\r\n    }\r\n\r\n    @RequestMapping(\"/\")\r\n    public String index(ModelMap map) {\r\n        map.addAttribute(\"host\", \"http://blog.didispace.com\");\r\n        return \"index\";\r\n    }\r\n\r\n}"
  },
  {
    "path": "1.x/Chapter3-1-4/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-1-4/src/main/resources/templates/index.vm",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title></title>\n</head>\n<body>\nVelocity模板\n<h1>${host}</h1>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter3-1-4/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.HelloController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(\n\t\t\t\tnew HelloController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>SpringBootWithSwagger</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>SpringBootWithSwagger</name>\n\t<description>SpringBootWithSwagger</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger2</artifactId>\n\t\t\t<version>2.2.2</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-swagger-ui</artifactId>\n\t\t\t<version>2.2.2</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\n</project>\n"
  },
  {
    "path": "1.x/Chapter3-1-5/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-5/src/main/java/com/didispace/Swagger2.java",
    "content": "package com.didispace;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.service.ApiInfo;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/4/18 下午12:02.\n * @blog http://blog.didispace.com\n */\n@Configuration\n@EnableSwagger2\npublic class Swagger2 {\n\n    @Bean\n    public Docket createRestApi() {\n        return new Docket(DocumentationType.SWAGGER_2)\n                .apiInfo(apiInfo())\n                .select()\n                .apis(RequestHandlerSelectors.basePackage(\"com.didispace.web\"))\n                .paths(PathSelectors.any())\n                .build();\n    }\n\n    private ApiInfo apiInfo() {\n        return new ApiInfoBuilder()\n                .title(\"Spring Boot中使用Swagger2构建RESTful APIs\")\n                .description(\"更多Spring Boot相关文章请关注：http://blog.didispace.com/\")\n                .termsOfServiceUrl(\"http://blog.didispace.com/\")\n                .contact(\"程序猿DD\")\n                .version(\"1.0\")\n                .build();\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-5/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\npublic class User {\n\n    private Long id;\n    private String name;\n    private Integer age;\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-5/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\nimport springfox.documentation.annotations.ApiIgnore;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RestController\npublic class HelloController {\n\n    @ApiIgnore\n    @RequestMapping(value = \"/hello\", method = RequestMethod.GET)\n    public String index() {\n        return \"Hello World\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-1-5/src/main/java/com/didispace/web/UserController.java",
    "content": "package com.didispace.web;\n\nimport com.didispace.domain.User;\n\nimport java.util.*;\n\nimport io.swagger.annotations.*;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RestController\n@RequestMapping(value=\"/users\")     // 通过这里配置使下面的映射都在/users下，可去除\npublic class UserController {\n\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());\n\n    @ApiOperation(value=\"获取用户列表\", notes=\"\")\n    @RequestMapping(value={\"\"}, method=RequestMethod.GET)\n    public List<User> getUserList() {\n        List<User> r = new ArrayList<User>(users.values());\n        return r;\n    }\n\n    @ApiOperation(value=\"创建用户\", notes=\"根据User对象创建用户\")\n    @ApiImplicitParam(name = \"user\", value = \"用户详细实体user\", required = true, dataType = \"User\")\n    @RequestMapping(value=\"\", method=RequestMethod.POST)\n    public String postUser(@RequestBody User user) {\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    @ApiOperation(value=\"获取用户详细信息\", notes=\"根据url的id来获取用户详细信息\")\n    @ApiImplicitParam(name = \"id\", value = \"用户ID\", required = true, dataType = \"Long\", paramType = \"path\")\n    @RequestMapping(value=\"/{id}\", method=RequestMethod.GET)\n    public User getUser(@PathVariable Long id) {\n        return users.get(id);\n    }\n\n    @ApiOperation(value=\"更新用户详细信息\", notes=\"根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\")\n    @ApiImplicitParams({\n            @ApiImplicitParam(name = \"id\", value = \"用户ID\", required = true, dataType = \"Long\", paramType = \"path\"),\n            @ApiImplicitParam(name = \"user\", value = \"用户详细实体user\", required = true, dataType = \"User\")\n    })\n    @RequestMapping(value=\"/{id}\", method=RequestMethod.PUT)\n    public String putUser(@PathVariable Long id, @RequestBody User user) {\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    @ApiOperation(value=\"删除用户\", notes=\"根据url的id来指定删除对象\")\n    @ApiImplicitParam(name = \"id\", value = \"用户ID\", required = true, dataType = \"Long\", paramType = \"path\")\n    @RequestMapping(value=\"/{id}\", method=RequestMethod.DELETE)\n    public String deleteUser(@PathVariable Long id) {\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-1-5/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-1-6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-1-6</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter3-1-6</name>\n\t<description>Spring Boot</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/java/com/didispace/dto/ErrorInfo.java",
    "content": "package com.didispace.dto;\n\npublic class ErrorInfo<T> {\n\n    public static final Integer OK = 0;\n    public static final Integer ERROR = 100;\n\n    private Integer code;\n    private String message;\n    private String url;\n    private T data;\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public static Integer getOK() {\n        return OK;\n    }\n\n    public static Integer getERROR() {\n        return ERROR;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public void setCode(Integer code) {\n        this.code = code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n    public T getData() {\n        return data;\n    }\n\n    public void setData(T data) {\n        this.data = data;\n    }\n    \n}"
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/java/com/didispace/exception/GlobalExceptionHandler.java",
    "content": "package com.didispace.exception;\n\nimport com.didispace.dto.ErrorInfo;\nimport org.springframework.web.bind.annotation.ControllerAdvice;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletRequest;\n\n@ControllerAdvice\npublic class GlobalExceptionHandler {\n\n    @ExceptionHandler(value = Exception.class)\n    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {\n        ModelAndView mav = new ModelAndView();\n        mav.addObject(\"exception\", e);\n        mav.addObject(\"url\", req.getRequestURL());\n        mav.setViewName(\"error\");\n        return mav;\n    }\n\n    @ExceptionHandler(value = MyException.class)\n    @ResponseBody\n    public ErrorInfo<String> jsonErrorHandler(HttpServletRequest req, MyException e) throws Exception {\n        ErrorInfo<String> r = new ErrorInfo<>();\n        r.setMessage(e.getMessage());\n        r.setCode(ErrorInfo.ERROR);\n        r.setData(\"Some Data\");\n        r.setUrl(req.getRequestURL().toString());\n        return r;\n    }\n\n}\n\n"
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/java/com/didispace/exception/MyException.java",
    "content": "package com.didispace.exception;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/2 上午10:50.\n * @blog http://blog.didispace.com\n */\npublic class MyException extends Exception {\n\n    public MyException(String message) {\n        super(message);\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport com.didispace.exception.MyException;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.ModelMap;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@Controller\npublic class HelloController {\n\n    @RequestMapping(\"/hello\")\n    public String hello() throws Exception {\n        throw new Exception(\"发生错误\");\n    }\n\n    @RequestMapping(\"/json\")\n    public String json() throws MyException {\n        throw new MyException(\"发生错误2\");\n    }\n\n    @RequestMapping(\"/\")\n    public String index(ModelMap map) {\n        map.addAttribute(\"host\", \"http://blog.didispace.com\");\n        return \"index\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/resources/templates/error.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title>统一异常处理</title>\n</head>\n<body>\n<h1>Error Handler</h1>\n<div th:text=\"${url}\"></div>\n<div th:text=\"${exception.message}\"></div>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter3-1-6/src/main/resources/templates/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title></title>\n</head>\n<body>\n<h1 th:text=\"${host}\">Hello World</h1>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter3-1-6/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.HelloController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-7/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-1-7</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter3-1-7</name>\n\t<description>Spring Boot</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.5.10.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.datatype</groupId>\n\t\t\t<artifactId>jackson-datatype-jsr310</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<version>1.16.20</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-1-7/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.SerializationFeature;\nimport com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.time.LocalDate;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n    @RestController\n    class HelloController {\n\n        @PostMapping(\"/user\")\n        public UserDto user(@RequestBody UserDto userDto) throws Exception {\n            return userDto;\n        }\n\n    }\n\n    @Data\n    @NoArgsConstructor\n    @AllArgsConstructor\n    static class UserDto {\n\n        private String userName;\n        private LocalDate birthday;\n\n    }\n\n    @Bean\n    public ObjectMapper serializingObjectMapper() {\n        ObjectMapper objectMapper = new ObjectMapper();\n        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);\n        objectMapper.registerModule(new JavaTimeModule());\n        return objectMapper;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-7/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-1-8/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-1-8</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.5.10.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.dataformat</groupId>\n\t\t\t<artifactId>jackson-dataformat-xml</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-1-8/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-8/src/main/java/com/didispace/web/User.java",
    "content": "package com.didispace.web;\n\n\nimport com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;\nimport com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@JacksonXmlRootElement(localName = \"User\")\npublic class User {\n\n    @JacksonXmlProperty(localName = \"name\")\n    private String name;\n    @JacksonXmlProperty(localName = \"age\")\n    private Integer age;\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-1-8/src/main/java/com/didispace/web/UserController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.http.MediaType;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@Controller\npublic class UserController {\n\n    @PostMapping(value = \"/user\", consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE)\n    @ResponseBody\n    public User create(@RequestBody User user) {\n        user.setName(\"didispace.com : \" + user.getName());\n        user.setAge(user.getAge() + 100);\n        return user;\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-1-8/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter3-2-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter3-2-1</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter3-2-1</name>\r\n\t<description>Spring Boot with JDBCTemplate</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>mysql</groupId>\r\n\t\t\t<artifactId>mysql-connector-java</artifactId>\r\n\t\t\t<version>5.1.21</version>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\r\n\t\t</dependency>\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-1/src/main/java/com/didispace/service/UserService.java",
    "content": "package com.didispace.service;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/17 下午7:04.\n * @blog http://blog.didispace.com\n */\npublic interface UserService {\n\n    /**\n     * 新增一个用户\n     * @param name\n     * @param age\n     */\n    void create(String name, Integer age);\n\n    /**\n     * 根据name删除一个用户高\n     * @param name\n     */\n    void deleteByName(String name);\n\n    /**\n     * 获取用户总量\n     */\n    Integer getAllUsers();\n\n    /**\n     * 删除所有用户\n     */\n    void deleteAllUsers();\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-1/src/main/java/com/didispace/service/UserServiceImpl.java",
    "content": "package com.didispace.service;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/17 下午6:44.\n * @blog http://blog.didispace.com\n */\n@Service\npublic class UserServiceImpl implements UserService {\n\n    @Autowired\n    private JdbcTemplate jdbcTemplate;\n\n    @Override\n    public void create(String name, Integer age) {\n        jdbcTemplate.update(\"insert into USER(NAME, AGE) values(?, ?)\", name, age);\n    }\n\n    @Override\n    public void deleteByName(String name) {\n        jdbcTemplate.update(\"delete from USER where NAME = ?\", name);\n    }\n\n    @Override\n    public Integer getAllUsers() {\n        return jdbcTemplate.queryForObject(\"select count(1) from USER\", Integer.class);\n    }\n\n    @Override\n    public void deleteAllUsers() {\n        jdbcTemplate.update(\"delete from USER\");\n    }\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-1/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\r\nspring.datasource.username=root\r\nspring.datasource.password=root\r\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver"
  },
  {
    "path": "1.x/Chapter3-2-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.service.UserService;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserService userSerivce;\n\n\t@Before\n\tpublic void setUp() {\n\t\t// 准备，清空user表\n\t\tuserSerivce.deleteAllUsers();\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\t\t// 插入5个用户\n\t\tuserSerivce.create(\"a\", 1);\n\t\tuserSerivce.create(\"b\", 2);\n\t\tuserSerivce.create(\"c\", 3);\n\t\tuserSerivce.create(\"d\", 4);\n\t\tuserSerivce.create(\"e\", 5);\n\n\t\t// 查数据库，应该有5个用户\n\t\tAssert.assertEquals(5, userSerivce.getAllUsers().intValue());\n\n\t\t// 删除两个用户\n\t\tuserSerivce.deleteByName(\"a\");\n\t\tuserSerivce.deleteByName(\"e\");\n\n\t\t// 查数据库，应该有5个用户\n\t\tAssert.assertEquals(3, userSerivce.getAllUsers().intValue());\n\n\t}\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-10/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-2-10</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter3-2-10</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.5.9.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-ldap</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.unboundid</groupId>\n\t\t\t<artifactId>unboundid-ldapsdk</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<version>1.16.16</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-10/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-10/src/main/java/com/didispace/Person.java",
    "content": "package com.didispace;\n\nimport lombok.Data;\nimport org.springframework.ldap.odm.annotations.*;\n\nimport javax.naming.Name;\n\n@Entry(base = \"ou=people,dc=didispace,dc=com\", objectClasses = \"inetOrgPerson\")\n@Data\npublic class Person {\n\n    @Id\n    private Name id;\n    @DnAttribute(value = \"uid\", index = 3)\n    private String uid;\n    @Attribute(name = \"cn\")\n    private String commonName;\n    @Attribute(name = \"sn\")\n    private String suerName;\n    private String userPassword;\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-10/src/main/java/com/didispace/PersonRepository.java",
    "content": "package com.didispace;\n\nimport org.springframework.data.repository.CrudRepository;\n\nimport javax.naming.Name;\n\npublic interface PersonRepository extends CrudRepository<Person, Name> {\n\n\n}"
  },
  {
    "path": "1.x/Chapter3-2-10/src/main/resources/application.properties",
    "content": "#spring.ldap.urls=ldap://localhost:1235\n#spring.ldap.base=dc=didispace,dc=com\n#spring.ldap.username=didispace\n#spring.ldap.password=123456"
  },
  {
    "path": "1.x/Chapter3-2-10/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate PersonRepository personRepository;\n\n\t@Test\n\tpublic void findAll() throws Exception {\n\n\t\tpersonRepository.findAll().forEach(p -> {\n\t\t\tSystem.out.println(p);\n\t\t});\n\n\t}\n\n\t@Test\n\tpublic void save() throws Exception {\n\t\tPerson person = new Person();\n\t\tperson.setUid(\"uid:1\");\n\t\tperson.setSuerName(\"AAA\");\n\t\tperson.setCommonName(\"aaa\");\n\t\tperson.setUserPassword(\"123456\");\n\t\tpersonRepository.save(person);\n\n\t\tpersonRepository.findAll().forEach(p -> {\n\t\t\tSystem.out.println(p);\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-10/src/test/resources/application.properties",
    "content": "spring.ldap.embedded.ldif=ldap-server.ldif\nspring.ldap.embedded.base-dn=dc=didispace,dc=com\n\n"
  },
  {
    "path": "1.x/Chapter3-2-10/src/test/resources/ldap-server.ldif",
    "content": "dn: dc=didispace,dc=com\nobjectClass: top\nobjectClass: domain\n\ndn: ou=people,dc=didispace,dc=com\nobjectclass: top\nobjectclass: organizationalUnit\nou: people\n\ndn: uid=ben,ou=people,dc=didispace,dc=com\nobjectclass: top\nobjectclass: person\nobjectclass: organizationalPerson\nobjectclass: inetOrgPerson\ncn: didi\nsn: zhaiyongchao\nuid: didi\nuserPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=\n"
  },
  {
    "path": "1.x/Chapter3-2-11/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>Chapter3-2-11</artifactId>\n    <version>1.0.0</version>\n    <packaging>jar</packaging>\n\n    <name>Chapter3-2-11</name>\n    <description>Spring Boot project</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>1.5.10.RELEASE</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-mongodb</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.spring4all</groupId>\n            <artifactId>mongodb-plus-spring-boot-starter</artifactId>\n            <version>1.0.0.RELEASE</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.16.12</version>\n            <scope>provided</scope>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n\n</project>\n"
  },
  {
    "path": "1.x/Chapter3-2-11/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport com.spring4all.mongodb.EnableMongoPlus;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@EnableMongoPlus\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-11/src/main/resources/application.properties",
    "content": "spring.data.mongodb.uri=mongodb://localhost:27017/test\n\nspring.data.mongodb.option.min-connection-per-host=20\nspring.data.mongodb.option.max-connection-per-host=200\n"
  },
  {
    "path": "1.x/Chapter3-2-11/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.mongodb.MongoClient;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\n@Slf4j\npublic class ApplicationTests {\n\n    @Autowired\n    private MongoClient mongoClient;\n\n    @Test\n    public void test() throws Exception {\n        log.info(\"MinConnectionsPerHost = {}, MaxConnectionsPerHost = {}\",\n                mongoClient.getMongoClientOptions().getMinConnectionsPerHost(),\n                mongoClient.getMongoClientOptions().getConnectionsPerHost());\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter3-2-2</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter3-2-2</name>\r\n\t<description>Spring Boot project</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>mysql</groupId>\r\n\t\t\t<artifactId>mysql-connector-java</artifactId>\r\n\t\t\t<version>5.1.21</version>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\r\n\t\t</dependency>\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-2/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-2/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/21 下午3:35.\n * @blog http://blog.didispace.com\n */\n@Entity\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @Column(nullable = false)\n    private String name;\n\n    @Column(nullable = false)\n    private Integer age;\n\n    public User(){}\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-2/src/main/java/com/didispace/domain/UserRepository.java",
    "content": "package com.didispace.domain;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    User findByName(String name);\n\n    User findByNameAndAge(String name, Integer age);\n\n    @Query(\"from User u where u.name=:name\")\n    User findUser(@Param(\"name\") String name);\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-2/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=root\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver\n\nspring.jpa.properties.hibernate.hbm2ddl.auto=create-drop"
  },
  {
    "path": "1.x/Chapter3-2-2/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.domain.UserRepository;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserRepository userRepository;\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\t// 创建10条记录\n\t\tuserRepository.save(new User(\"AAA\", 10));\n\t\tuserRepository.save(new User(\"BBB\", 20));\n\t\tuserRepository.save(new User(\"CCC\", 30));\n\t\tuserRepository.save(new User(\"DDD\", 40));\n\t\tuserRepository.save(new User(\"EEE\", 50));\n\t\tuserRepository.save(new User(\"FFF\", 60));\n\t\tuserRepository.save(new User(\"GGG\", 70));\n\t\tuserRepository.save(new User(\"HHH\", 80));\n\t\tuserRepository.save(new User(\"III\", 90));\n\t\tuserRepository.save(new User(\"JJJ\", 100));\n\n\t\t// 测试findAll, 查询所有记录\n\t\tAssert.assertEquals(10, userRepository.findAll().size());\n\n\t\t// 测试findByName, 查询姓名为FFF的User\n\t\tAssert.assertEquals(60, userRepository.findByName(\"FFF\").getAge().longValue());\n\n\t\t// 测试findUser, 查询姓名为FFF的User\n\t\tAssert.assertEquals(60, userRepository.findUser(\"FFF\").getAge().longValue());\n\n\t\t// 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的User\n\t\tAssert.assertEquals(\"FFF\", userRepository.findByNameAndAge(\"FFF\", 60).getName());\n\n\t\t// 测试删除姓名为AAA的User\n\t\tuserRepository.delete(userRepository.findByName(\"AAA\"));\n\n\t\t// 测试findAll, 查询所有记录, 验证上面的删除是否成功\n\t\tAssert.assertEquals(9, userRepository.findAll().size());\n\n\t}\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter3-2-3</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter3-2-3</name>\r\n\t<description>Spring Boot project</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>mysql</groupId>\r\n\t\t\t<artifactId>mysql-connector-java</artifactId>\r\n\t\t\t<version>5.1.21</version>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\r\n\t\t</dependency>\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-3/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.sql.DataSource;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-3/src/main/java/com/didispace/DataSourceConfig.java",
    "content": "package com.didispace;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.sql.DataSource;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/26 下午9:11.\n * @blog http://blog.didispace.com\n */\n@Configuration\npublic class DataSourceConfig {\n\n    @Bean(name = \"primaryDataSource\")\n    @Qualifier(\"primaryDataSource\")\n    @ConfigurationProperties(prefix=\"spring.datasource.primary\")\n    public DataSource primaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n    @Bean(name = \"secondaryDataSource\")\n    @Qualifier(\"secondaryDataSource\")\n    @Primary\n    @ConfigurationProperties(prefix=\"spring.datasource.secondary\")\n    public DataSource secondaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n    @Bean(name = \"primaryJdbcTemplate\")\n    public JdbcTemplate primaryJdbcTemplate(\n            @Qualifier(\"primaryDataSource\") DataSource dataSource) {\n        return new JdbcTemplate(dataSource);\n    }\n\n    @Bean(name = \"secondaryJdbcTemplate\")\n    public JdbcTemplate secondaryJdbcTemplate(\n            @Qualifier(\"secondaryDataSource\") DataSource dataSource) {\n        return new JdbcTemplate(dataSource);\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-3/src/main/resources/application.properties",
    "content": "spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.username=root\nspring.datasource.primary.password=root\nspring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver\n\nspring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.username=root\nspring.datasource.secondary.password=root\nspring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver\n"
  },
  {
    "path": "1.x/Chapter3-2-3/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\t@Qualifier(\"primaryJdbcTemplate\")\n\tprotected JdbcTemplate jdbcTemplate1;\n\n\t@Autowired\n\t@Qualifier(\"secondaryJdbcTemplate\")\n\tprotected JdbcTemplate jdbcTemplate2;\n\n\t@Before\n\tpublic void setUp() {\n\t\tjdbcTemplate1.update(\"DELETE  FROM  USER \");\n\t\tjdbcTemplate2.update(\"DELETE  FROM  USER \");\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\t// 往第一个数据源中插入两条数据\n\t\tjdbcTemplate1.update(\"insert into user(id,name,age) values(?, ?, ?)\", 1, \"aaa\", 20);\n\t\tjdbcTemplate1.update(\"insert into user(id,name,age) values(?, ?, ?)\", 2, \"bbb\", 30);\n\n\t\t// 往第二个数据源中插入一条数据，若插入的是第一个数据源，则会主键冲突报错\n\t\tjdbcTemplate2.update(\"insert into user(id,name,age) values(?, ?, ?)\", 1, \"aaa\", 20);\n\n\t\t// 查一下第一个数据源中是否有两条数据，验证插入是否成功\n\t\tAssert.assertEquals(\"2\", jdbcTemplate1.queryForObject(\"select count(1) from user\", String.class));\n\n\t\t// 查一下第一个数据源中是否有两条数据，验证插入是否成功\n\t\tAssert.assertEquals(\"1\", jdbcTemplate2.queryForObject(\"select count(1) from user\", String.class));\n\n\t}\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter3-2-4</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter3-2-4</name>\r\n\t<description>Spring Boot project</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>mysql</groupId>\r\n\t\t\t<artifactId>mysql-connector-java</artifactId>\r\n\t\t\t<version>5.1.21</version>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\r\n\t\t</dependency>\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.sql.DataSource;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/DataSourceConfig.java",
    "content": "package com.didispace;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\n\nimport javax.sql.DataSource;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/26 下午9:11.\n * @blog http://blog.didispace.com\n */\n@Configuration\npublic class DataSourceConfig {\n\n    @Bean(name = \"primaryDataSource\")\n    @Qualifier(\"primaryDataSource\")\n    @ConfigurationProperties(prefix=\"spring.datasource.primary\")\n    public DataSource primaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n    @Bean(name = \"secondaryDataSource\")\n    @Qualifier(\"secondaryDataSource\")\n    @Primary\n    @ConfigurationProperties(prefix=\"spring.datasource.secondary\")\n    public DataSource secondaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/PrimaryConfig.java",
    "content": "package com.didispace;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;\nimport org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\nimport org.springframework.orm.jpa.JpaTransactionManager;\nimport org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;\nimport org.springframework.transaction.PlatformTransactionManager;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\nimport javax.persistence.EntityManager;\nimport javax.sql.DataSource;\nimport java.util.Map;\n\n@Configuration\n@EnableTransactionManagement\n@EnableJpaRepositories(\n        entityManagerFactoryRef=\"entityManagerFactoryPrimary\",\n        transactionManagerRef=\"transactionManagerPrimary\",\n        basePackages= { \"com.didispace.domain.p\" }) //设置Repository所在位置\npublic class PrimaryConfig {\n\n    @Autowired @Qualifier(\"primaryDataSource\")\n    private DataSource primaryDataSource;\n\n    @Primary\n    @Bean(name = \"entityManagerPrimary\")\n    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {\n        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();\n    }\n\n    @Primary\n    @Bean(name = \"entityManagerFactoryPrimary\")\n    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {\n        return builder\n                .dataSource(primaryDataSource)\n                .properties(getVendorProperties(primaryDataSource))\n                .packages(\"com.didispace.domain.p\") //设置实体类所在位置\n                .persistenceUnit(\"primaryPersistenceUnit\")\n                .build();\n    }\n\n    @Autowired\n    private JpaProperties jpaProperties;\n\n    private Map<String, String> getVendorProperties(DataSource dataSource) {\n        return jpaProperties.getHibernateProperties(dataSource);\n    }\n\n    @Primary\n    @Bean(name = \"transactionManagerPrimary\")\n    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {\n        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/SecondaryConfig.java",
    "content": "package com.didispace;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;\nimport org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\nimport org.springframework.orm.jpa.JpaTransactionManager;\nimport org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;\nimport org.springframework.transaction.PlatformTransactionManager;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\nimport javax.persistence.EntityManager;\nimport javax.sql.DataSource;\nimport java.util.Map;\n\n@Configuration\n@EnableTransactionManagement\n@EnableJpaRepositories(\n        entityManagerFactoryRef=\"entityManagerFactorySecondary\",\n        transactionManagerRef=\"transactionManagerSecondary\",\n        basePackages= { \"com.didispace.domain.s\" }) //设置Repository所在位置\npublic class SecondaryConfig {\n\n    @Autowired @Qualifier(\"secondaryDataSource\")\n    private DataSource secondaryDataSource;\n\n    @Bean(name = \"entityManagerSecondary\")\n    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {\n        return entityManagerFactorySecondary(builder).getObject().createEntityManager();\n    }\n\n    @Bean(name = \"entityManagerFactorySecondary\")\n    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {\n        return builder\n                .dataSource(secondaryDataSource)\n                .properties(getVendorProperties(secondaryDataSource))\n                .packages(\"com.didispace.domain.s\") //设置实体类所在位置\n                .persistenceUnit(\"secondaryPersistenceUnit\")\n                .build();\n    }\n\n    @Autowired\n    private JpaProperties jpaProperties;\n\n    private Map<String, String> getVendorProperties(DataSource dataSource) {\n        return jpaProperties.getHibernateProperties(dataSource);\n    }\n\n    @Bean(name = \"transactionManagerSecondary\")\n    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {\n        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/domain/p/User.java",
    "content": "package com.didispace.domain.p;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/21 下午3:35.\n * @blog http://blog.didispace.com\n */\n@Entity\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @Column(nullable = false)\n    private String name;\n\n    @Column(nullable = false)\n    private Integer age;\n\n    public User(){}\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/domain/p/UserRepository.java",
    "content": "package com.didispace.domain.p;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/domain/s/Message.java",
    "content": "package com.didispace.domain.s;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/21 下午3:35.\n * @blog http://blog.didispace.com\n */\n@Entity\npublic class Message {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @Column(nullable = false)\n    private String name;\n\n    @Column(nullable = false)\n    private String content;\n\n    public Message(){}\n\n    public Message(String name, String content) {\n        this.name = name;\n        this.content = content;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getContent() {\n        return content;\n    }\n\n    public void setContent(String content) {\n        this.content = content;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/java/com/didispace/domain/s/MessageRepository.java",
    "content": "package com.didispace.domain.s;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\npublic interface MessageRepository extends JpaRepository<Message, Long> {\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-4/src/main/resources/application.properties",
    "content": "spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.username=root\nspring.datasource.primary.password=52261340\nspring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver\n\nspring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.username=root\nspring.datasource.secondary.password=52261340\nspring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver\n\nspring.jpa.properties.hibernate.hbm2ddl.auto=create-drop"
  },
  {
    "path": "1.x/Chapter3-2-4/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.p.User;\nimport com.didispace.domain.p.UserRepository;\nimport com.didispace.domain.s.Message;\nimport com.didispace.domain.s.MessageRepository;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserRepository userRepository;\n\t@Autowired\n\tprivate MessageRepository messageRepository;\n\n\t@Before\n\tpublic void setUp() {\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\tuserRepository.save(new User(\"aaa\", 10));\n\t\tuserRepository.save(new User(\"bbb\", 20));\n\t\tuserRepository.save(new User(\"ccc\", 30));\n\t\tuserRepository.save(new User(\"ddd\", 40));\n\t\tuserRepository.save(new User(\"eee\", 50));\n\n\t\tAssert.assertEquals(5, userRepository.findAll().size());\n\n\t\tmessageRepository.save(new Message(\"o1\", \"aaaaaaaaaa\"));\n\t\tmessageRepository.save(new Message(\"o2\", \"bbbbbbbbbb\"));\n\t\tmessageRepository.save(new Message(\"o3\", \"cccccccccc\"));\n\n\t\tAssert.assertEquals(3, messageRepository.findAll().size());\n\n\t}\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n\t<modelVersion>4.0.0</modelVersion>\r\n\r\n\t<groupId>com.didispace</groupId>\r\n\t<artifactId>Chapter3-2-5</artifactId>\r\n\t<version>1.0.0</version>\r\n\t<packaging>jar</packaging>\r\n\r\n\t<name>Chapter3-2-5</name>\r\n\t<description>Spring Boot project</description>\r\n\r\n\t<parent>\r\n\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\r\n\t\t<version>1.3.2.RELEASE</version>\r\n\t\t<relativePath/> <!-- lookup parent from repository -->\r\n\t</parent>\r\n\r\n\t<properties>\r\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r\n\t\t<java.version>1.8</java.version>\r\n\t</properties>\r\n\r\n\t<dependencies>\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter</artifactId>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\r\n\t\t\t<scope>test</scope>\r\n\t\t</dependency>\r\n\r\n\t\t<dependency>\r\n\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t<artifactId>spring-boot-starter-redis</artifactId>\r\n\t\t</dependency>\r\n\r\n\t</dependencies>\r\n\t\r\n\t<build>\r\n\t\t<plugins>\r\n\t\t\t<plugin>\r\n\t\t\t\t<groupId>org.springframework.boot</groupId>\r\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\r\n\t\t\t</plugin>\r\n\t\t</plugins>\r\n\t</build>\r\n\r\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-5/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-5/src/main/java/com/didispace/RedisConfig.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.connection.RedisConnectionFactory;\nimport org.springframework.data.redis.connection.jedis.JedisConnectionFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.data.redis.serializer.*;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/4/15 下午3:19.\n * @blog http://blog.didispace.com\n */\n@Configuration\npublic class RedisConfig {\n\n    @Bean\n    JedisConnectionFactory jedisConnectionFactory() {\n        return new JedisConnectionFactory();\n    }\n\n    @Bean\n    public RedisTemplate<String, User> redisTemplate(RedisConnectionFactory factory) {\n        RedisTemplate<String, User> template = new RedisTemplate<String, User>();\n        template.setConnectionFactory(jedisConnectionFactory());\n        template.setKeySerializer(new StringRedisSerializer());\n        template.setValueSerializer(new RedisObjectSerializer());\n        return template;\n    }\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-5/src/main/java/com/didispace/RedisObjectSerializer.java",
    "content": "package com.didispace;\n\nimport org.springframework.core.convert.converter.Converter;\nimport org.springframework.core.serializer.support.DeserializingConverter;\nimport org.springframework.core.serializer.support.SerializingConverter;\nimport org.springframework.data.redis.serializer.RedisSerializer;\nimport org.springframework.data.redis.serializer.SerializationException;\n\npublic class RedisObjectSerializer implements RedisSerializer<Object> {\n\n  private Converter<Object, byte[]> serializer = new SerializingConverter();\n  private Converter<byte[], Object> deserializer = new DeserializingConverter();\n\n  static final byte[] EMPTY_ARRAY = new byte[0];\n\n  public Object deserialize(byte[] bytes) {\n    if (isEmpty(bytes)) {\n      return null;\n    }\n\n    try {\n      return deserializer.convert(bytes);\n    } catch (Exception ex) {\n      throw new SerializationException(\"Cannot deserialize\", ex);\n    }\n  }\n\n  public byte[] serialize(Object object) {\n    if (object == null) {\n      return EMPTY_ARRAY;\n    }\n\n    try {\n      return serializer.convert(object);\n    } catch (Exception ex) {\n      return EMPTY_ARRAY;\n    }\n  }\n\n  private boolean isEmpty(byte[] data) {\n    return (data == null || data.length == 0);\n  }\n}"
  },
  {
    "path": "1.x/Chapter3-2-5/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\nimport java.io.Serializable;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/4/15 下午1:58.\n * @blog http://blog.didispace.com\n */\npublic class User implements Serializable {\n\n    private static final long serialVersionUID = -1L;\n\n    private String username;\n    private Integer age;\n\n    public User(String username, Integer age) {\n        this.username = username;\n        this.age = age;\n    }\n\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        this.username = username;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-5/src/main/resources/application.properties",
    "content": "# REDIS (RedisProperties)\n# Redis数据库索引（默认为0）\nspring.redis.database=0\n# Redis服务器地址\nspring.redis.host=localhost\n# Redis服务器连接端口\nspring.redis.port=6379\n# Redis服务器连接密码（默认为空）\nspring.redis.password=\n# 连接池最大连接数（使用负值表示没有限制）\nspring.redis.pool.max-active=8\n# 连接池最大阻塞等待时间（使用负值表示没有限制）\nspring.redis.pool.max-wait=-1\n# 连接池中的最大空闲连接\nspring.redis.pool.max-idle=8\n# 连接池中的最小空闲连接\nspring.redis.pool.min-idle=0\n# 连接超时时间（毫秒）\nspring.redis.timeout=0\n\n\n"
  },
  {
    "path": "1.x/Chapter3-2-5/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.data.redis.core.StringRedisTemplate;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate StringRedisTemplate stringRedisTemplate;\n\n\t@Autowired\n\tprivate RedisTemplate<String, User> redisTemplate;\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\t// 保存字符串\n\t\tstringRedisTemplate.opsForValue().set(\"aaa\", \"111\");\n\t\tAssert.assertEquals(\"111\", stringRedisTemplate.opsForValue().get(\"aaa\"));\n\n\t\t// 保存对象\n\t\tUser user = new User(\"超人\", 20);\n\t\tredisTemplate.opsForValue().set(user.getUsername(), user);\n\n\t\tuser = new User(\"蝙蝠侠\", 30);\n\t\tredisTemplate.opsForValue().set(user.getUsername(), user);\n\n\t\tuser = new User(\"蜘蛛侠\", 40);\n\t\tredisTemplate.opsForValue().set(user.getUsername(), user);\n\n\t\tAssert.assertEquals(20, redisTemplate.opsForValue().get(\"超人\").getAge().longValue());\n\t\tAssert.assertEquals(30, redisTemplate.opsForValue().get(\"蝙蝠侠\").getAge().longValue());\n\t\tAssert.assertEquals(40, redisTemplate.opsForValue().get(\"蜘蛛侠\").getAge().longValue());\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>demo</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>demo</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-mongodb</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\n</project>\n"
  },
  {
    "path": "1.x/Chapter3-2-6/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-6/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\nimport org.springframework.data.annotation.Id;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/4/27 下午10:04.\n * @blog http://blog.didispace.com\n */\npublic class User {\n\n    @Id\n    private Long id;\n\n    private String username;\n    private Integer age;\n\n    public User(Long id, String username, Integer age) {\n        this.id = id;\n        this.username = username;\n        this.age = age;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        this.username = username;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-6/src/main/java/com/didispace/domain/UserRepository.java",
    "content": "package com.didispace.domain;\n\nimport org.springframework.data.mongodb.repository.MongoRepository;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/4/27 下午10:16.\n * @blog http://blog.didispace.com\n */\npublic interface UserRepository extends MongoRepository<User, Long> {\n\n    User findByUsername(String username);\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-6/src/main/resources/application.properties",
    "content": "spring.data.mongodb.uri=mongodb://name:pass@localhost:27017/test\n\n\n"
  },
  {
    "path": "1.x/Chapter3-2-6/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.domain.UserRepository;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserRepository userRepository;\n\n\t@Before\n\tpublic void setUp() {\n\t\tuserRepository.deleteAll();\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\t// 创建三个User，并验证User总数\n\t\tuserRepository.save(new User(1L, \"didi\", 30));\n\t\tuserRepository.save(new User(2L, \"mama\", 40));\n\t\tuserRepository.save(new User(3L, \"kaka\", 50));\n\t\tAssert.assertEquals(3, userRepository.findAll().size());\n\n\t\t// 删除一个User，再验证User总数\n\t\tUser u = userRepository.findOne(1L);\n\t\tuserRepository.delete(u);\n\t\tAssert.assertEquals(2, userRepository.findAll().size());\n\n\t\t// 删除一个User，再验证User总数\n\t\tu = userRepository.findByUsername(\"mama\");\n\t\tuserRepository.delete(u);\n\t\tAssert.assertEquals(1, userRepository.findAll().size());\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-7/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-2-7</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter3-2-7</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t\t<version>1.1.1</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t<version>5.1.21</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-7/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-7/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\npublic class User {\n\n    private Long id;\n    private String name;\n    private Integer age;\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-7/src/main/java/com/didispace/domain/UserMapper.java",
    "content": "package com.didispace.domain;\n\nimport org.apache.ibatis.annotations.*;\n\n@Mapper\npublic interface UserMapper {\n\n    @Select(\"SELECT * FROM USER WHERE NAME = #{name}\")\n    User findByName(@Param(\"name\") String name);\n\n    @Insert(\"INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})\")\n    int insert(@Param(\"name\") String name, @Param(\"age\") Integer age);\n\n}"
  },
  {
    "path": "1.x/Chapter3-2-7/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=123456\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver"
  },
  {
    "path": "1.x/Chapter3-2-7/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.domain.UserMapper;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\n@Transactional\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserMapper userMapper;\n\n\t@Test\n\t@Rollback\n\tpublic void findByName() throws Exception {\n\t\tuserMapper.insert(\"AAA\", 20);\n\t\tUser u = userMapper.findByName(\"AAA\");\n\t\tAssert.assertEquals(20, u.getAge().intValue());\n\t}\n\n}"
  },
  {
    "path": "1.x/Chapter3-2-8/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-2-8</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter3-2-8</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t\t<version>1.1.1</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t<version>5.1.21</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-8/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-8/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\npublic class User {\n\n    private Long id;\n    private String name;\n    private Integer age;\n\n    public User() {\n    }\n\n    public User(Long id, String name, Integer age) {\n        this.id = id;\n        this.name = name;\n        this.age = age;\n    }\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-8/src/main/java/com/didispace/domain/UserMapper.java",
    "content": "package com.didispace.domain;\n\nimport org.apache.ibatis.annotations.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Mapper\npublic interface UserMapper {\n\n    @Select(\"SELECT * FROM user WHERE name = #{name}\")\n    User findByName(@Param(\"name\") String name);\n\n    @Results({\n            @Result(property = \"name\", column = \"name\"),\n            @Result(property = \"age\", column = \"age\")\n    })\n    @Select(\"SELECT name, age FROM user\")\n    List<User> findAll();\n\n    @Insert(\"INSERT INTO user(name, age) VALUES(#{name}, #{age})\")\n    int insert(@Param(\"name\") String name, @Param(\"age\") Integer age);\n\n    @Update(\"UPDATE user SET age=#{age} WHERE name=#{name}\")\n    void update(User user);\n\n    @Delete(\"DELETE FROM user WHERE id =#{id}\")\n    void delete(Long id);\n\n    @Insert(\"INSERT INTO user(name, age) VALUES(#{name}, #{age})\")\n    int insertByUser(User user);\n\n    @Insert(\"INSERT INTO user(name, age) VALUES(#{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER})\")\n    int insertByMap(Map<String, Object> map);\n\n}"
  },
  {
    "path": "1.x/Chapter3-2-8/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=123456\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver"
  },
  {
    "path": "1.x/Chapter3-2-8/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.domain.UserMapper;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\n@Transactional\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserMapper userMapper;\n\n\t@Test\n\t@Rollback\n\tpublic void testUserMapper() throws Exception {\n\t\t// insert一条数据，并select出来验证\n\t\tuserMapper.insert(\"AAA\", 20);\n\t\tUser u = userMapper.findByName(\"AAA\");\n\t\tAssert.assertEquals(20, u.getAge().intValue());\n\t\t// update一条数据，并select出来验证\n\t\tu.setAge(30);\n\t\tuserMapper.update(u);\n\t\tu = userMapper.findByName(\"AAA\");\n\t\tAssert.assertEquals(30, u.getAge().intValue());\n\t\t// 删除这条数据，并select验证\n\t\tuserMapper.delete(u.getId());\n\t\tu = userMapper.findByName(\"AAA\");\n\t\tAssert.assertEquals(null, u);\n\n\t\tu = new User(\"BBB\", 30);\n\t\tuserMapper.insertByUser(u);\n\t\tAssert.assertEquals(30, userMapper.findByName(\"BBB\").getAge().intValue());\n\n\t\tMap<String, Object> map = new HashMap<>();\n\t\tmap.put(\"name\", \"CCC\");\n\t\tmap.put(\"age\", 40);\n\t\tuserMapper.insertByMap(map);\n\t\tAssert.assertEquals(40, userMapper.findByName(\"CCC\").getAge().intValue());\n\n\t\tList<User> userList = userMapper.findAll();\n\t\tfor(User user : userList) {\n\t\t\tAssert.assertEquals(null, user.getId());\n\t\t\tAssert.assertNotEquals(null, user.getName());\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-9/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-2-9</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter3-2-9</name>\n\t<description>Spring Boot with JDBCTemplate</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.5.9.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t<version>5.1.21</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.flywaydb</groupId>\n\t\t\t<artifactId>flyway-core</artifactId>\n\t\t\t<version>5.0.3</version>\n\t\t</dependency>\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-2-9/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-9/src/main/java/com/didispace/service/UserService.java",
    "content": "package com.didispace.service;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/17 下午7:04.\n * @blog http://blog.didispace.com\n */\npublic interface UserService {\n\n    /**\n     * 新增一个用户\n     * @param name\n     * @param age\n     */\n    void create(String name, Integer age);\n\n    /**\n     * 根据name删除一个用户高\n     * @param name\n     */\n    void deleteByName(String name);\n\n    /**\n     * 获取用户总量\n     */\n    Integer getAllUsers();\n\n    /**\n     * 删除所有用户\n     */\n    void deleteAllUsers();\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-9/src/main/java/com/didispace/service/UserServiceImpl.java",
    "content": "package com.didispace.service;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/17 下午6:44.\n * @blog http://blog.didispace.com\n */\n@Service\npublic class UserServiceImpl implements UserService {\n\n    @Autowired\n    private JdbcTemplate jdbcTemplate;\n\n    @Override\n    public void create(String name, Integer age) {\n        jdbcTemplate.update(\"insert into user(NAME, AGE) values(?, ?)\", name, age);\n    }\n\n    @Override\n    public void deleteByName(String name) {\n        jdbcTemplate.update(\"delete from user where NAME = ?\", name);\n    }\n\n    @Override\n    public Integer getAllUsers() {\n        return jdbcTemplate.queryForObject(\"select count(1) from user\", Integer.class);\n    }\n\n    @Override\n    public void deleteAllUsers() {\n        jdbcTemplate.update(\"delete from user\");\n    }\n}\n"
  },
  {
    "path": "1.x/Chapter3-2-9/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver\n\nflyway.locations=classpath:/db"
  },
  {
    "path": "1.x/Chapter3-2-9/src/main/resources/db/V1__Base_version.sql",
    "content": "DROP TABLE IF EXISTS `user` ;\n\n\nCREATE TABLE `user` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `name` varchar(30) NOT NULL COMMENT '姓名',\n  `age` int(5) DEFAULT NULL COMMENT '年龄',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n"
  },
  {
    "path": "1.x/Chapter3-2-9/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.service.UserService;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringBootTest\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserService userSerivce;\n\n\t@Before\n\tpublic void setUp() {\n\t\t// 准备，清空user表\n\t\tuserSerivce.deleteAllUsers();\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\t\t// 插入5个用户\n\t\tuserSerivce.create(\"a\", 1);\n\t\tuserSerivce.create(\"b\", 2);\n\t\tuserSerivce.create(\"c\", 3);\n\t\tuserSerivce.create(\"d\", 4);\n\t\tuserSerivce.create(\"e\", 5);\n\n\t\t// 查数据库，应该有5个用户\n\t\tAssert.assertEquals(5, userSerivce.getAllUsers().intValue());\n\n\t\t// 删除两个用户\n\t\tuserSerivce.deleteByName(\"a\");\n\t\tuserSerivce.deleteByName(\"e\");\n\n\t\t// 查数据库，应该有5个用户\n\t\tAssert.assertEquals(3, userSerivce.getAllUsers().intValue());\n\n\t}\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-3-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter3-3-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter3-3-1</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t<version>5.1.21</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter3-3-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-3-1/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/21 下午3:35.\n * @blog http://blog.didispace.com\n */\n@Entity\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @Column(nullable = false, length = 5)\n    private String name;\n\n    @Column(nullable = false)\n    private Integer age;\n\n    public User(){}\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-3-1/src/main/java/com/didispace/domain/UserRepository.java",
    "content": "package com.didispace.domain;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    User findByName(String name);\n\n    User findByNameAndAge(String name, Integer age);\n\n    @Query(\"from User u where u.name=:name\")\n    User findUser(@Param(\"name\") String name);\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-3-1/src/main/java/com/didispace/service/UserService.java",
    "content": "package com.didispace.service;\n\nimport com.didispace.domain.User;\nimport org.springframework.transaction.annotation.Propagation;\nimport org.springframework.transaction.annotation.Isolation;\nimport org.springframework.transaction.annotation.Transactional;\n\n\n/**\n * Created by Administrator on 2016/5/27.\n */\npublic interface UserService {\n\n    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)\n    User login(String name, String password);\n\n}\n"
  },
  {
    "path": "1.x/Chapter3-3-1/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=123456\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver\n\nspring.jpa.properties.hibernate.hbm2ddl.auto=create"
  },
  {
    "path": "1.x/Chapter3-3-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.domain.UserRepository;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserRepository userRepository;\n\n\t@Test\n\t@Transactional\n\tpublic void test() throws Exception {\n\n\t\t// 创建10条记录\n\t\tuserRepository.save(new User(\"AAA\", 10));\n\t\tuserRepository.save(new User(\"BBB\", 20));\n\t\tuserRepository.save(new User(\"CCC\", 30));\n\t\tuserRepository.save(new User(\"DDD\", 40));\n\t\tuserRepository.save(new User(\"EEE\", 50));\n\t\tuserRepository.save(new User(\"FFF\", 60));\n\t\tuserRepository.save(new User(\"GGG\", 70));\n\t\tuserRepository.save(new User(\"HHHHHHHHH\", 80));\n\t\tuserRepository.save(new User(\"III\", 90));\n\t\tuserRepository.save(new User(\"JJJ\", 100));\n\n\t\t// 测试findAll, 查询所有记录\n\t\tAssert.assertEquals(10, userRepository.findAll().size());\n\n\t\t// 测试findByName, 查询姓名为FFF的User\n\t\tAssert.assertEquals(60, userRepository.findByName(\"FFF\").getAge().longValue());\n\n\t\t// 测试findUser, 查询姓名为FFF的User\n\t\tAssert.assertEquals(60, userRepository.findUser(\"FFF\").getAge().longValue());\n\n\t\t// 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的User\n\t\tAssert.assertEquals(\"FFF\", userRepository.findByNameAndAge(\"FFF\", 60).getName());\n\n\t\t// 测试删除姓名为AAA的User\n\t\tuserRepository.delete(userRepository.findByName(\"AAA\"));\n\n\t\t// 测试findAll, 查询所有记录, 验证上面的删除是否成功\n\t\tAssert.assertEquals(9, userRepository.findAll().size());\n\n\t}\n\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-1-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-1-1</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-1-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n@SpringBootApplication\n@EnableScheduling\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-1/src/main/java/com/didispace/task/ScheduledTasks.java",
    "content": "package com.didispace.task;\n\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n@Component\npublic class ScheduledTasks {\n\n    private static final SimpleDateFormat dateFormat = new SimpleDateFormat(\"HH:mm:ss\");\n\n    @Scheduled(fixedRate = 5000)\n    public void reportCurrentTime() {\n        System.out.println(\"当前时间：\" + dateFormat.format(new Date()));\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-1/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-1-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-1-2</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-1-2</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-1-2/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n@SpringBootApplication\n@EnableAsync\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-2/src/main/java/com/didispace/async/Task.java",
    "content": "package com.didispace.async;\n\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.scheduling.annotation.AsyncResult;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\nimport java.util.concurrent.Future;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/16 下午12:58.\n * @blog http://blog.didispace.com\n */\n@Component\npublic class Task {\n\n    public static Random random =new Random();\n\n    @Async\n    public Future<String> doTaskOne() throws Exception {\n        System.out.println(\"开始做任务一\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        System.out.println(\"完成任务一，耗时：\" + (end - start) + \"毫秒\");\n        return new AsyncResult<>(\"任务一完成\");\n    }\n\n    @Async\n    public Future<String> doTaskTwo() throws Exception {\n        System.out.println(\"开始做任务二\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        System.out.println(\"完成任务二，耗时：\" + (end - start) + \"毫秒\");\n        return new AsyncResult<>(\"任务二完成\");\n    }\n\n    @Async\n    public Future<String> doTaskThree() throws Exception {\n        System.out.println(\"开始做任务三\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        System.out.println(\"完成任务三，耗时：\" + (end - start) + \"毫秒\");\n        return new AsyncResult<>(\"任务三完成\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-2/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-1-2/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.async.Task;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\nimport java.util.concurrent.Future;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate Task task;\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\tlong start = System.currentTimeMillis();\n\n\t\tFuture<String> task1 = task.doTaskOne();\n\t\tFuture<String> task2 = task.doTaskTwo();\n\t\tFuture<String> task3 = task.doTaskThree();\n\n\t\twhile(true) {\n\t\t\tif(task1.isDone() && task2.isDone() && task3.isDone()) {\n\t\t\t\t// 三个任务都调用完成，退出循环等待\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tThread.sleep(1000);\n\t\t}\n\n\t\tlong end = System.currentTimeMillis();\n\n\t\tSystem.out.println(\"任务全部完成，总耗时：\" + (end - start) + \"毫秒\");\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>Chapter4-1-3</artifactId>\n    <version>1.0.0</version>\n    <packaging>jar</packaging>\n\n    <name>Chapter4-1-3</name>\n    <description>Spring Boot project</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>1.5.10.RELEASE</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.16.20</version>\n            <scope>provided</scope>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-1-3/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;\n\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.ThreadPoolExecutor;\n\n\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n    @EnableAsync\n    @Configuration\n    class TaskPoolConfig {\n\n        @Bean(\"taskExecutor\")\n        public Executor taskExecutor() {\n            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n            executor.setCorePoolSize(10);\n            executor.setMaxPoolSize(20);\n            executor.setQueueCapacity(200);\n            executor.setKeepAliveSeconds(60);\n            executor.setThreadNamePrefix(\"taskExecutor-\");\n            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());\n            return executor;\n        }\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-3/src/main/java/com/didispace/async/Task.java",
    "content": "package com.didispace.async;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/16 下午12:58.\n * @blog http://blog.didispace.com\n */\n@Slf4j\n@Component\npublic class Task {\n\n    public static Random random = new Random();\n\n    @Async(\"taskExecutor\")\n    public void doTaskOne() throws Exception {\n        log.info(\"开始做任务一\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务一，耗时：\" + (end - start) + \"毫秒\");\n    }\n\n    @Async(\"taskExecutor\")\n    public void doTaskTwo() throws Exception {\n        log.info(\"开始做任务二\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务二，耗时：\" + (end - start) + \"毫秒\");\n    }\n\n    @Async(\"taskExecutor\")\n    public void doTaskThree() throws Exception {\n        log.info(\"开始做任务三\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务三，耗时：\" + (end - start) + \"毫秒\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-3/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-1-3/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.async.Task;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringBootTest\npublic class ApplicationTests {\n\n    @Autowired\n    private Task task;\n\n    @Test\n    public void test() throws Exception {\n\n        task.doTaskOne();\n        task.doTaskTwo();\n        task.doTaskThree();\n\n        Thread.currentThread().join();\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>Chapter4-1-4</artifactId>\n    <version>1.0.0</version>\n    <packaging>jar</packaging>\n\n    <name>Chapter4-1-4</name>\n    <description>Spring Boot project</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>1.5.10.RELEASE</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-redis</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.16.20</version>\n            <scope>provided</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-1-4/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;\n\nimport java.util.concurrent.Executor;\n\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n    @EnableAsync\n    @Configuration\n    class TaskPoolConfig {\n\n        @Bean(\"taskExecutor\")\n        public Executor taskExecutor() {\n            ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();\n            executor.setPoolSize(20);\n            executor.setThreadNamePrefix(\"taskExecutor-\");\n\n            executor.setWaitForTasksToCompleteOnShutdown(true);\n            executor.setAwaitTerminationSeconds(60);\n            return executor;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-4/src/main/java/com/didispace/async/Task.java",
    "content": "package com.didispace.async;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.redis.core.StringRedisTemplate;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/16 下午12:58.\n * @blog http://blog.didispace.com\n */\n@Slf4j\n@Component\npublic class Task {\n\n    @Autowired\n    private StringRedisTemplate stringRedisTemplate;\n\n    @Async(\"taskExecutor\")\n    public void doTaskOne() throws Exception {\n        log.info(\"开始做任务一\");\n        long start = System.currentTimeMillis();\n        log.info(stringRedisTemplate.randomKey());\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务一，耗时：\" + (end - start) + \"毫秒\");\n    }\n\n    @Async(\"taskExecutor\")\n    public void doTaskTwo() throws Exception {\n        log.info(\"开始做任务二\");\n        long start = System.currentTimeMillis();\n        log.info(stringRedisTemplate.randomKey());\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务二，耗时：\" + (end - start) + \"毫秒\");\n    }\n\n    @Async(\"taskExecutor\")\n    public void doTaskThree() throws Exception {\n        log.info(\"开始做任务三\");\n        long start = System.currentTimeMillis();\n        log.info(stringRedisTemplate.randomKey());\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务三，耗时：\" + (end - start) + \"毫秒\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-4/src/main/resources/application.properties",
    "content": "spring.redis.pool.max-wait=5000\nspring.redis.pool.max-active=10\n"
  },
  {
    "path": "1.x/Chapter4-1-4/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.async.Task;\nimport lombok.SneakyThrows;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringBootTest\npublic class ApplicationTests {\n\n    @Autowired\n    private Task task;\n\n    @Test\n    @SneakyThrows\n    public void test() {\n\n        for (int i = 0; i < 10000; i++) {\n            task.doTaskOne();\n            task.doTaskTwo();\n            task.doTaskThree();\n\n            if (i == 9999) {\n                System.exit(0);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>Chapter4-1-5</artifactId>\n    <version>1.0.0</version>\n    <packaging>jar</packaging>\n\n    <name>Chapter4-1-5</name>\n    <description>Spring Boot project</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>1.5.10.RELEASE</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.16.20</version>\n            <scope>provided</scope>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-1-5/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;\n\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.ThreadPoolExecutor;\n\n\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n    @EnableAsync\n    @Configuration\n    class TaskPoolConfig {\n\n        @Bean(\"taskExecutor\")\n        public Executor taskExecutor() {\n            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n            executor.setCorePoolSize(10);\n            executor.setMaxPoolSize(20);\n            executor.setQueueCapacity(200);\n            executor.setKeepAliveSeconds(60);\n            executor.setThreadNamePrefix(\"taskExecutor-\");\n            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());\n            return executor;\n        }\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-5/src/main/java/com/didispace/async/Task.java",
    "content": "package com.didispace.async;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.scheduling.annotation.AsyncResult;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\nimport java.util.concurrent.Future;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/16 下午12:58.\n * @blog http://blog.didispace.com\n */\n@Slf4j\n@Component\npublic class Task {\n\n    public static Random random = new Random();\n\n    @Async(\"taskExecutor\")\n    public Future<String> run() throws Exception {\n        long sleep = random.nextInt(10000);\n        log.info(\"开始任务，需耗时：\" + sleep + \"毫秒\");\n        Thread.sleep(sleep);\n        log.info(\"完成任务\");\n        return new AsyncResult<>(\"test\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-1-5/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-1-5/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.async.Task;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\n\n@Slf4j\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringBootTest\npublic class ApplicationTests {\n\n    @Autowired\n    private Task task;\n\n    @Test\n    public void test() throws Exception {\n        Future<String> futureResult = task.run();\n        String result = futureResult.get(5, TimeUnit.SECONDS);\n        log.info(result);\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-2-2</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-2-2</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t<artifactId>spring-boot-starter-logging</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-log4j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-2-2/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-2/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-2-2/src/main/resources/log4j.properties",
    "content": "# LOG4J配置\nlog4j.rootCategory=INFO, stdout, file, errorfile\nlog4j.category.com.didispace=DEBUG, didifile\nlog4j.logger.error=errorfile\n\n# 控制台输出\nlog4j.appender.stdout=org.apache.log4j.ConsoleAppender\nlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout\nlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# root日志输出\nlog4j.appender.file=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.file.file=logs/all.log\nlog4j.appender.file.DatePattern='.'yyyy-MM-dd\nlog4j.appender.file.layout=org.apache.log4j.PatternLayout\nlog4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# error日志输出\nlog4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.errorfile.file=logs/error.log\nlog4j.appender.errorfile.DatePattern='.'yyyy-MM-dd\nlog4j.appender.errorfile.Threshold = ERROR\nlog4j.appender.errorfile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# com.didispace下的日志输出\nlog4j.appender.didifile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.didifile.file=logs/my.log\nlog4j.appender.didifile.DatePattern='.'yyyy-MM-dd\nlog4j.appender.didifile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.didifile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n\n\n\n\n\n\n"
  },
  {
    "path": "1.x/Chapter4-2-2/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\tprivate Logger logger = Logger.getLogger(getClass());\n\n\t@Test\n\tpublic void test() throws Exception {\n\t\tlogger.info(\"输出info\");\n\t\tlogger.debug(\"输出debug\");\n\t\tlogger.error(\"输出error\");\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-2-3</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-2-3</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t<artifactId>spring-boot-starter-logging</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-log4j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-2-3/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-3/src/main/resources/application-dev.properties",
    "content": "logging.level.com.didispace=INFO"
  },
  {
    "path": "1.x/Chapter4-2-3/src/main/resources/application-prod.properties",
    "content": "logging.level.com.didispace=INFO"
  },
  {
    "path": "1.x/Chapter4-2-3/src/main/resources/application-test.properties",
    "content": "logging.level.com.didispace=DEBUG"
  },
  {
    "path": "1.x/Chapter4-2-3/src/main/resources/application.properties",
    "content": "spring.profiles.active=dev"
  },
  {
    "path": "1.x/Chapter4-2-3/src/main/resources/log4j.properties",
    "content": "# LOG4J配置\nlog4j.rootCategory=INFO, stdout, file, errorfile\nlog4j.category.com.didispace=${logging.level.com.didispace}, didifile\nlog4j.logger.error=errorfile\n\n# 控制台输出\nlog4j.appender.stdout=org.apache.log4j.ConsoleAppender\nlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout\nlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# root日志输出\nlog4j.appender.file=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.file.file=logs/all.log\nlog4j.appender.file.DatePattern='.'yyyy-MM-dd\nlog4j.appender.file.layout=org.apache.log4j.PatternLayout\nlog4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# error日志输出\nlog4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.errorfile.file=logs/error.log\nlog4j.appender.errorfile.DatePattern='.'yyyy-MM-dd\nlog4j.appender.errorfile.Threshold = ERROR\nlog4j.appender.errorfile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# com.didispace下的日志输出\nlog4j.appender.didifile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.didifile.file=logs/my.log\nlog4j.appender.didifile.DatePattern='.'yyyy-MM-dd\nlog4j.appender.didifile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.didifile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n\n\n\n\n\n\n"
  },
  {
    "path": "1.x/Chapter4-2-3/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\tprivate Logger logger = Logger.getLogger(getClass());\n\n\t@Test\n\tpublic void test() throws Exception {\n\t\tlogger.info(\"输出info\");\n\t\tlogger.debug(\"输出debug\");\n\t\tlogger.error(\"输出error\");\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-2-4</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-2-4</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t<artifactId>spring-boot-starter-logging</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-log4j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-aop</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-2-4/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-4/src/main/java/com/didispace/aspect/WebLogAspect.java",
    "content": "package com.didispace.aspect;\n\nimport org.apache.log4j.Logger;\nimport org.aspectj.lang.JoinPoint;\nimport org.aspectj.lang.annotation.AfterReturning;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Before;\nimport org.aspectj.lang.annotation.Pointcut;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.context.request.RequestContextHolder;\nimport org.springframework.web.context.request.ServletRequestAttributes;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Arrays;\n\n/**\n * Web层日志切面\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/17 上午10:42.\n * @blog http://blog.didispace.com\n */\n@Aspect\n@Order(5)\n@Component\npublic class WebLogAspect {\n\n    private Logger logger = Logger.getLogger(getClass());\n\n    ThreadLocal<Long> startTime = new ThreadLocal<>();\n\n    @Pointcut(\"execution(public * com.didispace.web..*.*(..))\")\n    public void webLog(){}\n\n    @Before(\"webLog()\")\n    public void doBefore(JoinPoint joinPoint) throws Throwable {\n        startTime.set(System.currentTimeMillis());\n\n        // 接收到请求，记录请求内容\n        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();\n        HttpServletRequest request = attributes.getRequest();\n\n        // 记录下请求内容\n        logger.info(\"URL : \" + request.getRequestURL().toString());\n        logger.info(\"HTTP_METHOD : \" + request.getMethod());\n        logger.info(\"IP : \" + request.getRemoteAddr());\n        logger.info(\"CLASS_METHOD : \" + joinPoint.getSignature().getDeclaringTypeName() + \".\" + joinPoint.getSignature().getName());\n        logger.info(\"ARGS : \" + Arrays.toString(joinPoint.getArgs()));\n\n    }\n\n    @AfterReturning(returning = \"ret\", pointcut = \"webLog()\")\n    public void doAfterReturning(Object ret) throws Throwable {\n        // 处理完请求，返回内容\n        logger.info(\"RESPONSE : \" + ret);\n        logger.info(\"SPEND TIME : \" + (System.currentTimeMillis() - startTime.get()));\n    }\n\n\n}\n\n"
  },
  {
    "path": "1.x/Chapter4-2-4/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.web.bind.annotation.*;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/19 下午1:27.\n * @blog http://blog.didispace.com\n */\n@RestController\npublic class HelloController {\n\n    @RequestMapping(value = \"/hello\", method = RequestMethod.GET)\n    @ResponseBody\n    public String hello(@RequestParam String name) {\n        return \"Hello \" + name;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-4/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-2-4/src/main/resources/log4j.properties",
    "content": "# LOG4J配置\nlog4j.rootCategory=INFO, stdout, file, errorfile\nlog4j.category.com.didispace=DEBUG, didifile\nlog4j.logger.error=errorfile\n\n# 控制台输出\nlog4j.appender.stdout=org.apache.log4j.ConsoleAppender\nlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout\nlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# root日志输出\nlog4j.appender.file=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.file.file=logs/all.log\nlog4j.appender.file.DatePattern='.'yyyy-MM-dd\nlog4j.appender.file.layout=org.apache.log4j.PatternLayout\nlog4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# error日志输出\nlog4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.errorfile.file=logs/error.log\nlog4j.appender.errorfile.DatePattern='.'yyyy-MM-dd\nlog4j.appender.errorfile.Threshold = ERROR\nlog4j.appender.errorfile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# com.didispace下的日志输出\nlog4j.appender.didifile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.didifile.file=logs/my.log\nlog4j.appender.didifile.DatePattern='.'yyyy-MM-dd\nlog4j.appender.didifile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.didifile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n\n\n\n\n\n\n"
  },
  {
    "path": "1.x/Chapter4-2-4/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\tprivate Logger logger = Logger.getLogger(getClass());\n\n\t@Test\n\tpublic void test() throws Exception {\n\t\tlogger.info(\"输出info\");\n\t\tlogger.debug(\"输出debug\");\n\t\tlogger.error(\"输出error\");\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-2-5</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-2-5</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t<artifactId>spring-boot-starter-logging</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-log4j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-aop</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.mongodb</groupId>\n\t\t\t<artifactId>mongodb-driver</artifactId>\n\t\t\t<version>3.2.2</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-2-5/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-5/src/main/java/com/didispace/aspect/WebLogAspect.java",
    "content": "package com.didispace.aspect;\n\nimport com.mongodb.BasicDBObject;\nimport org.apache.log4j.Logger;\nimport org.aspectj.lang.JoinPoint;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Before;\nimport org.aspectj.lang.annotation.Pointcut;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.context.request.RequestContextHolder;\nimport org.springframework.web.context.request.ServletRequestAttributes;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Arrays;\nimport java.util.Enumeration;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Web层日志切面\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/17 上午10:42.\n * @blog http://blog.didispace.com\n */\n@Aspect\n@Order(1)\n@Component\npublic class WebLogAspect {\n\n    private Logger logger = Logger.getLogger(\"mongodb\");\n\n    @Pointcut(\"execution(public * com.didispace.web..*.*(..))\")\n    public void webLog(){}\n\n    @Before(\"webLog()\")\n    public void doBefore(JoinPoint joinPoint) throws Throwable {\n        // 获取HttpServletRequest\n        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();\n        HttpServletRequest request = attributes.getRequest();\n        // 获取要记录的日志内容\n        BasicDBObject logInfo = getBasicDBObject(request, joinPoint);\n        logger.info(logInfo);\n    }\n\n\n    private BasicDBObject getBasicDBObject(HttpServletRequest request, JoinPoint joinPoint) {\n        // 基本信息\n        BasicDBObject r = new BasicDBObject();\n        r.append(\"requestURL\", request.getRequestURL().toString());\n        r.append(\"requestURI\", request.getRequestURI());\n        r.append(\"queryString\", request.getQueryString());\n        r.append(\"remoteAddr\", request.getRemoteAddr());\n        r.append(\"remoteHost\", request.getRemoteHost());\n        r.append(\"remotePort\", request.getRemotePort());\n        r.append(\"localAddr\", request.getLocalAddr());\n        r.append(\"localName\", request.getLocalName());\n        r.append(\"method\", request.getMethod());\n        r.append(\"headers\", getHeadersInfo(request));\n        r.append(\"parameters\", request.getParameterMap());\n        r.append(\"classMethod\", joinPoint.getSignature().getDeclaringTypeName() + \".\" + joinPoint.getSignature().getName());\n        r.append(\"args\", Arrays.toString(joinPoint.getArgs()));\n        return r;\n    }\n\n    /**\n     * 获取头信息\n     *\n     * @param request\n     * @return\n     */\n    private Map<String, String> getHeadersInfo(HttpServletRequest request) {\n        Map<String, String> map = new HashMap<>();\n        Enumeration headerNames = request.getHeaderNames();\n        while (headerNames.hasMoreElements()) {\n            String key = (String) headerNames.nextElement();\n            String value = request.getHeader(key);\n            map.put(key, value);\n        }\n        return map;\n    }\n\n}\n\n"
  },
  {
    "path": "1.x/Chapter4-2-5/src/main/java/com/didispace/log/MongoAppender.java",
    "content": "package com.didispace.log;\n\nimport com.mongodb.BasicDBObject;\nimport com.mongodb.MongoClient;\nimport com.mongodb.MongoClientURI;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoDatabase;\nimport org.apache.log4j.AppenderSkeleton;\nimport org.apache.log4j.spi.LoggingEvent;\n\n/**\n * 日志插入MongoDB\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/23 下午4:53.\n * @blog http://blog.didispace.com\n */\npublic class MongoAppender  extends AppenderSkeleton {\n\n    private MongoClient mongoClient;\n    private MongoDatabase mongoDatabase;\n    private MongoCollection<BasicDBObject> logsCollection;\n\n    private String connectionUrl;\n    private String databaseName;\n    private String collectionName;\n\n    @Override\n    protected void append(LoggingEvent loggingEvent) {\n\n        if(mongoDatabase == null) {\n            MongoClientURI connectionString = new MongoClientURI(connectionUrl);\n            mongoClient = new MongoClient(connectionString);\n            mongoDatabase = mongoClient.getDatabase(databaseName);\n            logsCollection = mongoDatabase.getCollection(collectionName, BasicDBObject.class);\n        }\n        logsCollection.insertOne((BasicDBObject) loggingEvent.getMessage());\n\n    }\n\n    @Override\n    public void close() {\n        if(mongoClient != null) {\n            mongoClient.close();\n        }\n    }\n\n    @Override\n    public boolean requiresLayout() {\n        return false;\n    }\n\n    public String getConnectionUrl() {\n        return connectionUrl;\n    }\n\n    public void setConnectionUrl(String connectionUrl) {\n        this.connectionUrl = connectionUrl;\n    }\n\n    public String getDatabaseName() {\n        return databaseName;\n    }\n\n    public void setDatabaseName(String databaseName) {\n        this.databaseName = databaseName;\n    }\n\n    public String getCollectionName() {\n        return collectionName;\n    }\n\n    public void setCollectionName(String collectionName) {\n        this.collectionName = collectionName;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-5/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.web.bind.annotation.*;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/5/19 下午1:27.\n * @blog http://blog.didispace.com\n */\n@RestController\npublic class HelloController {\n\n    @RequestMapping(value = \"/hello\", method = RequestMethod.GET)\n    @ResponseBody\n    public String hello(@RequestParam String name) {\n        return \"Hello \" + name;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-5/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-2-5/src/main/resources/log4j.properties",
    "content": "# LOG4J配置\nlog4j.rootCategory=INFO, stdout\nlog4j.logger.mongodb=INFO, mongodb\n\n# 控制台输出\nlog4j.appender.stdout=org.apache.log4j.ConsoleAppender\nlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout\nlog4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n\n\n# mongodb输出\nlog4j.appender.mongodb=com.didispace.log.MongoAppender\nlog4j.appender.mongodb.connectionUrl=mongodb://localhost:27017\nlog4j.appender.mongodb.databaseName=logs\nlog4j.appender.mongodb.collectionName=logs_request\n"
  },
  {
    "path": "1.x/Chapter4-2-5/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\n\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>demo</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<packaging>jar</packaging>\n\n\t<name>demo</name>\n\t<description>Demo project for Spring Boot</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.5.1.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\n</project>\n"
  },
  {
    "path": "1.x/Chapter4-2-6/src/main/java/com/didispace/DemoApplication.java",
    "content": "package com.didispace;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@SpringBootApplication\npublic class DemoApplication {\n\n\tprivate Logger logger = LoggerFactory.getLogger(getClass());\n\n\t@RequestMapping(value = \"/test\", method = RequestMethod.GET)\n\tpublic String testLogLevel() {\n\t\tlogger.debug(\"Logger Level ：DEBUG\");\n\t\tlogger.info(\"Logger Level ：INFO\");\n\t\tlogger.error(\"Logger Level ：ERROR\");\n\t\treturn \"\";\n\t}\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(DemoApplication.class, args);\n\t}\n}\n"
  },
  {
    "path": "1.x/Chapter4-2-6/src/main/resources/application.properties",
    "content": "management.security.enabled=false\n"
  },
  {
    "path": "1.x/Chapter4-2-6/src/test/java/com/didispace/DemoApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class DemoApplicationTests {\n\n\t@Test\n\tpublic void contextLoads() {\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-3-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-3-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-3-1</name>\n\t<description>Spring Boot with Thymeleaf</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-security</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-3-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-3-1/src/main/java/com/didispace/WebSecurityConfig.java",
    "content": "package com.didispace;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\n\n@Configuration\n@EnableWebSecurity\npublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http\n            .authorizeRequests()\n                .antMatchers(\"/\", \"/home\").permitAll()\n                .anyRequest().authenticated()\n                .and()\n            .formLogin()\n                .loginPage(\"/login\")\n                .permitAll()\n                .and()\n            .logout()\n                .permitAll();\n    }\n\n    @Autowired\n    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {\n        auth\n            .inMemoryAuthentication()\n                .withUser(\"user\").password(\"password\").roles(\"USER\");\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter4-3-1/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.ModelMap;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@Controller\npublic class HelloController {\n\n    @RequestMapping(\"/\")\n    public String index() {\n        return \"index\";\n    }\n\n    @RequestMapping(\"/hello\")\n    public String hello() {\n        return \"hello\";\n    }\n\n    @RequestMapping(value = \"/login\", method = RequestMethod.GET)\n    public String login() {\n        return \"login\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter4-3-1/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "1.x/Chapter4-3-1/src/main/resources/templates/hello.html",
    "content": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.thymeleaf.org\"\n      xmlns:sec=\"http://www.thymeleaf.org/thymeleaf-extras-springsecurity3\">\n<head>\n    <title>Hello World!</title>\n</head>\n<body>\n<h1 th:inline=\"text\">Hello [[${#httpServletRequest.remoteUser}]]!</h1>\n<form th:action=\"@{/logout}\" method=\"post\">\n    <input type=\"submit\" value=\"注销\"/>\n</form>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter4-3-1/src/main/resources/templates/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.thymeleaf.org\"\n      xmlns:sec=\"http://www.thymeleaf.org/thymeleaf-extras-springsecurity3\">\n<head>\n    <title>Spring Security入门</title>\n</head>\n<body>\n<h1>欢迎使用Spring Security!</h1>\n\n<p>点击 <a th:href=\"@{/hello}\">这里</a> 打个招呼吧</p>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter4-3-1/src/main/resources/templates/login.html",
    "content": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\"\n      xmlns:th=\"http://www.thymeleaf.org\"\n      xmlns:sec=\"http://www.thymeleaf.org/thymeleaf-extras-springsecurity3\">\n<head>\n    <title>Spring Security Example </title>\n</head>\n<body>\n<div th:if=\"${param.error}\">\n    用户名或密码错\n</div>\n<div th:if=\"${param.logout}\">\n    您已注销成功\n</div>\n<form th:action=\"@{/login}\" method=\"post\">\n    <div><label> 用户名 : <input type=\"text\" name=\"username\"/> </label></div>\n    <div><label> 密 码 : <input type=\"password\" name=\"password\"/> </label></div>\n    <div><input type=\"submit\" value=\"登录\"/></div>\n</form>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter4-3-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.HelloController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(\n\t\t\t\tnew HelloController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-4-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-4-1</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t<version>5.1.21</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-cache</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>net.sf.ehcache</groupId>\n\t\t\t<artifactId>ehcache</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-4-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\n@SpringBootApplication\n@EnableCaching\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-1/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/21 下午3:35.\n * @blog http://blog.didispace.com\n */\n@Entity\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @Column(nullable = false)\n    private String name;\n\n    @Column(nullable = false)\n    private Integer age;\n\n    public User(){}\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-1/src/main/java/com/didispace/domain/UserRepository.java",
    "content": "package com.didispace.domain;\n\nimport org.springframework.cache.annotation.CacheConfig;\nimport org.springframework.cache.annotation.CacheEvict;\nimport org.springframework.cache.annotation.CachePut;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\n@CacheConfig(cacheNames = \"users\")\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    @Cacheable(key = \"#p0\", condition = \"#p0.length() < 10\")\n    User findByName(String name);\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-1/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=123456\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver\n\nspring.jpa.properties.hibernate.hbm2ddl.auto=create-drop\nspring.jpa.properties.hibernate.show_sql=true"
  },
  {
    "path": "1.x/Chapter4-4-1/src/main/resources/ehcache.xml",
    "content": "<ehcache xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"ehcache.xsd\">\n\n    <cache name=\"users\"\n           maxEntriesLocalHeap=\"200\"\n           timeToLiveSeconds=\"600\">\n    </cache>\n\n</ehcache>"
  },
  {
    "path": "1.x/Chapter4-4-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.domain.UserRepository;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.cache.ehcache.EhCacheCacheManager;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserRepository userRepository;\n\n\t@Autowired\n\tprivate CacheManager cacheManager;\n\n\t@Before\n\tpublic void before() {\n\t\tuserRepository.save(new User(\"AAA\", 10));\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\tUser u1 = userRepository.findByName(\"AAA\");\n\t\tSystem.out.println(\"第一次查询：\" + u1.getAge());\n\n\t\tUser u2 = userRepository.findByName(\"AAA\");\n\t\tSystem.out.println(\"第二次查询：\" + u2.getAge());\n\n\t\tu1.setAge(20);\n\t\tuserRepository.save(u1);\n\t\tUser u3 = userRepository.findByName(\"AAA\");\n\t\tSystem.out.println(\"第三次查询：\" + u3.getAge());\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-4-2</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-4-2</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t\t<version>5.1.21</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-cache</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-redis</artifactId>\n\t\t</dependency>\n\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-4-2/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\n@SpringBootApplication\n@EnableCaching\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-2/src/main/java/com/didispace/domain/User.java",
    "content": "package com.didispace.domain;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport java.io.Serializable;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/21 下午3:35.\n * @blog http://blog.didispace.com\n */\n@Entity\npublic class User implements Serializable {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @Column(nullable = false)\n    private String name;\n\n    @Column(nullable = false)\n    private Integer age;\n\n    public User(){}\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getAge() {\n        return age;\n    }\n\n    public void setAge(Integer age) {\n        this.age = age;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-2/src/main/java/com/didispace/domain/UserRepository.java",
    "content": "package com.didispace.domain;\n\nimport org.springframework.cache.annotation.CacheConfig;\nimport org.springframework.cache.annotation.CachePut;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\n@CacheConfig(cacheNames = \"users\")\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    @Cacheable(key = \"#p0\")\n    User findByName(String name);\n\n    @CachePut(key = \"#p0.name\")\n    User save(User user);\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-4-2/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=123456\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver\n\nspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect\nspring.jpa.properties.hibernate.hbm2ddl.auto=create-drop\nspring.jpa.properties.hibernate.show_sql=true\n\nspring.redis.host=localhost\nspring.redis.port=6379\nspring.redis.pool.max-idle=8\nspring.redis.pool.min-idle=0\nspring.redis.pool.max-active=8\nspring.redis.pool.max-wait=-1\n\n"
  },
  {
    "path": "1.x/Chapter4-4-2/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.domain.User;\nimport com.didispace.domain.UserRepository;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @date 16/3/23 下午2:34.\n * @blog http://blog.didispace.com\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate UserRepository userRepository;\n\n\t@Autowired\n\tprivate CacheManager cacheManager;\n\n\t@Before\n\tpublic void before() {\n\t\tuserRepository.save(new User(\"AAA\", 10));\n\t}\n\n\t@Test\n\tpublic void test() throws Exception {\n\n\t\tUser u1 = userRepository.findByName(\"AAA\");\n\t\tSystem.out.println(\"第一次查询：\" + u1.getAge());\n\n\t\tUser u2 = userRepository.findByName(\"AAA\");\n\t\tSystem.out.println(\"第二次查询：\" + u2.getAge());\n\n\t\tu1.setAge(20);\n\t\tuserRepository.save(u1);\n\t\tUser u3 = userRepository.findByName(\"AAA\");\n\t\tSystem.out.println(\"第三次查询：\" + u3.getAge());\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-5-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter4-5-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter4-5-1</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-mail</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-velocity</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter4-5-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter4-5-1/src/main/resources/application.properties",
    "content": "spring.mail.host=smtp.qq.com\nspring.mail.username=username@qq.com\nspring.mail.password=password\nspring.mail.properties.mail.smtp.auth=true\nspring.mail.properties.mail.smtp.starttls.enable=true\nspring.mail.properties.mail.smtp.starttls.required=true"
  },
  {
    "path": "1.x/Chapter4-5-1/src/main/resources/templates/template.vm",
    "content": "<html>\n<body>\n    <h3>你好， ${username}, 这是一封模板邮件!</h3>\n</body>\n</html>"
  },
  {
    "path": "1.x/Chapter4-5-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.apache.commons.collections.map.HashedMap;\nimport org.apache.velocity.app.VelocityEngine;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.core.io.FileSystemResource;\nimport org.springframework.mail.SimpleMailMessage;\nimport org.springframework.mail.javamail.JavaMailSender;\nimport org.springframework.mail.javamail.MimeMessageHelper;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.ui.velocity.VelocityEngineUtils;\n\nimport javax.mail.internet.MimeMessage;\nimport java.io.File;\nimport java.util.Map;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate JavaMailSender mailSender;\n\t@Autowired\n\tprivate VelocityEngine velocityEngine;\n\n\t@Test\n\tpublic void sendSimpleMail() throws Exception {\n\n\t\tSimpleMailMessage message = new SimpleMailMessage();\n\t\tmessage.setFrom(\"dyc87112@qq.com\");\n\t\tmessage.setTo(\"dyc87112@qq.com\");\n\t\tmessage.setSubject(\"主题：简单邮件\");\n\t\tmessage.setText(\"测试邮件内容\");\n\n\t\tmailSender.send(message);\n\t}\n\n\t@Test\n\tpublic void sendAttachmentsMail() throws Exception {\n\n\t\tMimeMessage mimeMessage = mailSender.createMimeMessage();\n\n\t\tMimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);\n\t\thelper.setFrom(\"dyc87112@qq.com\");\n\t\thelper.setTo(\"dyc87112@qq.com\");\n\t\thelper.setSubject(\"主题：有附件\");\n\t\thelper.setText(\"有附件的邮件\");\n\n\t\tFileSystemResource file = new FileSystemResource(new File(\"weixin.jpg\"));\n\t\thelper.addAttachment(\"附件-1.jpg\", file);\n\t\thelper.addAttachment(\"附件-2.jpg\", file);\n\n\t\tmailSender.send(mimeMessage);\n\t}\n\n\t@Test\n\tpublic void sendInlineMail() throws Exception {\n\n\t\tMimeMessage mimeMessage = mailSender.createMimeMessage();\n\n\t\tMimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);\n\t\thelper.setFrom(\"dyc87112@qq.com\");\n\t\thelper.setTo(\"dyc87112@qq.com\");\n\t\thelper.setSubject(\"主题：嵌入静态资源\");\n\t\thelper.setText(\"<html><body><img src=\\\"cid:weixin\\\" ></body></html>\", true);\n\n\t\tFileSystemResource file = new FileSystemResource(new File(\"weixin.jpg\"));\n\t\thelper.addInline(\"weixin\", file);\n\n\t\tmailSender.send(mimeMessage);\n\t}\n\n\t@Test\n\tpublic void sendTemplateMail() throws Exception {\n\n\t\tMimeMessage mimeMessage = mailSender.createMimeMessage();\n\n\t\tMimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);\n\t\thelper.setFrom(\"dyc87112@qq.com\");\n\t\thelper.setTo(\"dyc87112@qq.com\");\n\t\thelper.setSubject(\"主题：模板邮件\");\n\n\t\tMap<String, Object> model = new HashedMap();\n\t\tmodel.put(\"username\", \"didi\");\n\t\tString text = VelocityEngineUtils.mergeTemplateIntoString(\n\t\t\t\tvelocityEngine, \"template.vm\", \"UTF-8\", model);\n\t\thelper.setText(text, true);\n\n\t\tmailSender.send(mimeMessage);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter5-2-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>rabbitmq-hello</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<packaging>jar</packaging>\n\n\t<name>rabbitmq-hello</name>\n\t<description>Demo project for Spring Boot</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.7.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-amqp</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "1.x/Chapter5-2-1/src/main/java/com/didispace/HelloApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class HelloApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(HelloApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter5-2-1/src/main/java/com/didispace/rabbit/RabbitConfig.java",
    "content": "package com.didispace.rabbit;\n\nimport org.springframework.amqp.core.Queue;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * @author 翟永超\n * @create 2016/9/25.\n * @blog http://blog.didispace.com\n */\n@Configuration\npublic class RabbitConfig {\n\n    @Bean\n    public Queue helloQueue() {\n        return new Queue(\"hello\");\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter5-2-1/src/main/java/com/didispace/rabbit/Receiver.java",
    "content": "package com.didispace.rabbit;\n\nimport org.springframework.amqp.rabbit.annotation.RabbitHandler;\nimport org.springframework.amqp.rabbit.annotation.RabbitListener;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Date;\n\n/**\n * @author 翟永超\n * @create 2016/9/25.\n * @blog http://blog.didispace.com\n */\n@Component\n@RabbitListener(queues = \"hello\")\npublic class Receiver {\n\n    @RabbitHandler\n    public void process(String hello) {\n        System.out.println(\"Receiver : \" + hello);\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter5-2-1/src/main/java/com/didispace/rabbit/Sender.java",
    "content": "package com.didispace.rabbit;\n\nimport org.springframework.amqp.core.AmqpTemplate;\nimport org.springframework.amqp.rabbit.core.RabbitTemplate;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Date;\n\n@Component\npublic class Sender {\n\n\t@Autowired\n\tprivate AmqpTemplate rabbitTemplate;\n\n\tpublic void send() {\n\t\tString context = \"hello \" + new Date();\n\t\tSystem.out.println(\"Sender : \" + context);\n\t\tthis.rabbitTemplate.convertAndSend(\"hello\", context);\n\t}\n\n}"
  },
  {
    "path": "1.x/Chapter5-2-1/src/main/resources/application.properties",
    "content": "spring.application.name=rabbitmq-hello\n\nspring.rabbitmq.host=localhost\nspring.rabbitmq.port=5672\nspring.rabbitmq.username=springcloud\nspring.rabbitmq.password=123456\n"
  },
  {
    "path": "1.x/Chapter5-2-1/src/test/java/com/didispace/HelloApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.rabbit.Sender;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = HelloApplication.class)\npublic class HelloApplicationTests {\n\n\t@Autowired\n\tprivate Sender sender;\n\n\t@Test\n\tpublic void hello() throws Exception {\n\t\tsender.send();\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter6-1-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>statemachine</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<packaging>jar</packaging>\n\n\t<name>statemachine</name>\n\t<description>Demo project for Spring Boot</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.4.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.statemachine</groupId>\n\t\t\t<artifactId>spring-statemachine-core</artifactId>\n\t\t\t<version>1.2.0.RELEASE</version>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "1.x/Chapter6-1-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.statemachine.StateMachine;\n\n@SpringBootApplication\npublic class Application implements CommandLineRunner {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n\t@Autowired\n\tprivate StateMachine<States, Events> stateMachine;\n\n\t@Override\n\tpublic void run(String... args) throws Exception {\n\t\tstateMachine.start();\n\t\tstateMachine.sendEvent(Events.PAY);\n\t\tstateMachine.sendEvent(Events.RECEIVE);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter6-1-1/src/main/java/com/didispace/EventConfig.java",
    "content": "package com.didispace;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.statemachine.annotation.*;\n\n/**\n * 该配置实现了com.didispace.StateMachineConfig类中定义的状态机监听器实现。\n */\n@WithStateMachine\npublic class EventConfig {\n\n    private Logger logger = LoggerFactory.getLogger(getClass());\n\n    @OnTransition(target = \"UNPAID\")\n    public void create() {\n        logger.info(\"订单创建，待支付\");\n    }\n\n    @OnTransition(source = \"UNPAID\", target = \"WAITING_FOR_RECEIVE\")\n    public void pay() {\n        logger.info(\"用户完成支付，待收货\");\n    }\n\n    @OnTransitionStart(source = \"UNPAID\", target = \"WAITING_FOR_RECEIVE\")\n    public void payStart() {\n        logger.info(\"用户完成支付，待收货: start\");\n    }\n\n    @OnTransitionEnd(source = \"UNPAID\", target = \"WAITING_FOR_RECEIVE\")\n    public void payEnd() {\n        logger.info(\"用户完成支付，待收货: end\");\n    }\n\n    @OnTransition(source = \"WAITING_FOR_RECEIVE\", target = \"DONE\")\n    public void receive() {\n        logger.info(\"用户已收货，订单完成\");\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter6-1-1/src/main/java/com/didispace/Events.java",
    "content": "package com.didispace;\n\npublic enum Events {\n    PAY,        // 支付\n    RECEIVE     // 收货\n}"
  },
  {
    "path": "1.x/Chapter6-1-1/src/main/java/com/didispace/StateMachineConfig.java",
    "content": "package com.didispace;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.statemachine.config.EnableStateMachine;\nimport org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;\nimport org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;\nimport org.springframework.statemachine.config.builders.StateMachineStateConfigurer;\nimport org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;\nimport org.springframework.statemachine.listener.StateMachineListener;\nimport org.springframework.statemachine.listener.StateMachineListenerAdapter;\nimport org.springframework.statemachine.transition.Transition;\n\nimport java.util.EnumSet;\n\n\n@Configuration\n@EnableStateMachine\npublic class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {\n\n    private Logger logger = LoggerFactory.getLogger(getClass());\n\n    @Override\n    public void configure(StateMachineStateConfigurer<States, Events> states)\n            throws Exception {\n        states\n            .withStates()\n                .initial(States.UNPAID)\n                .states(EnumSet.allOf(States.class));\n    }\n\n    @Override\n    public void configure(StateMachineTransitionConfigurer<States, Events> transitions)\n            throws Exception {\n        transitions\n            .withExternal()\n                .source(States.UNPAID).target(States.WAITING_FOR_RECEIVE)\n                .event(Events.PAY)\n                .and()\n            .withExternal()\n                .source(States.WAITING_FOR_RECEIVE).target(States.DONE)\n                .event(Events.RECEIVE);\n    }\n\n//    @Override\n//    public void configure(StateMachineConfigurationConfigurer<States, Events> config)\n//            throws Exception {\n//        config\n//            .withConfiguration()\n//                .listener(listener());\n//    }\n//\n//    @Bean\n//    public StateMachineListener<States, Events> listener() {\n//        return new StateMachineListenerAdapter<States, Events>() {\n//\n//            @Override\n//            public void transition(Transition<States, Events> transition) {\n//                if(transition.getTarget().getId() == States.UNPAID) {\n//                    logger.info(\"订单创建，待支付\");\n//                    return;\n//                }\n//\n//                if(transition.getSource().getId() == States.UNPAID\n//                        && transition.getTarget().getId() == States.WAITING_FOR_RECEIVE) {\n//                    logger.info(\"用户完成支付，待收货\");\n//                    return;\n//                }\n//\n//                if(transition.getSource().getId() == States.WAITING_FOR_RECEIVE\n//                        && transition.getTarget().getId() == States.DONE) {\n//                    logger.info(\"用户已收货，订单完成\");\n//                    return;\n//                }\n//            }\n//\n//        };\n//    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter6-1-1/src/main/java/com/didispace/States.java",
    "content": "package com.didispace;\n\npublic enum States {\n    UNPAID,                 // 待支付\n    WAITING_FOR_RECEIVE,    // 待收货\n    DONE                    // 结束\n}\n"
  },
  {
    "path": "1.x/Chapter6-1-1/src/main/resources/application.properties",
    "content": "spring.application.name=statemachine\n\n"
  },
  {
    "path": "1.x/Chapter6-2-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>Chapter6-2-1</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>Chapter6-2-1</name>\n\t<description></description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.5.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>pl.project13.maven</groupId>\n\t\t\t\t<artifactId>git-commit-id-plugin</artifactId>\n\t\t\t\t<version>2.1.15</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>revision</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t\t<configuration>\n\t\t\t\t\t<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter6-2-1/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter6-2-1/src/main/java/com/didispace/web/HelloController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@RestController\npublic class HelloController {\n\n    @RequestMapping(\"/hello\")\n    public String index() {\n        return \"Hello World\";\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter6-2-1/src/main/resources/application.properties",
    "content": "#management.info.git.mode=full"
  },
  {
    "path": "1.x/Chapter6-2-1/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootTest\npublic class ApplicationTests {\n\n\t@Test\n\tpublic void test1() throws Exception {\n\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-1/compute-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>compute-service</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>compute-service</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-1/compute-service/src/main/java/com/didispace/ComputeServiceApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class ComputeServiceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(ComputeServiceApplication.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-1/compute-service/src/main/java/com/didispace/web/ComputeController.java",
    "content": "package com.didispace.web;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ComputeController {\n\n    private final Logger logger = Logger.getLogger(getClass());\n\n    @Autowired\n    private DiscoveryClient client;\n\n    @RequestMapping(value = \"/add\" ,method = RequestMethod.GET)\n    public Integer add(@RequestParam Integer a, @RequestParam Integer b) {\n        ServiceInstance instance = client.getLocalServiceInstance();\n        Integer r = a + b;\n        logger.info(\"/add, host:\" + instance.getHost() + \", service_id:\" + instance.getServiceId() + \", result:\" + r);\n        return r;\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-1/compute-service/src/main/resources/application.properties",
    "content": "spring.application.name=compute-service\n\nserver.port=2222\n\neureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/\n\n"
  },
  {
    "path": "1.x/Chapter9-1-1/compute-service/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.ComputeController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(new ComputeController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-1/eureka-server/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>eureka-server</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>eureka-server</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka-server</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-1/eureka-server/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\n\n@EnableEurekaServer\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(Application.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-1/eureka-server/src/main/resources/application.properties",
    "content": "server.port=1111\n#eureka.instance.hostname=localhost\n\neureka.client.register-with-eureka=false\neureka.client.fetch-registry=false\neureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-feign/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>eureka-feign</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>eureka-feign</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-feign</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-feign/src/main/java/com/didispace/FeignApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.netflix.feign.EnableFeignClients;\n\n@SpringBootApplication\n@EnableDiscoveryClient\n@EnableFeignClients\npublic class FeignApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(FeignApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-feign/src/main/java/com/didispace/service/ComputeClient.java",
    "content": "package com.didispace.service;\n\nimport org.springframework.cloud.netflix.feign.FeignClient;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n@FeignClient(\"compute-service\")\npublic interface ComputeClient {\n\n    @RequestMapping(method = RequestMethod.GET, value = \"/add\")\n    Integer add(@RequestParam(value = \"a\") Integer a, @RequestParam(value = \"b\") Integer b);\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-feign/src/main/java/com/didispace/web/ConsumerController.java",
    "content": "package com.didispace.web;\n\nimport com.didispace.service.ComputeClient;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ConsumerController {\n\n    @Autowired\n    ComputeClient computeClient;\n\n    @RequestMapping(value = \"/add\", method = RequestMethod.GET)\n    public Integer add() {\n        return computeClient.add(10, 20);\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-feign/src/main/resources/application.properties",
    "content": "spring.application.name=feign-consumer\nserver.port=3333\n\neureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/\n\n"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-ribbon/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>eureka-ribbon</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>eureka-ribbon</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-ribbon</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-ribbon/src/main/java/com/didispace/RibbonApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.client.RestTemplate;\n\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class RibbonApplication {\n\n\t@Bean\n\t@LoadBalanced\n\tRestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RibbonApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-ribbon/src/main/java/com/didispace/web/ConsumerController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n@RestController\npublic class ConsumerController {\n\n    @Autowired\n    RestTemplate restTemplate;\n\n    @RequestMapping(value = \"/add\", method = RequestMethod.GET)\n    public String add() {\n        return restTemplate.getForEntity(\"http://COMPUTE-SERVICE/add?a=10&b=20\", String.class).getBody();\n    }\n\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-2/eureka-ribbon/src/main/resources/application.properties",
    "content": "spring.application.name=ribbon-consumer\nserver.port=3333\n\neureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/\n\n"
  },
  {
    "path": "1.x/Chapter9-1-3/compute-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>compute-service</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>compute-service</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-3/compute-service/src/main/java/com/didispace/ComputeServiceApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class ComputeServiceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(ComputeServiceApplication.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-3/compute-service/src/main/java/com/didispace/web/ComputeController.java",
    "content": "package com.didispace.web;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ComputeController {\n\n    private final Logger logger = Logger.getLogger(getClass());\n\n    @Autowired\n    private DiscoveryClient client;\n\n    @RequestMapping(value = \"/add\" ,method = RequestMethod.GET)\n    public Integer add(@RequestParam Integer a, @RequestParam Integer b) {\n        ServiceInstance instance = client.getLocalServiceInstance();\n        Integer r = a + b;\n        logger.info(\"/add, host:\" + instance.getHost() + \", service_id:\" + instance.getServiceId() + \", result:\" + r);\n        return r;\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-3/compute-service/src/main/resources/application.properties",
    "content": "spring.application.name=compute-service\n\nserver.port=2222\n\neureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/\n\n"
  },
  {
    "path": "1.x/Chapter9-1-3/compute-service/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.ComputeController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(new ComputeController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t\tmvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n\t\t\t\t.andExpect(status().isOk())\n\t\t\t\t.andExpect(content().string(equalTo(\"Hello World\")));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-feign/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>eureka-feign</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>eureka-feign</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<!--<dependency>-->\n\t\t\t<!--<groupId>org.springframework.cloud</groupId>-->\n\t\t\t<!--<artifactId>spring-cloud-starter-hystrix</artifactId>-->\n\t\t<!--</dependency>-->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-feign</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-feign/src/main/java/com/didispace/FeignApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.netflix.feign.EnableFeignClients;\n\n@SpringBootApplication\n@EnableDiscoveryClient\n@EnableFeignClients\npublic class FeignApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(FeignApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-feign/src/main/java/com/didispace/service/ComputeClient.java",
    "content": "package com.didispace.service;\n\nimport org.springframework.cloud.netflix.feign.FeignClient;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n@FeignClient(value = \"compute-service\", fallback = ComputeClientHystrix.class)\npublic interface ComputeClient {\n\n    @RequestMapping(method = RequestMethod.GET, value = \"/add\")\n    Integer add(@RequestParam(value = \"a\") Integer a, @RequestParam(value = \"b\") Integer b);\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-feign/src/main/java/com/didispace/service/ComputeClientHystrix.java",
    "content": "package com.didispace.service;\n\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n@Component\npublic class ComputeClientHystrix implements ComputeClient {\n\n    @Override\n    public Integer add(@RequestParam(value = \"a\") Integer a, @RequestParam(value = \"b\") Integer b) {\n        return -9999;\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-feign/src/main/java/com/didispace/web/ConsumerController.java",
    "content": "package com.didispace.web;\n\nimport com.didispace.service.ComputeClient;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ConsumerController {\n\n    @Autowired\n    ComputeClient computeClient;\n\n    @RequestMapping(value = \"/add\", method = RequestMethod.GET)\n    public Integer add() {\n        return computeClient.add(10, 20);\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-ribbon/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>eureka-ribbon</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>eureka-ribbon</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-hystrix</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-ribbon</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-ribbon/src/main/java/com/didispace/RibbonApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.client.RestTemplate;\n\n@SpringBootApplication\n@EnableDiscoveryClient\n@EnableCircuitBreaker\npublic class RibbonApplication {\n\n\t@Bean\n\t@LoadBalanced\n\tRestTemplate restTemplate() {\n\t\treturn new RestTemplate();\n\t}\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(RibbonApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-ribbon/src/main/java/com/didispace/service/ComputeService.java",
    "content": "package com.didispace.service;\n\nimport com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.client.RestTemplate;\n\n@Service\npublic class ComputeService {\n\n    @Autowired\n    RestTemplate restTemplate;\n\n    @HystrixCommand(fallbackMethod = \"addServiceFallback\")\n    public String addService() {\n        return restTemplate.getForEntity(\"http://COMPUTE-SERVICE/add?a=10&b=20\", String.class).getBody();\n    }\n\n    public String addServiceFallback() {\n        return \"error\";\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-ribbon/src/main/java/com/didispace/web/ConsumerController.java",
    "content": "package com.didispace.web;\n\nimport com.didispace.service.ComputeService;\nimport com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\nimport java.util.Map;\n\n@RestController\npublic class ConsumerController {\n\n    @Autowired\n    private ComputeService computeService;\n\n    @RequestMapping(value = \"/add\", method = RequestMethod.GET)\n    public String add() {\n        return computeService.addService();\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-server/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>eureka-server</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>eureka-server</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka-server</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-server/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\n\n@EnableEurekaServer\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(Application.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-3/eureka-server/src/main/resources/application.properties",
    "content": "server.port=1111\n#eureka.instance.hostname=localhost\n\neureka.client.register-with-eureka=false\neureka.client.fetch-registry=false\neureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/"
  },
  {
    "path": "1.x/Chapter9-1-4/config-client/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>config-client</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>config-client</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-config</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-4/config-client/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\n\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(Application.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-4/config-client/src/main/java/com/didispace/web/TestController.java",
    "content": "package com.didispace.web;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.cloud.context.config.annotation.RefreshScope;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RefreshScope\n@RestController\nclass TestController {\n\n    @Value(\"${from}\")\n    private String from;\n\n    @RequestMapping(\"/from\")\n    public String from() {\n\n        return this.from;\n    }\n\n    public void setFrom(String from) {\n        this.from = from;\n    }\n\n    public String getFrom() {\n        return from;\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-4/config-client/src/main/resources/bootstrap.properties",
    "content": "spring.application.name=didispace\nspring.cloud.config.profile=dev\nspring.cloud.config.uri=http://localhost:7001/\n\nserver.port=7002\n\n\n\n\n\n"
  },
  {
    "path": "1.x/Chapter9-1-4/config-repo/didispace-dev.properties",
    "content": "from=git-dev-1.0"
  },
  {
    "path": "1.x/Chapter9-1-4/config-repo/didispace-prod.properties",
    "content": "from=git-prod-1.0"
  },
  {
    "path": "1.x/Chapter9-1-4/config-repo/didispace-test.properties",
    "content": "from=git-test-1.0"
  },
  {
    "path": "1.x/Chapter9-1-4/config-repo/didispace.properties",
    "content": "from=git-default-1.0\n"
  },
  {
    "path": "1.x/Chapter9-1-4/config-server/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>config-server</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>config-server</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-config-server</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-4/config-server/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.config.server.EnableConfigServer;\n\n@EnableConfigServer\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(Application.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-4/config-server/src/main/resources/application.properties",
    "content": "spring.application.name=config-server\nserver.port=7001\n\n# git\nspring.cloud.config.server.git.uri=http://git.oschina.net/didispace/SpringBoot-Learning/\nspring.cloud.config.server.git.searchPaths=Chapter9-1-4/config-repo\nspring.cloud.config.server.git.username=username\nspring.cloud.config.server.git.password=password\n\n# \nspring.profiles.active=native\n\n\n\n\n"
  },
  {
    "path": "1.x/Chapter9-1-4/config-server/src/main/resources/didispace-dev.properties",
    "content": "from=local-dev"
  },
  {
    "path": "1.x/Chapter9-1-4/config-server/src/main/resources/didispace-prod.properties",
    "content": "from=local-prod"
  },
  {
    "path": "1.x/Chapter9-1-4/config-server/src/main/resources/didispace-test.properties",
    "content": "from=local-test"
  },
  {
    "path": "1.x/Chapter9-1-4/config-server/src/main/resources/didispace.properties",
    "content": "from=local"
  },
  {
    "path": "1.x/Chapter9-1-5/api-gateway/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>api-gateway</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>api-gateway</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-zuul</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-5/api-gateway/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport com.didispace.filter.AccessFilter;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.client.SpringCloudApplication;\nimport org.springframework.cloud.netflix.zuul.EnableZuulProxy;\nimport org.springframework.context.annotation.Bean;\n\n@EnableZuulProxy\n@SpringCloudApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(Application.class).web(true).run(args);\n\t}\n\n\t@Bean\n\tpublic AccessFilter accessFilter() {\n\t\treturn new AccessFilter();\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-5/api-gateway/src/main/java/com/didispace/filter/AccessFilter.java",
    "content": "package com.didispace.filter;\n\nimport com.netflix.zuul.ZuulFilter;\nimport com.netflix.zuul.context.RequestContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.http.HttpServletRequest;\n\npublic class AccessFilter extends ZuulFilter  {\n\n    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);\n\n    @Override\n    public String filterType() {\n        return \"pre\";\n    }\n\n    @Override\n    public int filterOrder() {\n        return 0;\n    }\n\n    @Override\n    public boolean shouldFilter() {\n        return true;\n    }\n\n    @Override\n    public Object run() {\n        RequestContext ctx = RequestContext.getCurrentContext();\n        HttpServletRequest request = ctx.getRequest();\n\n        log.info(String.format(\"%s request to %s\", request.getMethod(), request.getRequestURL().toString()));\n\n        Object accessToken = request.getParameter(\"accessToken\");\n        if(accessToken == null) {\n            log.warn(\"access token is empty\");\n            ctx.setSendZuulResponse(false);\n            ctx.setResponseStatusCode(401);\n            return null;\n        }\n        log.info(\"access token ok\");\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-5/api-gateway/src/main/resources/application.properties",
    "content": "spring.application.name=api-gateway\nserver.port=5555\n\n# routes to serviceId\nzuul.routes.api-a.path=/api-a/**\nzuul.routes.api-a.serviceId=service-A\n\nzuul.routes.api-b.path=/api-b/**\nzuul.routes.api-b.serviceId=service-B\n\n# routes to url\nzuul.routes.api-a-url.path=/api-a-url/**\nzuul.routes.api-a-url.url=http://localhost:2222/\n\neureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/"
  },
  {
    "path": "1.x/Chapter9-1-5/eureka-server/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>eureka-server</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>eureka-server</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka-server</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-5/eureka-server/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\n\n@EnableEurekaServer\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(Application.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-5/eureka-server/src/main/resources/application.properties",
    "content": "server.port=1111\n#eureka.instance.hostname=localhost\n\neureka.client.register-with-eureka=false\neureka.client.fetch-registry=false\neureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/"
  },
  {
    "path": "1.x/Chapter9-1-5/service-A/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>service-A</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>service-A</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-5/service-A/src/main/java/com/didispace/ComputeServiceApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class ComputeServiceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(ComputeServiceApplication.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-5/service-A/src/main/java/com/didispace/web/ComputeController.java",
    "content": "package com.didispace.web;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ComputeController {\n\n    private final Logger logger = Logger.getLogger(getClass());\n\n    @Autowired\n    private DiscoveryClient client;\n\n    @RequestMapping(value = \"/add\" ,method = RequestMethod.GET)\n    public String add(@RequestParam Integer a, @RequestParam Integer b) {\n        ServiceInstance instance = client.getLocalServiceInstance();\n        Integer r = a + b;\n        logger.info(\"/add, host:\" + instance.getHost() + \", service_id:\" + instance.getServiceId() + \", result:\" + r);\n        return \"From Service-A, Result is \" + r;\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-5/service-A/src/main/resources/application.properties",
    "content": "spring.application.name=service-A\n\nserver.port=2222\n\neureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/\n\n"
  },
  {
    "path": "1.x/Chapter9-1-5/service-A/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.ComputeController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(new ComputeController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-5/service-B/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>service-B</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>service-B</name>\n\t<description>Spring Cloud project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.5.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t<artifactId>spring-cloud-starter-eureka</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>Brixton.RELEASE</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-1-5/service-B/src/main/java/com/didispace/ComputeServiceApplication.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class ComputeServiceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tnew SpringApplicationBuilder(ComputeServiceApplication.class).web(true).run(args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-1-5/service-B/src/main/java/com/didispace/web/ComputeController.java",
    "content": "package com.didispace.web;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.ServiceInstance;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ComputeController {\n\n    private final Logger logger = Logger.getLogger(getClass());\n\n    @Autowired\n    private DiscoveryClient client;\n\n    @RequestMapping(value = \"/add\" ,method = RequestMethod.GET)\n    public String add(@RequestParam Integer a, @RequestParam Integer b) {\n        ServiceInstance instance = client.getLocalServiceInstance();\n        Integer r = a + b;\n        logger.info(\"/add, host:\" + instance.getHost() + \", service_id:\" + instance.getServiceId() + \", result:\" + r);\n        return \"From Service-B, Result is \" + r;\n    }\n\n}"
  },
  {
    "path": "1.x/Chapter9-1-5/service-B/src/main/resources/application.properties",
    "content": "spring.application.name=service-B\n\nserver.port=3333\n\neureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/\n\n"
  },
  {
    "path": "1.x/Chapter9-1-5/service-B/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.web.ComputeController;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\npublic class ApplicationTests {\n\n\tprivate MockMvc mvc;\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t\tmvc = MockMvcBuilders.standaloneSetup(new ComputeController()).build();\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-1/compute-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>compute-service</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>compute-service</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>dubbo</artifactId>\n\t\t\t<version>2.5.3</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>spring</artifactId>\n\t\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.zookeeper</groupId>\n\t\t\t<artifactId>zookeeper</artifactId>\n\t\t\t<version>3.4.6</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t\t<artifactId>slf4j-log4j12</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>log4j</groupId>\n\t\t\t\t\t<artifactId>log4j</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.github.sgroschupf</groupId>\n\t\t\t<artifactId>zkclient</artifactId>\n\t\t\t<version>0.1</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-2-1/compute-service/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ImportResource;\n\nimport java.util.concurrent.CountDownLatch;\n\n@SpringBootApplication\n@ImportResource({\"classpath:dubbo.xml\"})\npublic class Application {\n\n\tprivate static final Logger logger = Logger.getLogger(Application.class);\n\n\t@Bean\n\tpublic CountDownLatch closeLatch() {\n\t\treturn new CountDownLatch(1);\n\t}\n\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\tApplicationContext ctx = SpringApplication.run(Application.class, args);\n\t\tlogger.info(\"项目启动!\");\n\t\tCountDownLatch closeLatch = ctx.getBean(CountDownLatch.class);\n\t\tcloseLatch.await();\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-1/compute-service/src/main/java/com/didispace/service/ComputeService.java",
    "content": "package com.didispace.service;\n\n/**\n * Created by zhaiyc on 2016/7/14.\n */\npublic interface ComputeService {\n\n    Integer add(int a, int b);\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-1/compute-service/src/main/java/com/didispace/service/impl/ComputeServiceImpl.java",
    "content": "package com.didispace.service.impl;\n\nimport com.didispace.service.ComputeService;\n\n/**\n * Created by zhaiyc on 2016/7/14.\n */\npublic class ComputeServiceImpl implements ComputeService {\n\n    @Override\n    public Integer add(int a, int b) {\n        return a + b;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-1/compute-service/src/main/resources/application.properties",
    "content": "#ZooKeeper\ndubbo.registry.address=localhost:2181\n\nlogging.level.root=DEBUG"
  },
  {
    "path": "1.x/Chapter9-2-1/compute-service/src/main/resources/dubbo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd\">\n\n    <!-- 提供方应用信息，用于计算依赖关系 -->\n    <dubbo:application name=\"compute-service\"  />\n\n    <!-- 注册中心服务地址 -->\n    <dubbo:registry id=\"zookeeper\" protocol=\"zookeeper\" address=\"${dubbo.registry.address}\" />\n\n    <!-- 用dubbo协议在30001 -->\n    <dubbo:protocol name=\"dubbo\" port=\"30001\" dispather=\"all\" threadpool=\"cached\" threads=\"5000\"/>\n\n    <!-- 声明需要暴露的服务接口 -->\n    <dubbo:service interface=\"com.didispace.service.ComputeService\" ref=\"computeService\"\n                   version=\"1.0\" registry=\"zookeeper\" owner=\"shp\"/>\n\n    <!-- 具体服务接口的实现 -->\n    <bean id=\"computeService\" class=\"com.didispace.service.impl.ComputeServiceImpl\" />\n\n</beans>"
  },
  {
    "path": "1.x/Chapter9-2-1/compute-service/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-1/consumer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>consumer</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>consumer</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>dubbo</artifactId>\n\t\t\t<version>2.5.3</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>spring</artifactId>\n\t\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.zookeeper</groupId>\n\t\t\t<artifactId>zookeeper</artifactId>\n\t\t\t<version>3.4.6</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t\t<artifactId>slf4j-log4j12</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>log4j</groupId>\n\t\t\t\t\t<artifactId>log4j</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.github.sgroschupf</groupId>\n\t\t\t<artifactId>zkclient</artifactId>\n\t\t\t<version>0.1</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-2-1/consumer/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ImportResource;\n\nimport java.util.concurrent.CountDownLatch;\n\n@SpringBootApplication\n@ImportResource({\"classpath:dubbo.xml\"})\npublic class Application {\n\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-1/consumer/src/main/java/com/didispace/service/ComputeService.java",
    "content": "package com.didispace.service;\n\n/**\n * Created by zhaiyc on 2016/7/14.\n */\npublic interface ComputeService {\n\n    Integer add(int a, int b);\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-1/consumer/src/main/resources/application.properties",
    "content": "#ZooKeeper\ndubbo.registry.address=localhost:2181\n\n\nlogging.level.root=DEBUG"
  },
  {
    "path": "1.x/Chapter9-2-1/consumer/src/main/resources/dubbo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd\">\n\n    <!-- 消费方应用名 -->\n    <dubbo:application name=\"consumer\"  />\n\n    <!-- 注册中心服务地址 -->\n    <dubbo:registry id=\"zookeeper\" protocol=\"zookeeper\" address=\"${dubbo.registry.address}\" />\n\n    <!-- 引用ComputeService服务-->\n    <dubbo:reference id=\"computeService\" interface=\"com.didispace.service.ComputeService\"\n                     check=\"false\" version=\"1.0\" url=\"\" registry=\"zookeeper\" protocol=\"dubbo\" timeout=\"15000\"/>\n\n</beans>"
  },
  {
    "path": "1.x/Chapter9-2-1/consumer/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.service.ComputeService;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tComputeService computeService;\n\n\t@Test\n\tpublic void testAdd() throws Exception {\n\t\tAssert.assertEquals(\"compute-service:add\", new Integer(3), computeService.add(1, 2));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>com.didispace</groupId>\n\t\t<artifactId>compute-service</artifactId>\n\t\t<version>1.0-SNAPSHOT</version>\n\t</parent>\n\n\t<artifactId>compute-api</artifactId>\n\t<name>compute-api</name>\n\t<packaging>jar</packaging>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api/src/main/java/com/didispace/service/ComputeService.java",
    "content": "package com.didispace.service;\n\n/**\n * Created by zhaiyc on 2016/7/14.\n */\npublic interface ComputeService {\n\n    Integer add(int a, int b);\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api/src/main/java/com/didispace/service/impl/ComputeServiceImpl.java",
    "content": "package com.didispace.service.impl;\n\nimport com.didispace.service.ComputeService;\n\n/**\n * Created by zhaiyc on 2016/7/14.\n */\npublic class ComputeServiceImpl implements ComputeService {\n\n    @Override\n    public Integer add(int a, int b) {\n        return a + b;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api-server/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>compute-api-server</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>compute-api-server</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<!-- spring boot -->\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<!-- micro service api -->\n\t\t<dependency>\n\t\t\t<groupId>com.didispace</groupId>\n\t\t\t<artifactId>compute-api</artifactId>\n\t\t\t<version>1.0-SNAPSHOT</version>\n\t\t</dependency>\n\n\t\t<!-- dubbo -->\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>dubbo</artifactId>\n\t\t\t<version>2.5.3</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>spring</artifactId>\n\t\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.zookeeper</groupId>\n\t\t\t<artifactId>zookeeper</artifactId>\n\t\t\t<version>3.4.6</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t\t<artifactId>slf4j-log4j12</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>log4j</groupId>\n\t\t\t\t\t<artifactId>log4j</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.github.sgroschupf</groupId>\n\t\t\t<artifactId>zkclient</artifactId>\n\t\t\t<version>0.1</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api-server/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.apache.log4j.Logger;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ImportResource;\n\nimport java.util.concurrent.CountDownLatch;\n\n@SpringBootApplication\n@ImportResource({\"classpath:dubbo.xml\"})\npublic class Application {\n\n\tprivate static final Logger logger = Logger.getLogger(Application.class);\n\n\t@Bean\n\tpublic CountDownLatch closeLatch() {\n\t\treturn new CountDownLatch(1);\n\t}\n\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\tApplicationContext ctx = SpringApplication.run(Application.class, args);\n\t\tlogger.info(\"项目启动!\");\n\t\tCountDownLatch closeLatch = ctx.getBean(CountDownLatch.class);\n\t\tcloseLatch.await();\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api-server/src/main/java/com/didispace/service/impl/ComputeServiceImpl.java",
    "content": "package com.didispace.service.impl;\n\nimport com.didispace.service.ComputeService;\n\n/**\n * Created by zhaiyc on 2016/7/14.\n */\npublic class ComputeServiceImpl implements ComputeService {\n\n    @Override\n    public Integer add(int a, int b) {\n        return a + b;\n    }\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api-server/src/main/resources/application.properties",
    "content": "#ZooKeeper\ndubbo.registry.address=localhost:2181\n\nlogging.level.root=DEBUG"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api-server/src/main/resources/dubbo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd\">\n\n    <!-- 提供方应用信息，用于计算依赖关系 -->\n    <dubbo:application name=\"compute-service\"  />\n\n    <!-- 注册中心服务地址 -->\n    <dubbo:registry id=\"zookeeper\" protocol=\"zookeeper\" address=\"${dubbo.registry.address}\" />\n\n    <!-- 用dubbo协议在30001 -->\n    <dubbo:protocol name=\"dubbo\" port=\"30001\" dispather=\"all\" threadpool=\"cached\" threads=\"5000\"/>\n\n    <!-- 声明需要暴露的服务接口 -->\n    <dubbo:service interface=\"com.didispace.service.ComputeService\" ref=\"computeService\"\n                   version=\"1.0\" registry=\"zookeeper\" owner=\"shp\"/>\n\n    <!-- 具体服务接口的实现 -->\n    <bean id=\"computeService\" class=\"com.didispace.service.impl.ComputeServiceImpl\" />\n\n</beans>"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/compute-api-server/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\t@Before\n\tpublic void setUp() throws Exception {\n\t}\n\n\t@Test\n\tpublic void getHello() throws Exception {\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-2/compute-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>compute-service</artifactId>\n\t<packaging>pom</packaging>\n\t<version>1.0-SNAPSHOT</version>\n\n\t<modules>\n\t\t<module>compute-api</module>\n\t\t<module>compute-api-server</module>\n\t</modules>\n\n\t<properties>\n\t\t<maven.test.skip>true</maven.test.skip>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.7</java.version>\n\t\t<maven.compiler.source>1.7</maven.compiler.source>\n\t\t<maven.compiler.target>1.7</maven.compiler.target>\n\t</properties>\n\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-2-2/consumer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>consumer</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<name>consumer</name>\n\t<description>Spring Boot project</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>1.3.2.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<!-- micro service api -->\n\t\t<dependency>\n\t\t\t<groupId>com.didispace</groupId>\n\t\t\t<artifactId>compute-api</artifactId>\n\t\t\t<version>1.0-SNAPSHOT</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>dubbo</artifactId>\n\t\t\t<version>2.5.3</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<artifactId>spring</artifactId>\n\t\t\t\t\t<groupId>org.springframework</groupId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.zookeeper</groupId>\n\t\t\t<artifactId>zookeeper</artifactId>\n\t\t\t<version>3.4.6</version>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t\t<artifactId>slf4j-log4j12</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>log4j</groupId>\n\t\t\t\t\t<artifactId>log4j</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.github.sgroschupf</groupId>\n\t\t\t<artifactId>zkclient</artifactId>\n\t\t\t<version>0.1</version>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "1.x/Chapter9-2-2/consumer/src/main/java/com/didispace/Application.java",
    "content": "package com.didispace;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.ImportResource;\n\n@SpringBootApplication\n@ImportResource({\"classpath:dubbo.xml\"})\npublic class Application {\n\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "1.x/Chapter9-2-2/consumer/src/main/resources/application.properties",
    "content": "#ZooKeeper\ndubbo.registry.address=localhost:2181\n\n\nlogging.level.root=INFO"
  },
  {
    "path": "1.x/Chapter9-2-2/consumer/src/main/resources/dubbo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:dubbo=\"http://code.alibabatech.com/schema/dubbo\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd\">\n\n    <!-- 消费方应用名 -->\n    <dubbo:application name=\"consumer\"  />\n\n    <!-- 注册中心服务地址 -->\n    <dubbo:registry id=\"zookeeper\" protocol=\"zookeeper\" address=\"${dubbo.registry.address}\" />\n\n    <!-- 引用ComputeService服务-->\n    <dubbo:reference id=\"computeService\" interface=\"com.didispace.service.ComputeService\"\n                     check=\"false\" version=\"1.0\" url=\"\" registry=\"zookeeper\" protocol=\"dubbo\" timeout=\"15000\"/>\n\n</beans>"
  },
  {
    "path": "1.x/Chapter9-2-2/consumer/src/test/java/com/didispace/ApplicationTests.java",
    "content": "package com.didispace;\n\nimport com.didispace.service.ComputeService;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = Application.class)\npublic class ApplicationTests {\n\n\t@Autowired\n\tprivate ComputeService computeService;\n\n\t@Test\n\tpublic void testAdd() throws Exception {\n\t\tAssert.assertEquals(\"compute-service:add\", new Integer(3), computeService.add(1, 2));\n\t}\n\n}\n"
  },
  {
    "path": "1.x/README.md",
    "content": "该目录下为Spring Boot 1.x版本的教程，因为版本落后，**后续不再继续更新**。\n\n推荐下面的2.x版本，还在持续更新哦！\n\n- 教程汇总（1.x版本）：[《Spring Boot基础教程》](https://blog.didispace.com/spring-boot-learning-1x/)\n- 教程汇总（2.x版本）：[《Spring Boot基础教程》](https://blog.didispace.com/spring-boot-learning-2x/)\n\nSpring Boot 2.x版本的教程可在`2.x`目录下查看。\n\n\n## 教程目录（1.x版本）\n\n本教程版本基于Spring Boot 1.3.x - 1.5.x，部分内容可能会有出入。如果您发现问题，首先看版本是否一致。如果还有问题，可以提Issue指出。\n\n如果您要学习Spring Boot 2.x版本，可以切换到2.x分支学习，本教程正在连载2.x版本的最新教程，如果您觉得内容不错，Star关注我吧！\n\n#### 快速入门\n\n- [Spring Cloud Alibaba与Spring Boot、Spring Cloud之间不得不说的版本关系](http://blog.didispace.com/spring-cloud-alibaba-version/)\n- chapter1：[基本项目构建（可作为工程脚手架），引入web模块，完成一个简单的RESTful API](http://blog.didispace.com/spring-boot-learning-1/)\n- [使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程](http://blog.didispace.com/spring-initializr-in-intellij/)\n\n> 提示：我们在学习Spring Boot、Spring Cloud的时候，一定要知道它们的版本关系，以避免不必要的困恼。\n\n#### 工程配置\n\n- chapter2-1-1：[配置文件详解：自定义属性、随机数、多环境配置等](http://blog.didispace.com/springbootproperties/)\n- chapter2-2-1：[2.0 新特性（一）：配置绑定全解析](http://blog.didispace.com/Spring-Boot-2-0-feature-1-relaxed-binding-2/)\n- chapter2-1-2：[2.0 新特性（二）：新增事件ApplicationStartedEvent](http://blog.didispace.com/Spring-Boot-2-0-feature-2-ApplicationStartedEvent/)\n\n#### Web开发\n\n- chapter3-1-1：[构建一个较为复杂的RESTful API以及单元测试](http://blog.didispace.com/springbootrestfulapi/)\n- chapter3-1-2：[使用Thymeleaf模板引擎渲染web视图](http://blog.didispace.com/springbootweb/)\n- chapter3-1-3：[使用Freemarker模板引擎渲染web视图](http://blog.didispace.com/springbootweb/)\n- chapter3-1-4：[使用Velocity模板引擎渲染web视图](http://blog.didispace.com/springbootweb/)\n- chapter3-1-5：[使用Swagger2构建RESTful API](http://blog.didispace.com/springbootswagger2/)\n- chapter3-1-6：[统一异常处理](http://blog.didispace.com/springbootexception/)\n- chapter3-1-7：[使用Java 8中LocalDate等时间日期类的问题解决](http://blog.didispace.com/Spring-Boot-And-Feign-Use-localdate/)\n- chapter3-1-8：[扩展XML请求和响应的支持](http://blog.didispace.com/spring-boot-xml-httpmessageconverter)\n\n#### 数据访问\n\n- chapter3-2-1：[使用JdbcTemplate](http://blog.didispace.com/springbootdata1/)\n- chapter3-2-2：[使用Spring-data-jpa简化数据访问层（推荐）](http://blog.didispace.com/springbootdata2/)\n- chapter3-2-3：[多数据源配置（一）：JdbcTemplate](http://blog.didispace.com/springbootmultidatasource/)\n- chapter3-2-4：[多数据源配置（二）：Spring-data-jpa](http://blog.didispace.com/springbootmultidatasource/)\n- chapter3-2-5：[使用NoSQL数据库（一）：Redis](http://blog.didispace.com/springbootredis/)\n- chapter3-2-6：[使用NoSQL数据库（二）：MongoDB](http://blog.didispace.com/springbootmongodb/)\n- chapter3-2-7：[整合MyBatis](http://blog.didispace.com/springbootmybatis/)\n- chapter3-2-8：[MyBatis注解配置详解](http://blog.didispace.com/mybatisinfo/)\n- chapter3-2-9：[使用Flyway来管理数据库版本](http://blog.didispace.com/spring-boot-flyway-db-version/)\n- chapter3-2-10：[使用LDAP来统一管理用户信息](http://blog.didispace.com/spring-boot-ldap-user/)\n- chapter3-2-11：[Spring Boot中增强对MongoDB的配置（连接池等）](http://blog.didispace.com/springbootmongodb-plus/)\n\n#### 事务管理\n\n- chapter3-3-1：[使用事务管理](http://blog.didispace.com/springboottransactional/)\n- chapter3-3-2：[分布式事务（未完成）]\n\n#### 其他内容\n\n- chapter4-1-1：[使用@Scheduled创建定时任务](http://blog.didispace.com/springbootscheduled/)\n- chapter4-1-2：[使用@Async实现异步调用](http://blog.didispace.com/springbootasync/)\n- chapter4-1-3：[使用@Async实现异步调用：自定义线程池](http://blog.didispace.com/springbootasync-2/)\n- chapter4-1-4：[使用@Async实现异步调用：资源优雅关闭](http://blog.didispace.com/springbootasync-3/)\n- chapter4-1-5：[使用@Async实现异步调用：使用Future以及定义超时](http://blog.didispace.com/springbootasync-4/)\n\n#### 日志管理\n\n- chapter4-2-1：[默认日志的配置](http://blog.didispace.com/springbootlog/)\n- chapter4-2-2：[使用log4j记录日志](http://blog.didispace.com/springbootlog4j/)\n- chapter4-2-3：[对log4j进行多环境不同日志级别的控制](http://blog.didispace.com/springbootlog4jmuilt/)\n- chapter4-2-4：[使用AOP统一处理Web请求日志](http://blog.didispace.com/springbootaoplog/)\n- chapter4-2-5：[使用log4j记录日志到MongoDB](http://blog.didispace.com/springbootlog4jmongodb/)\n- chapter4-2-6：[Spring Boot 1.5.x新特性：动态修改日志级别](http://blog.didispace.com/spring-boot-1-5-x-feature-1/)]\n\n#### 安全管理\n\n- chapter4-3-1：[使用Spring Security](http://blog.didispace.com/springbootsecurity/)\n- chapter4-3-2：[使用Spring Session（未完成）]\n\n#### 缓存支持\n\n- chapter4-4-1：[注解配置与EhCache使用](http://blog.didispace.com/springbootcache1/)\n- chapter4-4-2：[使用Redis做集中式缓存](http://blog.didispace.com/springbootcache2/)\n\n#### 邮件发送\n\n- chapter4-5-1：[实现邮件发送：简单邮件、附件邮件、嵌入资源的邮件、模板邮件](http://blog.didispace.com/springbootmailsender/)\n\n#### 消息服务\n\n- chapter5-1-1：[JMS（未完成）]\n- chapter5-2-1：[Spring Boot中使用RabbitMQ](http://blog.didispace.com/spring-boot-rabbitmq/)\n\n#### 其他功能\n\n- chapter6-1-1：[使用Spring StateMachine框架实现状态机](http://blog.didispace.com/spring-statemachine/)\n- [Spring Boot Actuator监控端点小结](http://blog.didispace.com/spring-boot-actuator-1/)\n- [在传统Spring应用中使用spring-boot-actuator模块提供监控端点](http://blog.didispace.com/spring-boot-actuator-without-boot/)\n- [Spring Boot应用的后台运行配置](http://blog.didispace.com/spring-boot-run-backend/)\n- [Spring Boot自定义Banner](http://blog.didispace.com/spring-boot-banner/)\n\n#### Dubbo进行服务治理\n\n- chapter9-2-1：[Spring Boot中使用Dubbo进行服务治理](https://gitee.com/didispace/SpringBoot-Learning/tree/master/Chapter9-2-1)\n- chapter9-2-2：[Spring Boot与Dubbo中管理服务依赖](https://gitee.com/didispace/SpringBoot-Learning/tree/master/Chapter9-2-2)\n\n## 推荐内容\n\n- [我的博客](http://blog.didispace.com)：分享平时学习和实践过的技术内容\n- [知识星球](https://t.xiaomiquan.com/zfEiY3v)：聊聊技术人的斜杠生活\n- [GitHub](https://github.com/dyc87112/SpringBoot-Learning)：Star支持一下呗\n- [Gitee](https://gitee.com/didispace/SpringBoot-Learning)：Star支持一下呗\n- [Spring问答社区](http://www.spring4all.com/)：如果您有什么问题，可以去这里发帖\n- [Spring Boot基础教程](http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)：全网Star最多的免费Spring Boot基础教程\n- [Spring Cloud基础教程](http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)：全网最早最全的免费Spring Cloud基础教程\n\n## 我的公众号\n\n<img src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/weixin.jpg?raw=true\" style=\"width:150px;height:150px;\" />\n\n\n"
  },
  {
    "path": "1.x/README_zh.md",
    "content": "该目录下为Spring Boot 1.x版本的教程，因为版本落后，**后续不再继续更新**。\n\n推荐下面的2.x版本，还在持续更新哦！\n\n- 教程汇总（1.x版本）：[《Spring Boot基础教程》](https://blog.didispace.com/spring-boot-learning-1x/)\n- 教程汇总（2.x版本）：[《Spring Boot基础教程》](https://blog.didispace.com/spring-boot-learning-2x/)\n\nSpring Boot 2.x版本的教程可在`2.x`目录下查看。\n\n\n## 教程目录（1.x版本）\n\n本教程版本基于Spring Boot 1.3.x - 1.5.x，部分内容可能会有出入。如果您发现问题，首先看版本是否一致。如果还有问题，可以提Issue指出。\n\n如果您要学习Spring Boot 2.x版本，可以切换到2.x分支学习，本教程正在连载2.x版本的最新教程，如果您觉得内容不错，Star关注我吧！\n\n#### 快速入门\n\n- [Spring Cloud Alibaba与Spring Boot、Spring Cloud之间不得不说的版本关系](http://blog.didispace.com/spring-cloud-alibaba-version/)\n- chapter1：[基本项目构建（可作为工程脚手架），引入web模块，完成一个简单的RESTful API](http://blog.didispace.com/spring-boot-learning-1/)\n- [使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程](http://blog.didispace.com/spring-initializr-in-intellij/)\n\n> 提示：我们在学习Spring Boot、Spring Cloud的时候，一定要知道它们的版本关系，以避免不必要的困恼。\n\n#### 工程配置\n\n- chapter2-1-1：[配置文件详解：自定义属性、随机数、多环境配置等](http://blog.didispace.com/springbootproperties/)\n- chapter2-2-1：[2.0 新特性（一）：配置绑定全解析](http://blog.didispace.com/Spring-Boot-2-0-feature-1-relaxed-binding-2/)\n- chapter2-1-2：[2.0 新特性（二）：新增事件ApplicationStartedEvent](http://blog.didispace.com/Spring-Boot-2-0-feature-2-ApplicationStartedEvent/)\n\n#### Web开发\n\n- chapter3-1-1：[构建一个较为复杂的RESTful API以及单元测试](http://blog.didispace.com/springbootrestfulapi/)\n- chapter3-1-2：[使用Thymeleaf模板引擎渲染web视图](http://blog.didispace.com/springbootweb/)\n- chapter3-1-3：[使用Freemarker模板引擎渲染web视图](http://blog.didispace.com/springbootweb/)\n- chapter3-1-4：[使用Velocity模板引擎渲染web视图](http://blog.didispace.com/springbootweb/)\n- chapter3-1-5：[使用Swagger2构建RESTful API](http://blog.didispace.com/springbootswagger2/)\n- chapter3-1-6：[统一异常处理](http://blog.didispace.com/springbootexception/)\n- chapter3-1-7：[使用Java 8中LocalDate等时间日期类的问题解决](http://blog.didispace.com/Spring-Boot-And-Feign-Use-localdate/)\n- chapter3-1-8：[扩展XML请求和响应的支持](http://blog.didispace.com/spring-boot-xml-httpmessageconverter)\n\n#### 数据访问\n\n- chapter3-2-1：[使用JdbcTemplate](http://blog.didispace.com/springbootdata1/)\n- chapter3-2-2：[使用Spring-data-jpa简化数据访问层（推荐）](http://blog.didispace.com/springbootdata2/)\n- chapter3-2-3：[多数据源配置（一）：JdbcTemplate](http://blog.didispace.com/springbootmultidatasource/)\n- chapter3-2-4：[多数据源配置（二）：Spring-data-jpa](http://blog.didispace.com/springbootmultidatasource/)\n- chapter3-2-5：[使用NoSQL数据库（一）：Redis](http://blog.didispace.com/springbootredis/)\n- chapter3-2-6：[使用NoSQL数据库（二）：MongoDB](http://blog.didispace.com/springbootmongodb/)\n- chapter3-2-7：[整合MyBatis](http://blog.didispace.com/springbootmybatis/)\n- chapter3-2-8：[MyBatis注解配置详解](http://blog.didispace.com/mybatisinfo/)\n- chapter3-2-9：[使用Flyway来管理数据库版本](http://blog.didispace.com/spring-boot-flyway-db-version/)\n- chapter3-2-10：[使用LDAP来统一管理用户信息](http://blog.didispace.com/spring-boot-ldap-user/)\n- chapter3-2-11：[Spring Boot中增强对MongoDB的配置（连接池等）](http://blog.didispace.com/springbootmongodb-plus/)\n\n#### 事务管理\n\n- chapter3-3-1：[使用事务管理](http://blog.didispace.com/springboottransactional/)\n- chapter3-3-2：[分布式事务（未完成）]\n\n#### 其他内容\n\n- chapter4-1-1：[使用@Scheduled创建定时任务](http://blog.didispace.com/springbootscheduled/)\n- chapter4-1-2：[使用@Async实现异步调用](http://blog.didispace.com/springbootasync/)\n- chapter4-1-3：[使用@Async实现异步调用：自定义线程池](http://blog.didispace.com/springbootasync-2/)\n- chapter4-1-4：[使用@Async实现异步调用：资源优雅关闭](http://blog.didispace.com/springbootasync-3/)\n- chapter4-1-5：[使用@Async实现异步调用：使用Future以及定义超时](http://blog.didispace.com/springbootasync-4/)\n\n#### 日志管理\n\n- chapter4-2-1：[默认日志的配置](http://blog.didispace.com/springbootlog/)\n- chapter4-2-2：[使用log4j记录日志](http://blog.didispace.com/springbootlog4j/)\n- chapter4-2-3：[对log4j进行多环境不同日志级别的控制](http://blog.didispace.com/springbootlog4jmuilt/)\n- chapter4-2-4：[使用AOP统一处理Web请求日志](http://blog.didispace.com/springbootaoplog/)\n- chapter4-2-5：[使用log4j记录日志到MongoDB](http://blog.didispace.com/springbootlog4jmongodb/)\n- chapter4-2-6：[Spring Boot 1.5.x新特性：动态修改日志级别](http://blog.didispace.com/spring-boot-1-5-x-feature-1/)]\n\n#### 安全管理\n\n- chapter4-3-1：[使用Spring Security](http://blog.didispace.com/springbootsecurity/)\n- chapter4-3-2：[使用Spring Session（未完成）]\n\n#### 缓存支持\n\n- chapter4-4-1：[注解配置与EhCache使用](http://blog.didispace.com/springbootcache1/)\n- chapter4-4-2：[使用Redis做集中式缓存](http://blog.didispace.com/springbootcache2/)\n\n#### 邮件发送\n\n- chapter4-5-1：[实现邮件发送：简单邮件、附件邮件、嵌入资源的邮件、模板邮件](http://blog.didispace.com/springbootmailsender/)\n\n#### 消息服务\n\n- chapter5-1-1：[JMS（未完成）]\n- chapter5-2-1：[Spring Boot中使用RabbitMQ](http://blog.didispace.com/spring-boot-rabbitmq/)\n\n#### 其他功能\n\n- chapter6-1-1：[使用Spring StateMachine框架实现状态机](http://blog.didispace.com/spring-statemachine/)\n- [Spring Boot Actuator监控端点小结](http://blog.didispace.com/spring-boot-actuator-1/)\n- [在传统Spring应用中使用spring-boot-actuator模块提供监控端点](http://blog.didispace.com/spring-boot-actuator-without-boot/)\n- [Spring Boot应用的后台运行配置](http://blog.didispace.com/spring-boot-run-backend/)\n- [Spring Boot自定义Banner](http://blog.didispace.com/spring-boot-banner/)\n\n#### Dubbo进行服务治理\n\n- chapter9-2-1：[Spring Boot中使用Dubbo进行服务治理](https://gitee.com/didispace/SpringBoot-Learning/tree/master/Chapter9-2-1)\n- chapter9-2-2：[Spring Boot与Dubbo中管理服务依赖](https://gitee.com/didispace/SpringBoot-Learning/tree/master/Chapter9-2-2)\n\n## 推荐内容\n\n- [我的博客](http://blog.didispace.com)：分享平时学习和实践过的技术内容\n- [知识星球](https://t.xiaomiquan.com/zfEiY3v)：聊聊技术人的斜杠生活\n- [GitHub](https://github.com/dyc87112/SpringBoot-Learning)：Star支持一下呗\n- [Gitee](https://gitee.com/didispace/SpringBoot-Learning)：Star支持一下呗\n- [Spring问答社区](http://www.spring4all.com/)：如果您有什么问题，可以去这里发帖\n- [Spring Boot基础教程](http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)：全网Star最多的免费Spring Boot基础教程\n- [Spring Cloud基础教程](http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)：全网最早最全的免费Spring Cloud基础教程\n\n## 我的公众号\n\n<img src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/weixin.jpg?raw=true\" style=\"width:150px;height:150px;\" />\n\n\n"
  },
  {
    "path": "2.x/README.md",
    "content": "# Spring Boot基础教程（2.x版本）\n\n本项目内容为[《Spring Boot基础教程》](http://blog.didispace.com/spring-boot-learning-2x/)的程序样例。\n\n**专题目标**：打造全网内容最全，比收费教程更好的Spring Boot免费教程！\n\n**加入社群**：如果你正在学习Spring Boot，不妨加入我们的[Spring技术交流群](https://blog.didispace.com/join-group-spring/index.html) ，一起成长\n\n**Spring社区**：如果您在学习过程中碰到问题，可以访问[SpringForAll社区](http://spring4all.com)，描述你的问题，我们会尽快给你答复。当然，如果你想分享你的学习经验，也可以在这里发表你的文章\n\n**如何支持**：\n\n1. 关注我的公众号”**程序猿DD**“\n2. 点个`Star`并`Follow`我\n3. 把该仓库分享给更多的朋友\n\n## 教程目录（2.x版本）\n\n本教程内容持续更新连载中！**Star关注**支持一下，随时获得更新信息！\n\n### 快速入门\n\n- [Spring Boot 2.x基础教程：版本关系](http://blog.didispace.com/spring-cloud-alibaba-version/)\n- [Spring Boot 2.x基础教程：快速入门](http://blog.didispace.com/spring-boot-learning-21-1-1/)\n- [Spring Boot 2.x基础教程：工程结构推荐](http://blog.didispace.com/spring-boot-learning-21-1-2/)\n\n### 配置详解\n\n- [Spring Boot 2.x基础教程：配置文件详解](http://blog.didispace.com/spring-boot-learning-21-1-3/)\n- [Spring Boot 2.x基础教程：2.4版本前后的多环境配置变化](http://blog.didispace.com/spring-boot-learning-24-1-4/)\n- [Spring Boot 2.x基础教程：2.4版本前后的分组配置变化](http://blog.didispace.com/spring-boot-learning-24-1-5/)\n- [Spring Boot 2.x基础教程：配置元数据的应用 ](http://blog.didispace.com/spring-boot-learning-24-1-6/)\n- [Spring Boot 2.x基础教程：加密配置中的敏感信息](http://blog.didispace.com/spring-boot-learning-2-1-5/)\n\n### API开发\n\n- [Spring Boot 2.x基础教程：构建RESTful API与单元测试](http://blog.didispace.com/spring-boot-learning-21-2-1/)\n- [Spring Boot 2.x基础教程：使用Swagger2构建强大的API文档](http://blog.didispace.com/spring-boot-learning-21-2-2/)\n- [Spring Boot 2.x基础教程：JSR-303实现请求参数校验](http://blog.didispace.com/spring-boot-learning-21-2-3/)\n- [Spring Boot 2.x基础教程：Swagger接口分类与各元素排序问题详解](http://blog.didispace.com/spring-boot-learning-21-2-4/)\n- [Spring Boot 2.x基础教程：Swagger静态文档的生成](http://blog.didispace.com/spring-boot-learning-21-2-5/)\n- [Spring Boot 2.x基础教程：找回启动日志中的请求路径列表](http://blog.didispace.com/spring-boot-learning-21-2-6/)\n- [Spring Boot 2.x基础教程：使用SpringFox 3生成Swagger文档](http://blog.didispace.com/spring-boot-learning-21-2-7/)\n- [Spring Boot 2.x基础教程：如何扩展XML格式的请求和响应](http://blog.didispace.com/spring-boot-learning-21-2-8/)\n\n### 数据访问\n\n**关系型数据库**\n\n- [Spring Boot 2.x基础教程：使用JdbcTemplate访问MySQL数据库](http://blog.didispace.com/spring-boot-learning-21-3-1/)\n- [Spring Boot 2.x基础教程：默认数据源Hikari的配置详解](http://blog.didispace.com/spring-boot-learning-21-3-2/)\n- [Spring Boot 2.x基础教程：使用国产数据库连接池Druid](http://blog.didispace.com/spring-boot-learning-21-3-3/)\n- [Spring Boot 2.x基础教程：使用Spring Data JPA访问MySQL](http://blog.didispace.com/spring-boot-learning-21-3-4/)\n- [Spring Boot 2.x基础教程：使用MyBatis访问MySQL](http://blog.didispace.com/spring-boot-learning-21-3-5/)\n- [Spring Boot 2.x基础教程：使用MyBatis的XML配置方式](http://blog.didispace.com/spring-boot-learning-21-3-6/)\n- [Spring Boot 2.x基础教程：JdbcTemplate的多数据源配置](http://blog.didispace.com/spring-boot-learning-21-3-7/)\n- [Spring Boot 2.x基础教程：Spring Data JPA的多数据源配置](http://blog.didispace.com/spring-boot-learning-21-3-8/)\n- [Spring Boot 2.x基础教程：MyBatis的多数据源配置](http://blog.didispace.com/spring-boot-learning-21-3-9/)\n- [Spring Boot 2.x基础教程：事务管理入门](http://blog.didispace.com/spring-boot-learning-21-3-10/)\n- [Spring Boot 2.x基础教程：使用Flyway管理数据库版本](http://blog.didispace.com/spring-boot-learning-24-3-11/)\n- [Spring Boot 2.x基础教程：使用JTA实现多数据源的事务管理](http://blog.didispace.com/spring-boot-learning-24-3-12/)\n- [Spring Boot 2.x基础教程：2.5版本后数据脚本初始化的变动](http://blog.didispace.com/spring-boot-learning-25-3-13/)\n\n**加速利器：各种缓存的使用**\n\n- [Spring Boot 2.x基础教程：进程内缓存的使用与Cache注解详解](http://blog.didispace.com/spring-boot-learning-21-5-1/)\n- [Spring Boot 2.x基础教程：EhCache缓存的使用](http://blog.didispace.com/spring-boot-learning-21-5-2/)\n- [Spring Boot 2.x基础教程：使用EhCache缓存集群](http://blog.didispace.com/spring-boot-learning-21-5-3/)\n- [Spring Boot 2.x基础教程：使用集中式缓存Redis](http://blog.didispace.com/spring-boot-learning-21-5-4/)\n- [Spring Boot 2.x基础教程：使用Redis的发布订阅功能](http://blog.didispace.com/spring-boot-learning-25-5-5/)\n\n**其他常见存储的使用**\n\n- [Spring Boot 2.x基础教程：使用MongoDB](http://blog.didispace.com/spring-boot-learning-24-6-1/)\n- [Spring Boot 2.x基础教程：使用LDAP来管理用户与组织数据](http://blog.didispace.com/spring-boot-learning-24-6-2/)\n- [Spring Boot 2.x基础教程：使用时序数据库InfluxDB](http://blog.didispace.com/spring-boot-learning-2-6-3/)\n- [Spring Boot 2.x基础教程：使用PostgreSQL](http://blog.didispace.com/spring-boot-learning-2-6-4/)\n\n### Web开发\n\n- [Spring Boot 2.x基础教程：使用 Thymeleaf开发Web页面](http://blog.didispace.com/spring-boot-learning-21-4-1/)\n- [Spring Boot 2.x基础教程：使用 ECharts 绘制各种华丽的数据图表](http://blog.didispace.com/spring-boot-learning-21-4-2/)\n- [Spring Boot 2.x基础教程：实现文件上传](http://blog.didispace.com/spring-boot-learning-21-4-3/)\n- [Spring Boot 2.x基础教程：多个文件的上传](http://blog.didispace.com/spring-boot-learning-21-4-4/)\n- [Spring Boot 2.x基础教程：文件上传的单元测试怎么写](http://blog.didispace.com/spring-boot-learning-21-4-5/)\n\n### 任务管理\n\n**定时任务**\n\n- [Spring Boot 2.x基础教程：使用@Scheduled实现定时任务](https://blog.didispace.com/spring-boot-learning-2-7-1)\n- [Spring Boot 2.x基础教程：使用Elastic Job实现定时任务](https://blog.didispace.com/spring-boot-learning-2-7-2)\n- [Spring Boot 2.x基础教程：使用Elastic Job的分片配置提高执行效率](https://blog.didispace.com/spring-boot-learning-2-7-3)\n- [Spring Boot 2.x基础教程：使用Elastic Job的namespace防止任务名冲突](https://blog.didispace.com/spring-boot-learning-2-7-4)\n\n**异步任务**\n\n- [Spring Boot 2.x基础教程：使用@Async实现异步任务](https://blog.didispace.com/spring-boot-learning-2-7-5)\n- [Spring Boot 2.x基础教程：配置@Async异步任务的线程池](https://blog.didispace.com/spring-boot-learning-2-7-6)\n- [Spring Boot 2.x基础教程：如何隔离@Async异步任务的线程池](https://blog.didispace.com/spring-boot-learning-2-7-7)\n- [Spring Boot 2.x基础教程：配置线程池的拒绝策略](https://blog.didispace.com/spring-boot-learning-2-7-8)\n\n### 日志管理\n\n- [Spring Boot 2.x基础教程：默认日志管理与Logback配置详解](https://blog.didispace.com/spring-boot-learning-2-8-1)\n- [Spring Boot 2.x基础教程：使用log4j2记录日志](https://blog.didispace.com/spring-boot-learning-2-8-2)\n- [Spring Boot 2.x基础教程：使用tinylog记录日志](https://blog.didispace.com/spring-boot-learning-2-8-3)\n\n\n### 其他内容\n\n- [Spring Boot自定义启动Banner](http://blog.didispace.com/spring-boot-banner/)\n- [实现邮件发送：简单邮件、附件邮件、嵌入资源的邮件、模板邮件](http://blog.didispace.com/springbootmailsender/)\n- [使用Spring StateMachine框架实现状态机](http://blog.didispace.com/spring-statemachine/)\n- [Spring Boot应用的后台运行配置](http://blog.didispace.com/spring-boot-run-backend/)\n\n## 进阶与深入\n\n- [什么时候不要使用@Autowire](http://blog.didispace.com/when-not-use-autowire-in-spring-boot/)\n- [为什么加了@Transactional注解，事务没有回滚？](http://blog.didispace.com/transactional-not-rollback/)\n- [为什么启动时候API路径都没了？](http://blog.didispace.com/spring-boot-learning-21-2-6/)\n- [使用Java 8中LocalDate等时间日期类的问题解决](http://blog.didispace.com/Spring-Boot-And-Feign-Use-localdate/)\n- [Request header is too large 如何解决？](https://blog.didispace.com/request-header-is-too-large/)\n- [Spring Boot自动化配置的利弊及解决之道](http://blog.didispace.com/spring-boot-disable-autoconfig/)\n\n## 版本资讯\n\n### 1.x到2.x\n\n- [Spring Boot 2.0 正式发布，升还是不升呢？](http://blog.didispace.com/spring-boot-2-release/)\n- [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/)\n- [Spring Boot 2.0 与 Java 9](http://blog.didispace.com/Spring-Boot-2.0%E4%B8%8EJava-9/)\n- [Spring Boot 2.0 新特性（一）：配置绑定 2.0 全解析](http://blog.didispace.com/Spring-Boot-2-0-feature-1-relaxed-binding-2/)\n- [Spring Boot 2.0 新特性（二）：新增事件ApplicationStartedEvent](http://blog.didispace.com/Spring-Boot-2-0-feature-2-ApplicationStartedEvent/)\n\n更多关于2.x的版本信息可查看[点击查看](http://www.springcloud.com.cn/)\n\n## 我的公众号\n\n<img src=\"https://blog.didispace.com/css/images/weixin.jpg\" style=\"width:150px;height:150px;\" />\n\n## 推荐我的书\n\n![Spring Boot微服务实战](https://git.oschina.net/uploads/images/2017/0416/233656_dd3bce94_437188.png)\n\n## 特别赞助商\n\n<table>\n      <tbody>\n        <tr>\n          <td align=\"center\" valign=\"middle\">\n             <a href=\"https://start.aliyun.com/\" target=\"_blank\">\n               <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/001.jpg?raw=true\">\n             </a>\n          </td>\n          <td align=\"center\" valign=\"middle\">\n            <a href=\"http://gk.link/a/103EK\" target=\"_blank\">\n              <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/002.jpg?raw=true\">\n            </a>\n          </td>  \n          <td align=\"center\" valign=\"middle\">\n             <a href=\"https://openwrite.cn/?from=didi-springcloud\" target=\"_blank\">\n               <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/003.jpg?raw=true\">\n             </a>\n          </td>          \n        </tr>\n        <tr>\n          <td align=\"center\" valign=\"middle\">\n            <a href=\"https://www.aliyun.com/minisite/goods?userCode=wxfqkr0o&share_source=copy_link\" target=\"_blank\">\n              <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/004.jpg?raw=true\">\n            </a>\n          </td>  \n          <td align=\"center\" valign=\"middle\">\n            <a href=\"https://curl.qcloud.com/M5wV9Ylj\" target=\"_blank\">\n              <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/005.jpg?raw=true\">\n            </a>\n          </td> \n          <td align=\"center\" valign=\"middle\">\n          </td>\n        </tr>\n      </tbody>\n</table>\n\n> 如果您也想赞助支持并出现在上表中的话，可以通过邮件联系我：`didi@didispace.com`"
  },
  {
    "path": "2.x/README_zh.md",
    "content": "# Spring Boot基础教程（2.x版本）\n\n本项目内容为[《Spring Boot基础教程》](http://blog.didispace.com/spring-boot-learning-2x/)的程序样例。\n\n**专题目标**：打造全网内容最全，比收费教程更好的Spring Boot免费教程！\n\n**加入社群**：如果你正在学习Spring Boot，不妨加入我们的[Spring技术交流群](https://blog.didispace.com/join-group-spring/index.html) ，一起成长\n\n**Spring社区**：如果您在学习过程中碰到问题，可以访问[SpringForAll社区](http://spring4all.com)，描述你的问题，我们会尽快给你答复。当然，如果你想分享你的学习经验，也可以在这里发表你的文章\n\n**如何支持**：\n\n1. 关注我的公众号”**程序猿DD**“\n2. 点个`Star`并`Follow`我\n3. 把该仓库分享给更多的朋友\n\n> **关注公众号：“程序猿DD”**，领取我整理的免费学习资料。<br>\n\n## 教程目录（2.x版本）\n\n本教程内容持续更新连载中！**Star关注**支持一下，随时获得更新信息！\n\n### 快速入门\n\n- [Spring Boot 2.x基础教程：版本关系](http://blog.didispace.com/spring-cloud-alibaba-version/)\n- [Spring Boot 2.x基础教程：快速入门](http://blog.didispace.com/spring-boot-learning-21-1-1/)\n- [Spring Boot 2.x基础教程：工程结构推荐](http://blog.didispace.com/spring-boot-learning-21-1-2/)\n\n### 配置详解\n\n- [Spring Boot 2.x基础教程：配置文件详解](http://blog.didispace.com/spring-boot-learning-21-1-3/)\n- [Spring Boot 2.x基础教程：2.4版本前后的多环境配置变化](http://blog.didispace.com/spring-boot-learning-24-1-4/)\n- [Spring Boot 2.x基础教程：2.4版本前后的分组配置变化](http://blog.didispace.com/spring-boot-learning-24-1-5/)\n- [Spring Boot 2.x基础教程：配置元数据的应用 ](http://blog.didispace.com/spring-boot-learning-24-1-6/)\n- [Spring Boot 2.x基础教程：加密配置中的敏感信息](http://blog.didispace.com/spring-boot-learning-2-1-5/)\n\n### API开发\n\n- [Spring Boot 2.x基础教程：构建RESTful API与单元测试](http://blog.didispace.com/spring-boot-learning-21-2-1/)\n- [Spring Boot 2.x基础教程：使用Swagger2构建强大的API文档](http://blog.didispace.com/spring-boot-learning-21-2-2/)\n- [Spring Boot 2.x基础教程：JSR-303实现请求参数校验](http://blog.didispace.com/spring-boot-learning-21-2-3/)\n- [Spring Boot 2.x基础教程：Swagger接口分类与各元素排序问题详解](http://blog.didispace.com/spring-boot-learning-21-2-4/)\n- [Spring Boot 2.x基础教程：Swagger静态文档的生成](http://blog.didispace.com/spring-boot-learning-21-2-5/)\n- [Spring Boot 2.x基础教程：找回启动日志中的请求路径列表](http://blog.didispace.com/spring-boot-learning-21-2-6/)\n- [Spring Boot 2.x基础教程：使用SpringFox 3生成Swagger文档](http://blog.didispace.com/spring-boot-learning-21-2-7/)\n- [Spring Boot 2.x基础教程：如何扩展XML格式的请求和响应](http://blog.didispace.com/spring-boot-learning-21-2-8/)\n\n### 数据访问\n\n**关系型数据库**\n\n- [Spring Boot 2.x基础教程：使用JdbcTemplate访问MySQL数据库](http://blog.didispace.com/spring-boot-learning-21-3-1/)\n- [Spring Boot 2.x基础教程：默认数据源Hikari的配置详解](http://blog.didispace.com/spring-boot-learning-21-3-2/)\n- [Spring Boot 2.x基础教程：使用国产数据库连接池Druid](http://blog.didispace.com/spring-boot-learning-21-3-3/)\n- [Spring Boot 2.x基础教程：使用Spring Data JPA访问MySQL](http://blog.didispace.com/spring-boot-learning-21-3-4/)\n- [Spring Boot 2.x基础教程：使用MyBatis访问MySQL](http://blog.didispace.com/spring-boot-learning-21-3-5/)\n- [Spring Boot 2.x基础教程：使用MyBatis的XML配置方式](http://blog.didispace.com/spring-boot-learning-21-3-6/)\n- [Spring Boot 2.x基础教程：JdbcTemplate的多数据源配置](http://blog.didispace.com/spring-boot-learning-21-3-7/)\n- [Spring Boot 2.x基础教程：Spring Data JPA的多数据源配置](http://blog.didispace.com/spring-boot-learning-21-3-8/)\n- [Spring Boot 2.x基础教程：MyBatis的多数据源配置](http://blog.didispace.com/spring-boot-learning-21-3-9/)\n- [Spring Boot 2.x基础教程：事务管理入门](http://blog.didispace.com/spring-boot-learning-21-3-10/)\n- [Spring Boot 2.x基础教程：使用Flyway管理数据库版本](http://blog.didispace.com/spring-boot-learning-24-3-11/)\n- [Spring Boot 2.x基础教程：使用JTA实现多数据源的事务管理](http://blog.didispace.com/spring-boot-learning-24-3-12/)\n- [Spring Boot 2.x基础教程：2.5版本后数据脚本初始化的变动](http://blog.didispace.com/spring-boot-learning-25-3-13/)\n\n**加速利器：各种缓存的使用**\n\n- [Spring Boot 2.x基础教程：进程内缓存的使用与Cache注解详解](http://blog.didispace.com/spring-boot-learning-21-5-1/)\n- [Spring Boot 2.x基础教程：EhCache缓存的使用](http://blog.didispace.com/spring-boot-learning-21-5-2/)\n- [Spring Boot 2.x基础教程：使用EhCache缓存集群](http://blog.didispace.com/spring-boot-learning-21-5-3/)\n- [Spring Boot 2.x基础教程：使用集中式缓存Redis](http://blog.didispace.com/spring-boot-learning-21-5-4/)\n- [Spring Boot 2.x基础教程：使用Redis的发布订阅功能](http://blog.didispace.com/spring-boot-learning-25-5-5/)\n\n**其他常见存储的使用**\n\n- [Spring Boot 2.x基础教程：使用MongoDB](http://blog.didispace.com/spring-boot-learning-24-6-1/)\n- [Spring Boot 2.x基础教程：使用LDAP来管理用户与组织数据](http://blog.didispace.com/spring-boot-learning-24-6-2/)\n- [Spring Boot 2.x基础教程：使用时序数据库InfluxDB](http://blog.didispace.com/spring-boot-learning-2-6-3/)\n- [Spring Boot 2.x基础教程：使用PostgreSQL](http://blog.didispace.com/spring-boot-learning-2-6-4/)\n\n### Web开发\n\n- [Spring Boot 2.x基础教程：使用 Thymeleaf开发Web页面](http://blog.didispace.com/spring-boot-learning-21-4-1/)\n- [Spring Boot 2.x基础教程：使用 ECharts 绘制各种华丽的数据图表](http://blog.didispace.com/spring-boot-learning-21-4-2/)\n- [Spring Boot 2.x基础教程：实现文件上传](http://blog.didispace.com/spring-boot-learning-21-4-3/)\n- [Spring Boot 2.x基础教程：多个文件的上传](http://blog.didispace.com/spring-boot-learning-21-4-4/)\n- [Spring Boot 2.x基础教程：文件上传的单元测试怎么写](http://blog.didispace.com/spring-boot-learning-21-4-5/)\n\n### 任务管理\n\n**定时任务**\n\n- [Spring Boot 2.x基础教程：使用@Scheduled实现定时任务](https://blog.didispace.com/spring-boot-learning-2-7-1)\n- [Spring Boot 2.x基础教程：使用Elastic Job实现定时任务](https://blog.didispace.com/spring-boot-learning-2-7-2)\n- [Spring Boot 2.x基础教程：使用Elastic Job的分片配置提高执行效率](https://blog.didispace.com/spring-boot-learning-2-7-3)\n- [Spring Boot 2.x基础教程：使用Elastic Job的namespace防止任务名冲突](https://blog.didispace.com/spring-boot-learning-2-7-4)\n\n**异步任务**\n\n- [Spring Boot 2.x基础教程：使用@Async实现异步任务](https://blog.didispace.com/spring-boot-learning-2-7-5)\n- [Spring Boot 2.x基础教程：配置@Async异步任务的线程池](https://blog.didispace.com/spring-boot-learning-2-7-6)\n- [Spring Boot 2.x基础教程：如何隔离@Async异步任务的线程池](https://blog.didispace.com/spring-boot-learning-2-7-7)\n- [Spring Boot 2.x基础教程：配置线程池的拒绝策略](https://blog.didispace.com/spring-boot-learning-2-7-8)\n\n### 日志管理\n\n- [Spring Boot 2.x基础教程：默认日志管理与Logback配置详解](https://blog.didispace.com/spring-boot-learning-2-8-1)\n- [Spring Boot 2.x基础教程：使用log4j2记录日志](https://blog.didispace.com/spring-boot-learning-2-8-2)\n- [Spring Boot 2.x基础教程：使用tinylog记录日志](https://blog.didispace.com/spring-boot-learning-2-8-3)\n\n### 其他内容\n\n- [Spring Boot自定义启动Banner](http://blog.didispace.com/spring-boot-banner/)\n- [实现邮件发送：简单邮件、附件邮件、嵌入资源的邮件、模板邮件](http://blog.didispace.com/springbootmailsender/)\n- [使用Spring StateMachine框架实现状态机](http://blog.didispace.com/spring-statemachine/)\n- [Spring Boot应用的后台运行配置](http://blog.didispace.com/spring-boot-run-backend/)\n\n\n## 进阶与深入\n\n- [什么时候不要使用@Autowire](http://blog.didispace.com/when-not-use-autowire-in-spring-boot/)\n- [为什么加了@Transactional注解，事务没有回滚？](http://blog.didispace.com/transactional-not-rollback/)\n- [为什么启动时候API路径都没了？](http://blog.didispace.com/spring-boot-learning-21-2-6/)\n- [使用Java 8中LocalDate等时间日期类的问题解决](http://blog.didispace.com/Spring-Boot-And-Feign-Use-localdate/)\n- [Request header is too large 如何解决？](https://blog.didispace.com/request-header-is-too-large/)\n- [Spring Boot自动化配置的利弊及解决之道](http://blog.didispace.com/spring-boot-disable-autoconfig/)\n\n## 版本资讯\n\n### 1.x到2.x\n\n- [Spring Boot 2.0 正式发布，升还是不升呢？](http://blog.didispace.com/spring-boot-2-release/)\n- [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/)\n- [Spring Boot 2.0 与 Java 9](http://blog.didispace.com/Spring-Boot-2.0%E4%B8%8EJava-9/)\n- [Spring Boot 2.0 新特性（一）：配置绑定 2.0 全解析](http://blog.didispace.com/Spring-Boot-2-0-feature-1-relaxed-binding-2/)\n- [Spring Boot 2.0 新特性（二）：新增事件ApplicationStartedEvent](http://blog.didispace.com/Spring-Boot-2-0-feature-2-ApplicationStartedEvent/)\n\n### 2.x版本信息\n\n- [Spring Boot 2.2 正式发布，大幅性能提升 + Java 13 支持](http://blog.didispace.com/spring-boot-2-2-release/)\n- [Spring Boot 2.3.0 发布](/spring-boot-2-3-0-release/) \n- [Spring Boot 2.3.0 放弃 Maven 转投 Gradle](/spring-boot-gradle/)\n- [Spring Boot 2.3.2 发布，解决 Too many open files 导致的应用宕机问题](http://blog.didispace.com/spring-boot-2-3-2-release/)\n- [Spring Boot 2.4.0 正式发布！全新的配置处理机制，拥抱云原生！](http://blog.didispace.com/spring-boot-2-4-0-ga/)\n- [Spring Boot 2.4.1 发布，修正大量2.4全新配置机制的Bug](http://blog.didispace.com/spring-boot-2-4-1-release/)\n- [Spring Boot 2.5.0 发布：支持Java16、Gradle 7、Datasource初始化调整](https://blog.didispace.com/spring-boot-2-5-0-release/)\n- [Spring Boot 2.5.1 发布](https://blog.didispace.com/spring-boot-2-5-1-release/)\n\n## 推荐内容\n\n- [我的博客](http://blog.didispace.com)：分享平时学习和实践过的技术内容\n- [知识星球](https://t.xiaomiquan.com/zfEiY3v)：聊聊技术人的斜杠生活\n- [Spring Boot基础教程](http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)：全网Star最多的免费Spring Boot基础教程\n- [Spring Cloud基础教程](http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)：全网最早最全的免费Spring Cloud基础教程\n\n## 我的公众号\n\n<img src=\"https://blog.didispace.com/css/images/weixin.jpg\" style=\"width:150px;height:150px;\" />\n\n## 推荐我的书\n\n![Spring Boot微服务实战](https://git.oschina.net/uploads/images/2017/0416/233656_dd3bce94_437188.png)\n\n## 特别赞助商\n\n<table>\n      <tbody>\n        <tr>\n          <td align=\"center\" valign=\"middle\">\n             <a href=\"https://start.aliyun.com/\" target=\"_blank\">\n               <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/001.jpg?raw=true\">\n             </a>\n          </td>\n          <td align=\"center\" valign=\"middle\">\n            <a href=\"http://gk.link/a/103EK\" target=\"_blank\">\n              <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/002.jpg?raw=true\">\n            </a>\n          </td>  \n          <td align=\"center\" valign=\"middle\">\n             <a href=\"https://openwrite.cn/?from=didi-springcloud\" target=\"_blank\">\n               <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/003.jpg?raw=true\">\n             </a>\n          </td>          \n        </tr>\n        <tr>\n          <td align=\"center\" valign=\"middle\">\n            <a href=\"https://www.aliyun.com/minisite/goods?userCode=wxfqkr0o&share_source=copy_link\" target=\"_blank\">\n              <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/004.jpg?raw=true\">\n            </a>\n          </td>  \n          <td align=\"center\" valign=\"middle\">\n            <a href=\"https://curl.qcloud.com/M5wV9Ylj\" target=\"_blank\">\n              <img width=\"300\" src=\"https://github.com/dyc87112/SpringBoot-Learning/blob/master/images/github/005.jpg?raw=true\">\n            </a>\n          </td> \n          <td align=\"center\" valign=\"middle\">\n          </td>\n        </tr>\n      </tbody>\n</table>\n\n> 如果您也想赞助支持并出现在上表中的话，可以通过邮件联系我：`didi@didispace.com`"
  },
  {
    "path": "2.x/chapter1-1/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter1-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter1-1</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter1-1</name>\n\t<description>快速入门</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter1-1/src/main/java/com/didispace/chapter11/Chapter11Application.java",
    "content": "package com.didispace.chapter11;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter11Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter11Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter1-1/src/main/java/com/didispace/chapter11/HelloController.java",
    "content": "package com.didispace.chapter11;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class HelloController {\n\n    @RequestMapping(\"/hello\")\n    public String index() {\n        return \"Hello World\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter1-1/src/main/resources/application.properties",
    "content": "\n"
  },
  {
    "path": "2.x/chapter1-1/src/test/java/com/didispace/chapter11/Chapter11ApplicationTests.java",
    "content": "package com.didispace.chapter11;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@SpringBootTest\npublic class Chapter11ApplicationTests {\n\n    private MockMvc mvc;\n\n    @Before\n    public void setUp() {\n        mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();\n    }\n\n    @Test\n    public void getHello() throws Exception {\n        mvc.perform(MockMvcRequestBuilders.get(\"/hello\").accept(MediaType.APPLICATION_JSON))\n                .andExpect(status().isOk())\n                .andExpect(content().string(equalTo(\"Hello World\")));\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter1-2/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter1-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter1-2</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter1-2</name>\n\t<description>2.4版本前后的多环境配置与配置激活</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter1-2/src/main/java/com/didispace/chapter12/Chapter12Application.java",
    "content": "package com.didispace.chapter12;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@SpringBootApplication\npublic class Chapter12Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter12Application.class, args);\n    }\n\n    @RestController\n    static class HelloController {\n\n        @Value(\"${name:}\")\n        private String name;\n\n        @RequestMapping(\"/\")\n        public String index() {\n            return name;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter1-2/src/main/resources/application.yaml",
    "content": "# 默认激活dev配置\nspring:\n  profiles:\n    active: \"dev\"\n\n---\n\nspring:\n  config:\n    activate:\n      on-profile: \"dev\"\n\nname: dev.didispace.com\n\n---\n\nspring:\n  config:\n    activate:\n      on-profile: \"test\"\n\nname: test.didispace.com\n\n---\n\nspring:\n  config:\n    activate:\n      on-profile: \"prod\"\n\nname: prod.didispace.com"
  },
  {
    "path": "2.x/chapter1-3/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter1-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter1-3</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter1-3</name>\n\t<description>2.4版本前后的配置分组配置</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter1-3/src/main/java/com/didispace/chapter13/Chapter13Application.java",
    "content": "package com.didispace.chapter13;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n\n@SpringBootApplication\npublic class Chapter13Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter13Application.class, args);\n    }\n\n    @Slf4j\n    @RestController\n    static class HelloController {\n\n        @Value(\"${db:}\")\n        private String db;\n\n        @Value(\"${mq:}\")\n        private String mq;\n\n        @RequestMapping(\"/\")\n        public String index() {\n            log.info(\"db：\" + db);\n            log.info(\"mq：\" + mq);\n            return \"\";\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter1-3/src/main/resources/application.yaml",
    "content": "# 2.4之前的配置\n#spring:\n#  profiles:\n#    active: \"dev\"\n#\n#---\n#spring.profiles: \"dev\"\n#spring.profiles.include: \"dev-db,dev-mq\"\n#\n#---\n#spring.profiles: \"dev-db\"\n#\n#db: dev-db.didispace.com\n#\n#---\n#spring.profiles: \"dev-mq\"\n#\n#mq: dev-mq.didispace.com\n#\n#---\n\n#2.4之后的配置\n# 默认激活dev配置\nspring:\n  profiles:\n    active: \"dev\"\n    group:\n      \"dev\": \"dev-db,dev-mq\"\n      \"prod\": \"prod-db,prod-mq\"\n\n---\nspring:\n  config:\n    activate:\n      on-profile: \"dev-db\"\n\ndb: dev-db.didispace.com\n\n---\nspring:\n  config:\n    activate:\n      on-profile: \"dev-mq\"\n\nmq: dev-mq.didispace.com\n\n---\nspring:\n  config:\n    activate:\n      on-profile: \"prod-db\"\n\ndb: prod-db.didispace.com\n\n---\nspring:\n  config:\n    activate:\n      on-profile: \"prod-mq\"\n\nmq: prod-mq.didispace.com\n"
  },
  {
    "path": "2.x/chapter1-4/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter1-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter1-4</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter1-4</name>\n\t<description>配置元数据的应用</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-configuration-processor</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter1-4/src/main/java/com/didispace/chapter14/Chapter14Application.java",
    "content": "package com.didispace.chapter14;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter14Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter14Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter1-4/src/main/java/com/didispace/chapter14/DidiProperties.java",
    "content": "package com.didispace.chapter14;\n\nimport lombok.Data;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.context.annotation.Configuration;\n\n@Data\n@Configuration\n@ConfigurationProperties(prefix = \"com.didispace\")\npublic class DidiProperties {\n\n    /**\n     * 这是一个测试配置\n     */\n    private String from;\n\n}\n"
  },
  {
    "path": "2.x/chapter1-4/src/main/java/com/didispace/chapter14/HelloController.java",
    "content": "package com.didispace.chapter14;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class HelloController {\n\n    @RequestMapping(\"/hello\")\n    public String index() {\n        return \"Hello World\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter1-4/src/main/resources/application.properties",
    "content": "\ncom.didispace.from=didi\n\n"
  },
  {
    "path": "2.x/chapter1-5/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter1-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter1-5</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>加密配置中的敏感信息</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.github.ulisesbocchio</groupId>\n            <artifactId>jasypt-spring-boot-starter</artifactId>\n            <version>3.0.3</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n\n            <plugin>\n                <groupId>com.github.ulisesbocchio</groupId>\n                <artifactId>jasypt-maven-plugin</artifactId>\n                <version>3.0.3</version>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter1-5/src/main/java/com/didispace/chapter15/Chapter15Application.java",
    "content": "package com.didispace.chapter15;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter15Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter15Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter1-5/src/main/resources/application.properties",
    "content": "\ndatasource.password=ENC(/AL9nJENCYCh9Pfzdf2xLPsqOZ6HwNgQ3AnMybFAMeOM5GphZlOK6PxzozwtCm+Q)\n\njasypt.encryptor.password=didispace\n\n# mvn jasypt:encrypt -Djasypt.encryptor.password=didispace\n# mvn jasypt:decrypt -Djasypt.encryptor.password=didispace\n\n#jasypt.encryptor.property.prefix=ENC(\n#jasypt.encryptor.property.suffix=)"
  },
  {
    "path": "2.x/chapter1-5/src/test/java/com/didispace/chapter15/PropertiesTest.java",
    "content": "package com.didispace.chapter15;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@Slf4j\n@SpringBootTest\npublic class PropertiesTest {\n\n    @Value(\"${datasource.password:}\")\n    private String password;\n\n    @Test\n    public void test() {\n        log.info(\"datasource.password : {}\", password);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-1/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter2-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-1</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter2-1</name>\n\t<description>构建RESTful API与单元测试</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter2-1/src/main/java/com/didispace/chapter21/Chapter21Application.java",
    "content": "package com.didispace.chapter21;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter21Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter21Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter2-1/src/main/java/com/didispace/chapter21/User.java",
    "content": "package com.didispace.chapter21;\n\nimport lombok.Data;\n\n@Data\npublic class User {\n\n    private Long id;\n    private String name;\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter2-1/src/main/java/com/didispace/chapter21/UserController.java",
    "content": "package com.didispace.chapter21;\n\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.*;\n\n@RestController\n@RequestMapping(value = \"/users\")     // 通过这里配置使下面的映射都在/users下\npublic class UserController {\n\n    // 创建线程安全的Map，模拟users信息的存储\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());\n\n    /**\n     * 处理\"/users/\"的GET请求，用来获取用户列表\n     *\n     * @return\n     */\n    @GetMapping(\"/\")\n    public List<User> getUserList() {\n        // 还可以通过@RequestParam从页面中传递参数来进行查询条件或者翻页信息的传递\n        List<User> r = new ArrayList<User>(users.values());\n        return r;\n    }\n\n    /**\n     * 处理\"/users/\"的POST请求，用来创建User\n     *\n     * @param user\n     * @return\n     */\n    @PostMapping(\"/\")\n    public String postUser(@RequestBody User user) {\n        // @RequestBody注解用来绑定通过http请求中application/json类型上传的数据\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    /**\n     * 处理\"/users/{id}\"的GET请求，用来获取url中id值的User信息\n     *\n     * @param id\n     * @return\n     */\n    @GetMapping(\"/{id}\")\n    public User getUser(@PathVariable Long id) {\n        // url中的id可通过@PathVariable绑定到函数的参数中\n        return users.get(id);\n    }\n\n    /**\n     * 处理\"/users/{id}\"的PUT请求，用来更新User信息\n     *\n     * @param id\n     * @param user\n     * @return\n     */\n    @PutMapping(\"/{id}\")\n    public String putUser(@PathVariable Long id, @RequestBody User user) {\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    /**\n     * 处理\"/users/{id}\"的DELETE请求，用来删除User\n     *\n     * @param id\n     * @return\n     */\n    @DeleteMapping(\"/{id}\")\n    public String deleteUser(@PathVariable Long id) {\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-1/src/main/resources/application.properties",
    "content": "\n"
  },
  {
    "path": "2.x/chapter2-1/src/test/java/com/didispace/chapter21/Chapter21ApplicationTests.java",
    "content": "package com.didispace.chapter21;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.RequestBuilder;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter21ApplicationTests {\n\n    private MockMvc mvc;\n\n    @Before\n    public void setUp() {\n        mvc = MockMvcBuilders.standaloneSetup(new UserController()).build();\n    }\n\n    @Test\n    public void testUserController() throws Exception {\n        // 测试UserController\n        RequestBuilder request;\n\n        // 1、get查一下user列表，应该为空\n        request = get(\"/users/\");\n        mvc.perform(request)\n                .andExpect(status().isOk())\n                .andExpect(content().string(equalTo(\"[]\")));\n\n        // 2、post提交一个user\n        request = post(\"/users/\")\n                .contentType(MediaType.APPLICATION_JSON)\n                .content(\"{\\\"id\\\":1,\\\"name\\\":\\\"测试大师\\\",\\\"age\\\":20}\");\n        mvc.perform(request)\n                .andExpect(content().string(equalTo(\"success\")));\n\n        // 3、get获取user列表，应该有刚才插入的数据\n        request = get(\"/users/\");\n        mvc.perform(request)\n                .andExpect(status().isOk())\n                .andExpect(content().string(equalTo(\"[{\\\"id\\\":1,\\\"name\\\":\\\"测试大师\\\",\\\"age\\\":20}]\")));\n\n        // 4、put修改id为1的user\n        request = put(\"/users/1\")\n                .contentType(MediaType.APPLICATION_JSON)\n                .content(\"{\\\"name\\\":\\\"测试终极大师\\\",\\\"age\\\":30}\");\n        mvc.perform(request)\n                .andExpect(content().string(equalTo(\"success\")));\n\n        // 5、get一个id为1的user\n        request = get(\"/users/1\");\n        mvc.perform(request)\n                .andExpect(content().string(equalTo(\"{\\\"id\\\":1,\\\"name\\\":\\\"测试终极大师\\\",\\\"age\\\":30}\")));\n\n        // 6、del删除id为1的user\n        request = delete(\"/users/1\");\n        mvc.perform(request)\n                .andExpect(content().string(equalTo(\"success\")));\n\n        // 7、get查一下user列表，应该为空\n        request = get(\"/users/\");\n        mvc.perform(request)\n                .andExpect(status().isOk())\n                .andExpect(content().string(equalTo(\"[]\")));\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-2/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter2-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-2</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter2-2</name>\n\t<description>使用Swagger2构建强大的API文档</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.spring4all</groupId>\n\t\t\t<artifactId>swagger-spring-boot-starter</artifactId>\n\t\t\t<version>1.9.0.RELEASE</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter2-2/src/main/java/com/didispace/chapter22/Chapter22Application.java",
    "content": "package com.didispace.chapter22;\n\nimport com.spring4all.swagger.EnableSwagger2Doc;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@EnableSwagger2Doc\n@SpringBootApplication\npublic class Chapter22Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter22Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-2/src/main/java/com/didispace/chapter22/User.java",
    "content": "package com.didispace.chapter22;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n@Data\n@ApiModel(description=\"用户实体\")\npublic class User {\n\n    @ApiModelProperty(\"用户编号\")\n    private Long id;\n    @ApiModelProperty(\"用户姓名\")\n    private String name;\n    @ApiModelProperty(\"用户年龄\")\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter2-2/src/main/java/com/didispace/chapter22/UserController.java",
    "content": "package com.didispace.chapter22;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.*;\n\n@Api(tags = \"用户管理\")\n@RestController\n@RequestMapping(value = \"/users\")     // 通过这里配置使下面的映射都在/users下\npublic class UserController {\n\n    // 创建线程安全的Map，模拟users信息的存储\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());\n\n    @GetMapping(\"/\")\n    @ApiOperation(value = \"获取用户列表\")\n    public List<User> getUserList() {\n        List<User> r = new ArrayList<>(users.values());\n        return r;\n    }\n\n    @PostMapping(\"/\")\n    @ApiOperation(value = \"创建用户\", notes = \"根据User对象创建用户\")\n    public String postUser(@RequestBody User user) {\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"获取用户详细信息\", notes = \"根据url的id来获取用户详细信息\")\n    public User getUser(@PathVariable Long id) {\n        return users.get(id);\n    }\n\n    @PutMapping(\"/{id}\")\n    @ApiImplicitParam(paramType = \"path\", dataType = \"Long\", name = \"id\", value = \"用户编号\", required = true, example = \"1\")\n    @ApiOperation(value = \"更新用户详细信息\", notes = \"根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\")\n    public String putUser(@PathVariable Long id, @RequestBody User user) {\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除用户\", notes = \"根据url的id来指定删除对象\")\n    public String deleteUser(@PathVariable Long id) {\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-2/src/main/resources/application.properties",
    "content": "\n\nswagger.title=spring-boot-starter-swagger\nswagger.description=Starter for swagger 2.x\nswagger.version=1.9.0.RELEASE\nswagger.license=Apache License, Version 2.0\nswagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.html\nswagger.termsOfServiceUrl=https://github.com/dyc87112/spring-boot-starter-swagger\nswagger.contact.name=didi\nswagger.contact.url=http://blog.didispace.com\nswagger.contact.email=dyc87112@qq.com\nswagger.base-package=com.didispace\nswagger.base-path=/**"
  },
  {
    "path": "2.x/chapter2-3/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter2-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-3</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter2-3</name>\n\t<description>使用JSR-303实现请求参数校验</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.spring4all</groupId>\n\t\t\t<artifactId>swagger-spring-boot-starter</artifactId>\n\t\t\t<version>1.9.0.RELEASE</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter2-3/src/main/java/com/didispace/chapter23/Chapter23Application.java",
    "content": "package com.didispace.chapter23;\n\nimport com.spring4all.swagger.EnableSwagger2Doc;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@EnableSwagger2Doc\n@SpringBootApplication\npublic class Chapter23Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter23Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-3/src/main/java/com/didispace/chapter23/User.java",
    "content": "package com.didispace.chapter23;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\nimport javax.validation.constraints.*;\n\n@Data\n@ApiModel(description = \"用户实体\")\npublic class User {\n\n    @ApiModelProperty(\"用户编号\")\n    private Long id;\n\n    @NotNull\n    @Size(min = 2, max = 5)\n    @ApiModelProperty(\"用户姓名\")\n    private String name;\n\n    @NotNull\n    @Max(100)\n    @Min(10)\n    @ApiModelProperty(\"用户年龄\")\n    private Integer age;\n\n    @NotNull\n    @Email\n    @ApiModelProperty(\"用户邮箱\")\n    private String email;\n\n}"
  },
  {
    "path": "2.x/chapter2-3/src/main/java/com/didispace/chapter23/UserController.java",
    "content": "package com.didispace.chapter23;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.validation.Valid;\nimport java.util.*;\n\n@Api(tags = \"用户管理\")\n@RestController\n@RequestMapping(value = \"/users\")     // 通过这里配置使下面的映射都在/users下\npublic class UserController {\n\n    // 创建线程安全的Map，模拟users信息的存储\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());\n\n    @GetMapping(\"/\")\n    @ApiOperation(value = \"获取用户列表\")\n    public List<User> getUserList() {\n        List<User> r = new ArrayList<>(users.values());\n        return r;\n    }\n\n    @PostMapping(\"/\")\n    @ApiOperation(value = \"创建用户\", notes = \"根据User对象创建用户\")\n    public String postUser(@Valid @RequestBody User user) {\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"获取用户详细信息\", notes = \"根据url的id来获取用户详细信息\")\n    public User getUser(@PathVariable Long id) {\n        return users.get(id);\n    }\n\n    @PutMapping(\"/{id}\")\n    @ApiImplicitParam(paramType = \"path\", dataType = \"Long\", name = \"id\", value = \"用户编号\", required = true, example = \"1\")\n    @ApiOperation(value = \"更新用户详细信息\", notes = \"根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\")\n    public String putUser(@PathVariable Long id, @RequestBody User user) {\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除用户\", notes = \"根据url的id来指定删除对象\")\n    public String deleteUser(@PathVariable Long id) {\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-3/src/main/resources/application.properties",
    "content": "\n\nswagger.title=spring-boot-starter-swagger\nswagger.description=Starter for swagger 2.x\nswagger.version=1.9.0.RELEASE\nswagger.license=Apache License, Version 2.0\nswagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.html\nswagger.termsOfServiceUrl=https://github.com/dyc87112/spring-boot-starter-swagger\nswagger.contact.name=didi\nswagger.contact.url=http://blog.didispace.com\nswagger.contact.email=dyc87112@qq.com\nswagger.base-package=com.didispace\nswagger.base-path=/**"
  },
  {
    "path": "2.x/chapter2-4/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter2-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-4</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter2-4</name>\n\t<description>Swagger接口分类与各元素排序问题详解</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.spring4all</groupId>\n\t\t\t<artifactId>swagger-spring-boot-starter</artifactId>\n\t\t\t<version>1.9.0.RELEASE</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter2-4/src/main/java/com/didispace/chapter24/Chapter24Application.java",
    "content": "package com.didispace.chapter24;\n\nimport com.spring4all.swagger.EnableSwagger2Doc;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport io.swagger.annotations.Tag;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.validation.Valid;\nimport java.util.ArrayList;\nimport java.util.List;\n\n@EnableSwagger2Doc\n@SpringBootApplication\npublic class Chapter24Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter24Application.class, args);\n    }\n\n    @Api(tags = {\"1-教师管理\",\"3-教学管理\"})\n    @RestController\n    @RequestMapping(value = \"/teacher\")\n    static class TeacherController {\n\n        @ApiOperation(value = \"xxx\")\n        @GetMapping(\"/xxx\")\n        public String xxx() {\n            return \"xxx\";\n        }\n\n    }\n\n    @Api(tags = {\"2-学生管理\"})\n    @RestController\n    @RequestMapping(value = \"/student\")\n    static class StudentController {\n\n        @ApiOperation(value = \"获取学生清单\", tags = \"3-教学管理\")\n        @GetMapping(\"/list\")\n        public String bbb() {\n            return \"bbb\";\n        }\n\n        @ApiOperation(\"获取教某个学生的老师清单\")\n        @GetMapping(\"/his-teachers\")\n        public String ccc() {\n            return \"ccc\";\n        }\n\n        @ApiOperation(\"创建一个学生\")\n        @PostMapping(\"/aaa\")\n        public String aaa() {\n            return \"aaa\";\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-4/src/main/java/com/didispace/chapter24/User.java",
    "content": "package com.didispace.chapter24;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\nimport javax.validation.constraints.*;\n\n@Data\n@ApiModel(description = \"用户实体\")\npublic class User {\n\n    @ApiModelProperty(value = \"用户编号\", position = 1)\n    private Long id;\n\n    @NotNull\n    @Size(min = 2, max = 5)\n    @ApiModelProperty(value = \"用户姓名\", position = 2)\n    private String name;\n\n    @NotNull\n    @Max(100)\n    @Min(10)\n    @ApiModelProperty(value = \"用户年龄\", position = 3)\n    private Integer age;\n\n    @NotNull\n    @Email\n    @ApiModelProperty(value = \"用户邮箱\", position = 4)\n    private String email;\n\n}"
  },
  {
    "path": "2.x/chapter2-4/src/main/java/com/didispace/chapter24/UserController.java",
    "content": "package com.didispace.chapter24;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.validation.Valid;\nimport java.util.*;\n\n@Api(tags = \"用户管理\")\n@RestController\n@RequestMapping(value = \"/users\")     // 通过这里配置使下面的映射都在/users下\npublic class UserController {\n\n    // 创建线程安全的Map，模拟users信息的存储\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());\n\n    @GetMapping(\"/\")\n    @ApiOperation(value = \"获取用户列表\")\n    public List<User> getUserList() {\n        List<User> r = new ArrayList<>(users.values());\n        return r;\n    }\n\n    @PostMapping(\"/\")\n    @ApiOperation(value = \"创建用户\", notes = \"根据User对象创建用户\")\n    public String postUser(@Valid @RequestBody User user) {\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"获取用户详细信息\", notes = \"根据url的id来获取用户详细信息\")\n    public User getUser(@PathVariable Long id) {\n        return users.get(id);\n    }\n\n    @PutMapping(\"/{id}\")\n    @ApiImplicitParam(paramType = \"path\", dataType = \"Long\", name = \"id\", value = \"用户编号\", required = true, example = \"1\")\n    @ApiOperation(value = \"更新用户详细信息\", notes = \"根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\")\n    public String putUser(@PathVariable Long id, @RequestBody User user) {\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除用户\", notes = \"根据url的id来指定删除对象\")\n    public String deleteUser(@PathVariable Long id) {\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-4/src/main/resources/application.properties",
    "content": "\n\nswagger.title=spring-boot-starter-swagger\nswagger.description=Starter for swagger 2.x\nswagger.version=1.9.0.RELEASE\nswagger.license=Apache License, Version 2.0\nswagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.html\nswagger.termsOfServiceUrl=https://github.com/dyc87112/spring-boot-starter-swagger\nswagger.contact.name=didi\nswagger.contact.url=http://blog.didispace.com\nswagger.contact.email=dyc87112@qq.com\nswagger.base-package=com.didispace\nswagger.base-path=/**\n\nswagger.ui-config.tags-sorter=alpha\nswagger.ui-config.operations-sorter=alpha"
  },
  {
    "path": "2.x/chapter2-5/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter2-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-5</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<name>chapter2-5</name>\n\t<description>Swagger静态文档的生成</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.spring4all</groupId>\n\t\t\t<artifactId>swagger-spring-boot-starter</artifactId>\n\t\t\t<version>1.9.0.RELEASE</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n        <dependency>\n            <groupId>io.github.swagger2markup</groupId>\n            <artifactId>swagger2markup</artifactId>\n            <version>1.3.3</version>\n\t\t\t<scope>test</scope>\n        </dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>io.github.swagger2markup</groupId>\n\t\t\t\t<artifactId>swagger2markup-maven-plugin</artifactId>\n\t\t\t\t<version>1.3.3</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<swaggerInput>http://localhost:8080/v2/api-docs</swaggerInput>\n\t\t\t\t\t<outputDir>src/docs/asciidoc/generated-by-plugin</outputDir>\n\t\t\t\t\t<config>\n\t\t\t\t\t\t<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>\n\t\t\t\t\t</config>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t<artifactId>asciidoctor-maven-plugin</artifactId>\n\t\t\t\t<version>1.5.6</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<sourceDirectory>src/docs/asciidoc/generated</sourceDirectory>\n\t\t\t\t\t<outputDirectory>src/docs/asciidoc/html</outputDirectory>\n\t\t\t\t\t<backend>html</backend>\n\t\t\t\t\t<sourceHighlighter>coderay</sourceHighlighter>\n\t\t\t\t\t<attributes>\n\t\t\t\t\t\t<toc>left</toc>\n\t\t\t\t\t</attributes>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<repositories>\n\t\t<repository>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>false</enabled>\n\t\t\t</snapshots>\n\t\t\t<id>jcenter-releases</id>\n\t\t\t<name>jcenter</name>\n\t\t\t<url>http://jcenter.bintray.com</url>\n\t\t</repository>\n\t</repositories>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated/definitions.adoc",
    "content": "\n[[_definitions]]\n== Definitions\n\n[[_user]]\n=== User\n用户实体\n\n\n[options=\"header\", cols=\".^3a,.^11a,.^4a\"]\n|===\n|Name|Description|Schema\n|**age** +\n__optional__|用户年龄|integer (int32)\n|**id** +\n__optional__|用户编号|integer (int64)\n|**name** +\n__optional__|用户姓名|string\n|===\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated/overview.adoc",
    "content": "= spring-boot-starter-swagger\n\n\n[[_overview]]\n== Overview\nStarter for swagger 2.x\n\n\n=== Version information\n[%hardbreaks]\n__Version__ : 1.9.0.RELEASE\n\n\n=== Contact information\n[%hardbreaks]\n__Contact__ : didi\n__Contact Email__ : dyc87112@qq.com\n\n\n=== License information\n[%hardbreaks]\n__License__ : Apache License, Version 2.0\n__License URL__ : https://www.apache.org/licenses/LICENSE-2.0.html\n__Terms of service__ : https://github.com/dyc87112/spring-boot-starter-swagger\n\n\n=== URI scheme\n[%hardbreaks]\n__Host__ : localhost:8080\n__BasePath__ : /\n\n\n=== Tags\n\n* 用户管理 : User Controller\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated/paths.adoc",
    "content": "\n[[_paths]]\n== Paths\n\n[[_postuserusingpost]]\n=== 创建用户\n....\nPOST /users/\n....\n\n\n==== Description\n根据User对象创建用户\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2a,.^3a,.^9a,.^4a\"]\n|===\n|Type|Name|Description|Schema\n|**Body**|**user** +\n__required__|user|<<_user,User>>\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2a,.^14a,.^4a\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|string\n|**201**|Created|No Content\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Consumes\n\n* `application/json`\n\n\n==== Produces\n\n* `\\*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3a,.^4a,.^13a\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_getuserlistusingget]]\n=== 获取用户列表\n....\nGET /users/\n....\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2a,.^14a,.^4a\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|< <<_user,User>> > array\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Produces\n\n* `\\*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3a,.^4a,.^13a\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_getuserusingget]]\n=== 获取用户详细信息\n....\nGET /users/{id}\n....\n\n\n==== Description\n根据url的id来获取用户详细信息\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2a,.^3a,.^9a,.^4a\"]\n|===\n|Type|Name|Description|Schema\n|**Path**|**id** +\n__required__|id|integer (int64)\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2a,.^14a,.^4a\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|<<_user,User>>\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Produces\n\n* `\\*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3a,.^4a,.^13a\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_putuserusingput]]\n=== 更新用户详细信息\n....\nPUT /users/{id}\n....\n\n\n==== Description\n根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2a,.^3a,.^9a,.^4a\"]\n|===\n|Type|Name|Description|Schema\n|**Path**|**id** +\n__required__|用户编号|integer (int64)\n|**Body**|**user** +\n__required__|user|<<_user,User>>\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2a,.^14a,.^4a\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|string\n|**201**|Created|No Content\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Consumes\n\n* `application/json`\n\n\n==== Produces\n\n* `\\*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3a,.^4a,.^13a\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_deleteuserusingdelete]]\n=== 删除用户\n....\nDELETE /users/{id}\n....\n\n\n==== Description\n根据url的id来指定删除对象\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2a,.^3a,.^9a,.^4a\"]\n|===\n|Type|Name|Description|Schema\n|**Path**|**id** +\n__required__|id|integer (int64)\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2a,.^14a,.^4a\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|string\n|**204**|No Content|No Content\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|===\n\n\n==== Produces\n\n* `\\*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3a,.^4a,.^13a\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated/security.adoc",
    "content": "\n[[_securityscheme]]\n== Security\n\n[[_authorization]]\n=== Authorization\n[%hardbreaks]\n__Type__ : apiKey\n__Name__ : TOKEN\n__In__ : HEADER\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated-by-plugin/definitions.adoc",
    "content": "\n[[_definitions]]\n== Definitions\n\n[[_user]]\n=== User\n用户实体\n\n\n[options=\"header\", cols=\".^3,.^11,.^4\"]\n|===\n|Name|Description|Schema\n|**age** +\n__optional__|用户年龄|integer (int32)\n|**id** +\n__optional__|用户编号|integer (int64)\n|**name** +\n__optional__|用户姓名|string\n|===\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated-by-plugin/overview.adoc",
    "content": "= spring-boot-starter-swagger\n\n\n[[_overview]]\n== Overview\nStarter for swagger 2.x\n\n\n=== Version information\n[%hardbreaks]\n__Version__ : 1.9.0.RELEASE\n\n\n=== Contact information\n[%hardbreaks]\n__Contact__ : didi\n__Contact Email__ : dyc87112@qq.com\n\n\n=== License information\n[%hardbreaks]\n__License__ : Apache License, Version 2.0\n__License URL__ : https://www.apache.org/licenses/LICENSE-2.0.html\n__Terms of service__ : https://github.com/dyc87112/spring-boot-starter-swagger\n\n\n=== URI scheme\n[%hardbreaks]\n__Host__ : localhost:8080\n__BasePath__ : /\n\n\n=== Tags\n\n* 用户管理 : User Controller\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated-by-plugin/paths.adoc",
    "content": "\n[[_paths]]\n== Paths\n\n[[_postuserusingpost]]\n=== 创建用户\n....\nPOST /users/\n....\n\n\n==== Description\n根据User对象创建用户\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2,.^3,.^9,.^4\"]\n|===\n|Type|Name|Description|Schema\n|**Body**|**user** +\n__required__|user|<<_user,User>>\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2,.^14,.^4\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|string\n|**201**|Created|No Content\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Consumes\n\n* `application/json`\n\n\n==== Produces\n\n* `*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3,.^4,.^13\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_getuserlistusingget]]\n=== 获取用户列表\n....\nGET /users/\n....\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2,.^14,.^4\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|< <<_user,User>> > array\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Produces\n\n* `*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3,.^4,.^13\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_getuserusingget]]\n=== 获取用户详细信息\n....\nGET /users/{id}\n....\n\n\n==== Description\n根据url的id来获取用户详细信息\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2,.^3,.^9,.^4\"]\n|===\n|Type|Name|Description|Schema\n|**Path**|**id** +\n__required__|id|integer (int64)\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2,.^14,.^4\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|<<_user,User>>\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Produces\n\n* `*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3,.^4,.^13\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_putuserusingput]]\n=== 更新用户详细信息\n....\nPUT /users/{id}\n....\n\n\n==== Description\n根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2,.^3,.^9,.^4\"]\n|===\n|Type|Name|Description|Schema\n|**Path**|**id** +\n__required__|用户编号|integer (int64)\n|**Body**|**user** +\n__required__|user|<<_user,User>>\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2,.^14,.^4\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|string\n|**201**|Created|No Content\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|**404**|Not Found|No Content\n|===\n\n\n==== Consumes\n\n* `application/json`\n\n\n==== Produces\n\n* `*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3,.^4,.^13\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n[[_deleteuserusingdelete]]\n=== 删除用户\n....\nDELETE /users/{id}\n....\n\n\n==== Description\n根据url的id来指定删除对象\n\n\n==== Parameters\n\n[options=\"header\", cols=\".^2,.^3,.^9,.^4\"]\n|===\n|Type|Name|Description|Schema\n|**Path**|**id** +\n__required__|id|integer (int64)\n|===\n\n\n==== Responses\n\n[options=\"header\", cols=\".^2,.^14,.^4\"]\n|===\n|HTTP Code|Description|Schema\n|**200**|OK|string\n|**204**|No Content|No Content\n|**401**|Unauthorized|No Content\n|**403**|Forbidden|No Content\n|===\n\n\n==== Produces\n\n* `*/*`\n\n\n==== Tags\n\n* 用户管理\n\n\n==== Security\n\n[options=\"header\", cols=\".^3,.^4,.^13\"]\n|===\n|Type|Name|Scopes\n|**apiKey**|**<<_authorization,Authorization>>**|global\n|===\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/generated-by-plugin/security.adoc",
    "content": "\n[[_securityscheme]]\n== Security\n\n[[_authorization]]\n=== Authorization\n[%hardbreaks]\n__Type__ : apiKey\n__Name__ : TOKEN\n__In__ : HEADER\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/html/definitions.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<!--[if IE]><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><![endif]-->\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 1.5.6.1\">\n<title>Definitions</title>\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\">\n<style>\n/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */\n/* Remove comment around @import statement below when using as a custom stylesheet */\n/*@import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\";*/\narticle,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}\naudio,canvas,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\n[hidden],template{display:none}\nscript{display:none!important}\nhtml{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}\na{background:transparent}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nabbr[title]{border-bottom:1px dotted}\nb,strong{font-weight:bold}\ndfn{font-style:italic}\nhr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=\"checkbox\"],input[type=\"radio\"]{box-sizing:border-box;padding:0}\ninput[type=\"search\"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}\ninput[type=\"search\"]::-webkit-search-cancel-button,input[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.center{margin-left:auto;margin-right:auto}\n.spread{width:100%}\np.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:none}\np{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}\nul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}\nul.square{list-style-type:square}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nabbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}\nabbr{text-transform:none}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}\nblockquote cite:before{content:\"\\2014 \\0020\"}\nblockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}\ntable thead,table tfoot{background:#f7f8f7;font-weight:bold}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:\" \";display:table}\n.clearfix:after,.float-group:after{clear:both}\n*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}\n*:not(pre)>code.nobreak{word-wrap:normal}\n*:not(pre)>code.nowrap{white-space:nowrap}\npre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;text-rendering:optimizeSpeed}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button:before,b.button:after{position:relative;top:-1px;font-weight:400}\nb.button:before{content:\"[\";padding:0 3px 0 2px}\nb.button:after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:\" \";display:table}\n#header:after,#content:after,#footnotes:after,#footer:after{clear:both}\n#content{margin-top:1.25em}\n#content:before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}\n#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}\n#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span:before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author:before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark:before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber:after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media only screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\n#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}\n@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:rgba(255,255,255,.8);line-height:1.44}\n.sect1{padding-bottom:.625em}\n@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}\n.sect1+.sect1{border-top:1px solid #efefed}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\n.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}\n.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}\ntable.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:initial}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}\n.exampleblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child{margin-bottom:0}\n.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n.sidebarblock>:first-child{margin-top:0}\n.sidebarblock>:last-child{margin-bottom:0}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class=\"highlight\"],.listingblock pre[class^=\"highlight \"],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}\n.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class=\"highlight\"],.sidebarblock .listingblock pre[class^=\"highlight \"],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}\n.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}\n.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}\n@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}\n@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}\n.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.listingblock>.content{position:relative}\n.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}\n.listingblock:hover code[data-lang]:before{display:block}\n.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}\n.listingblock.terminal pre .command:not([data-prompt]):before{content:\"$\"}\ntable.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}\ntable.pyhltable td.code{padding-left:.75em;padding-right:0}\npre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}\npre.pygments .lineno{display:inline-block;margin-right:.25em}\ntable.pyhltable .linenodiv{background:none!important;padding-right:0!important}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote:before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}\n.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}\n.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}\n.quoteblock .quoteblock blockquote:before{display:none}\n.verseblock{margin:0 1em 1.25em 1em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract{margin:0 0 1.25em 0;display:block}\n.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}\n.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}\ntable.tableblock{max-width:100%;border-collapse:separate}\ntable.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}\ntable.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}\ntable.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}\ntable.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0}\ntable.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0}\ntable.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}\ntable.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}\ntable.frame-all{border-width:1px}\ntable.frame-sides{border-width:0 1px}\ntable.frame-topbot{border-width:1px 0}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\ntd>div.verse{white-space:pre}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nul.checklist{margin-left:.625em}\nul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist li>p:first-child>input[type=\"checkbox\"]:first-child{margin-right:.25em}\nul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}\nul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}\nul.inline>li>*{display:block}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top}\n.colist>table tr>td:first-of-type img{max-width:initial}\n.colist>table tr>td:last-of-type{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}\n.imageblock.left,.imageblock[style*=\"float: left\"]{margin:.25em .625em 1.25em 0}\n.imageblock.right,.imageblock[style*=\"float: right\"]{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\n.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}\n.gist .file-data>table td.line-data{width:99%}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background-color:#00fafa}\n.black{color:#000}\n.black-background{background-color:#000}\n.blue{color:#0000bf}\n.blue-background{background-color:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background-color:#fa00fa}\n.gray{color:#606060}\n.gray-background{background-color:#7d7d7d}\n.green{color:#006000}\n.green-background{background-color:#007d00}\n.lime{color:#00bf00}\n.lime-background{background-color:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background-color:#7d0000}\n.navy{color:#000060}\n.navy-background{background-color:#00007d}\n.olive{color:#606000}\n.olive-background{background-color:#7d7d00}\n.purple{color:#600060}\n.purple-background{background-color:#7d007d}\n.red{color:#bf0000}\n.red-background{background-color:#fa0000}\n.silver{color:#909090}\n.silver-background{background-color:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background-color:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background-color:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background-color:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note:before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip:before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning:before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution:before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important:before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]:after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,span.alt{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@media print{@page{margin:1.25cm .75cm}\n*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare):after,a[href^=\"https:\"]:not(.bare):after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]:after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}\n.sect1{padding-bottom:0!important}\n.sect1+.sect1{border:0!important}\n#header>h1:first-child{margin-top:1.25rem}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span:before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]:before{display:block}\n#footer{background:none!important;padding:0 .9375em}\n#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n</style>\n<style>\n/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */\n/*pre.CodeRay {background-color:#f7f7f8;}*/\n.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}\n.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}\n.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}\ntable.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}\ntable.CodeRay td{vertical-align: top;line-height:1.45}\ntable.CodeRay td.line-numbers{text-align:right}\ntable.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}\ntable.CodeRay td.code{padding:0 0 0 .5em}\ntable.CodeRay td.code>pre{padding:0}\n.CodeRay .debug{color:#fff !important;background:#000080 !important}\n.CodeRay .annotation{color:#007}\n.CodeRay .attribute-name{color:#000080}\n.CodeRay .attribute-value{color:#700}\n.CodeRay .binary{color:#509}\n.CodeRay .comment{color:#998;font-style:italic}\n.CodeRay .char{color:#04d}\n.CodeRay .char .content{color:#04d}\n.CodeRay .char .delimiter{color:#039}\n.CodeRay .class{color:#458;font-weight:bold}\n.CodeRay .complex{color:#a08}\n.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}\n.CodeRay .color{color:#099}\n.CodeRay .class-variable{color:#369}\n.CodeRay .decorator{color:#b0b}\n.CodeRay .definition{color:#099}\n.CodeRay .delimiter{color:#000}\n.CodeRay .doc{color:#970}\n.CodeRay .doctype{color:#34b}\n.CodeRay .doc-string{color:#d42}\n.CodeRay .escape{color:#666}\n.CodeRay .entity{color:#800}\n.CodeRay .error{color:#808}\n.CodeRay .exception{color:inherit}\n.CodeRay .filename{color:#099}\n.CodeRay .function{color:#900;font-weight:bold}\n.CodeRay .global-variable{color:#008080}\n.CodeRay .hex{color:#058}\n.CodeRay .integer,.CodeRay .float{color:#099}\n.CodeRay .include{color:#555}\n.CodeRay .inline{color:#000}\n.CodeRay .inline .inline{background:#ccc}\n.CodeRay .inline .inline .inline{background:#bbb}\n.CodeRay .inline .inline-delimiter{color:#d14}\n.CodeRay .inline-delimiter{color:#d14}\n.CodeRay .important{color:#555;font-weight:bold}\n.CodeRay .interpreted{color:#b2b}\n.CodeRay .instance-variable{color:#008080}\n.CodeRay .label{color:#970}\n.CodeRay .local-variable{color:#963}\n.CodeRay .octal{color:#40e}\n.CodeRay .predefined{color:#369}\n.CodeRay .preprocessor{color:#579}\n.CodeRay .pseudo-class{color:#555}\n.CodeRay .directive{font-weight:bold}\n.CodeRay .type{font-weight:bold}\n.CodeRay .predefined-type{color:inherit}\n.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}\n.CodeRay .key{color:#808}\n.CodeRay .key .delimiter{color:#606}\n.CodeRay .key .char{color:#80f}\n.CodeRay .value{color:#088}\n.CodeRay .regexp .delimiter{color:#808}\n.CodeRay .regexp .content{color:#808}\n.CodeRay .regexp .modifier{color:#808}\n.CodeRay .regexp .char{color:#d14}\n.CodeRay .regexp .function{color:#404;font-weight:bold}\n.CodeRay .string{color:#d20}\n.CodeRay .string .string .string{background:#ffd0d0}\n.CodeRay .string .content{color:#d14}\n.CodeRay .string .char{color:#d14}\n.CodeRay .string .delimiter{color:#d14}\n.CodeRay .shell{color:#d14}\n.CodeRay .shell .delimiter{color:#d14}\n.CodeRay .symbol{color:#990073}\n.CodeRay .symbol .content{color:#a60}\n.CodeRay .symbol .delimiter{color:#630}\n.CodeRay .tag{color:#008080}\n.CodeRay .tag-special{color:#d70}\n.CodeRay .variable{color:#036}\n.CodeRay .insert{background:#afa}\n.CodeRay .delete{background:#faa}\n.CodeRay .change{color:#aaf;background:#007}\n.CodeRay .head{color:#f8f;background:#505}\n.CodeRay .insert .insert{color:#080}\n.CodeRay .delete .delete{color:#800}\n.CodeRay .change .change{color:#66f}\n.CodeRay .head .head{color:#f4f}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_definitions\">Definitions</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_user\">User</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_definitions\">Definitions</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_user\">User</h3>\n<div class=\"paragraph\">\n<p>用户实体</p>\n</div>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 16.6666%;\">\n<col style=\"width: 61.1111%;\">\n<col style=\"width: 22.2223%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>age</strong><br>\n<em>optional</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>用户年龄</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>integer (int32)</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>id</strong><br>\n<em>optional</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>用户编号</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>integer (int64)</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>name</strong><br>\n<em>optional</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>用户姓名</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>string</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2019-10-15 10:39:03 CST\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/html/overview.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<!--[if IE]><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><![endif]-->\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 1.5.6.1\">\n<title>spring-boot-starter-swagger</title>\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\">\n<style>\n/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */\n/* Remove comment around @import statement below when using as a custom stylesheet */\n/*@import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\";*/\narticle,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}\naudio,canvas,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\n[hidden],template{display:none}\nscript{display:none!important}\nhtml{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}\na{background:transparent}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nabbr[title]{border-bottom:1px dotted}\nb,strong{font-weight:bold}\ndfn{font-style:italic}\nhr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=\"checkbox\"],input[type=\"radio\"]{box-sizing:border-box;padding:0}\ninput[type=\"search\"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}\ninput[type=\"search\"]::-webkit-search-cancel-button,input[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.center{margin-left:auto;margin-right:auto}\n.spread{width:100%}\np.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:none}\np{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}\nul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}\nul.square{list-style-type:square}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nabbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}\nabbr{text-transform:none}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}\nblockquote cite:before{content:\"\\2014 \\0020\"}\nblockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}\ntable thead,table tfoot{background:#f7f8f7;font-weight:bold}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:\" \";display:table}\n.clearfix:after,.float-group:after{clear:both}\n*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}\n*:not(pre)>code.nobreak{word-wrap:normal}\n*:not(pre)>code.nowrap{white-space:nowrap}\npre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;text-rendering:optimizeSpeed}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button:before,b.button:after{position:relative;top:-1px;font-weight:400}\nb.button:before{content:\"[\";padding:0 3px 0 2px}\nb.button:after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:\" \";display:table}\n#header:after,#content:after,#footnotes:after,#footer:after{clear:both}\n#content{margin-top:1.25em}\n#content:before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}\n#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}\n#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span:before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author:before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark:before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber:after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media only screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\n#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}\n@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:rgba(255,255,255,.8);line-height:1.44}\n.sect1{padding-bottom:.625em}\n@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}\n.sect1+.sect1{border-top:1px solid #efefed}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\n.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}\n.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}\ntable.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:initial}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}\n.exampleblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child{margin-bottom:0}\n.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n.sidebarblock>:first-child{margin-top:0}\n.sidebarblock>:last-child{margin-bottom:0}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class=\"highlight\"],.listingblock pre[class^=\"highlight \"],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}\n.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class=\"highlight\"],.sidebarblock .listingblock pre[class^=\"highlight \"],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}\n.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}\n.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}\n@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}\n@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}\n.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.listingblock>.content{position:relative}\n.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}\n.listingblock:hover code[data-lang]:before{display:block}\n.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}\n.listingblock.terminal pre .command:not([data-prompt]):before{content:\"$\"}\ntable.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}\ntable.pyhltable td.code{padding-left:.75em;padding-right:0}\npre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}\npre.pygments .lineno{display:inline-block;margin-right:.25em}\ntable.pyhltable .linenodiv{background:none!important;padding-right:0!important}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote:before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}\n.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}\n.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}\n.quoteblock .quoteblock blockquote:before{display:none}\n.verseblock{margin:0 1em 1.25em 1em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract{margin:0 0 1.25em 0;display:block}\n.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}\n.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}\ntable.tableblock{max-width:100%;border-collapse:separate}\ntable.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}\ntable.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}\ntable.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}\ntable.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0}\ntable.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0}\ntable.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}\ntable.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}\ntable.frame-all{border-width:1px}\ntable.frame-sides{border-width:0 1px}\ntable.frame-topbot{border-width:1px 0}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\ntd>div.verse{white-space:pre}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nul.checklist{margin-left:.625em}\nul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist li>p:first-child>input[type=\"checkbox\"]:first-child{margin-right:.25em}\nul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}\nul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}\nul.inline>li>*{display:block}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top}\n.colist>table tr>td:first-of-type img{max-width:initial}\n.colist>table tr>td:last-of-type{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}\n.imageblock.left,.imageblock[style*=\"float: left\"]{margin:.25em .625em 1.25em 0}\n.imageblock.right,.imageblock[style*=\"float: right\"]{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\n.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}\n.gist .file-data>table td.line-data{width:99%}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background-color:#00fafa}\n.black{color:#000}\n.black-background{background-color:#000}\n.blue{color:#0000bf}\n.blue-background{background-color:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background-color:#fa00fa}\n.gray{color:#606060}\n.gray-background{background-color:#7d7d7d}\n.green{color:#006000}\n.green-background{background-color:#007d00}\n.lime{color:#00bf00}\n.lime-background{background-color:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background-color:#7d0000}\n.navy{color:#000060}\n.navy-background{background-color:#00007d}\n.olive{color:#606000}\n.olive-background{background-color:#7d7d00}\n.purple{color:#600060}\n.purple-background{background-color:#7d007d}\n.red{color:#bf0000}\n.red-background{background-color:#fa0000}\n.silver{color:#909090}\n.silver-background{background-color:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background-color:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background-color:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background-color:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note:before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip:before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning:before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution:before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important:before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]:after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,span.alt{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@media print{@page{margin:1.25cm .75cm}\n*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare):after,a[href^=\"https:\"]:not(.bare):after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]:after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}\n.sect1{padding-bottom:0!important}\n.sect1+.sect1{border:0!important}\n#header>h1:first-child{margin-top:1.25rem}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span:before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]:before{display:block}\n#footer{background:none!important;padding:0 .9375em}\n#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n</style>\n<style>\n/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */\n/*pre.CodeRay {background-color:#f7f7f8;}*/\n.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}\n.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}\n.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}\ntable.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}\ntable.CodeRay td{vertical-align: top;line-height:1.45}\ntable.CodeRay td.line-numbers{text-align:right}\ntable.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}\ntable.CodeRay td.code{padding:0 0 0 .5em}\ntable.CodeRay td.code>pre{padding:0}\n.CodeRay .debug{color:#fff !important;background:#000080 !important}\n.CodeRay .annotation{color:#007}\n.CodeRay .attribute-name{color:#000080}\n.CodeRay .attribute-value{color:#700}\n.CodeRay .binary{color:#509}\n.CodeRay .comment{color:#998;font-style:italic}\n.CodeRay .char{color:#04d}\n.CodeRay .char .content{color:#04d}\n.CodeRay .char .delimiter{color:#039}\n.CodeRay .class{color:#458;font-weight:bold}\n.CodeRay .complex{color:#a08}\n.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}\n.CodeRay .color{color:#099}\n.CodeRay .class-variable{color:#369}\n.CodeRay .decorator{color:#b0b}\n.CodeRay .definition{color:#099}\n.CodeRay .delimiter{color:#000}\n.CodeRay .doc{color:#970}\n.CodeRay .doctype{color:#34b}\n.CodeRay .doc-string{color:#d42}\n.CodeRay .escape{color:#666}\n.CodeRay .entity{color:#800}\n.CodeRay .error{color:#808}\n.CodeRay .exception{color:inherit}\n.CodeRay .filename{color:#099}\n.CodeRay .function{color:#900;font-weight:bold}\n.CodeRay .global-variable{color:#008080}\n.CodeRay .hex{color:#058}\n.CodeRay .integer,.CodeRay .float{color:#099}\n.CodeRay .include{color:#555}\n.CodeRay .inline{color:#000}\n.CodeRay .inline .inline{background:#ccc}\n.CodeRay .inline .inline .inline{background:#bbb}\n.CodeRay .inline .inline-delimiter{color:#d14}\n.CodeRay .inline-delimiter{color:#d14}\n.CodeRay .important{color:#555;font-weight:bold}\n.CodeRay .interpreted{color:#b2b}\n.CodeRay .instance-variable{color:#008080}\n.CodeRay .label{color:#970}\n.CodeRay .local-variable{color:#963}\n.CodeRay .octal{color:#40e}\n.CodeRay .predefined{color:#369}\n.CodeRay .preprocessor{color:#579}\n.CodeRay .pseudo-class{color:#555}\n.CodeRay .directive{font-weight:bold}\n.CodeRay .type{font-weight:bold}\n.CodeRay .predefined-type{color:inherit}\n.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}\n.CodeRay .key{color:#808}\n.CodeRay .key .delimiter{color:#606}\n.CodeRay .key .char{color:#80f}\n.CodeRay .value{color:#088}\n.CodeRay .regexp .delimiter{color:#808}\n.CodeRay .regexp .content{color:#808}\n.CodeRay .regexp .modifier{color:#808}\n.CodeRay .regexp .char{color:#d14}\n.CodeRay .regexp .function{color:#404;font-weight:bold}\n.CodeRay .string{color:#d20}\n.CodeRay .string .string .string{background:#ffd0d0}\n.CodeRay .string .content{color:#d14}\n.CodeRay .string .char{color:#d14}\n.CodeRay .string .delimiter{color:#d14}\n.CodeRay .shell{color:#d14}\n.CodeRay .shell .delimiter{color:#d14}\n.CodeRay .symbol{color:#990073}\n.CodeRay .symbol .content{color:#a60}\n.CodeRay .symbol .delimiter{color:#630}\n.CodeRay .tag{color:#008080}\n.CodeRay .tag-special{color:#d70}\n.CodeRay .variable{color:#036}\n.CodeRay .insert{background:#afa}\n.CodeRay .delete{background:#faa}\n.CodeRay .change{color:#aaf;background:#007}\n.CodeRay .head{color:#f8f;background:#505}\n.CodeRay .insert .insert{color:#080}\n.CodeRay .delete .delete{color:#800}\n.CodeRay .change .change{color:#66f}\n.CodeRay .head .head{color:#f4f}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>spring-boot-starter-swagger</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_overview\">Overview</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_version_information\">Version information</a></li>\n<li><a href=\"#_contact_information\">Contact information</a></li>\n<li><a href=\"#_license_information\">License information</a></li>\n<li><a href=\"#_uri_scheme\">URI scheme</a></li>\n<li><a href=\"#_tags\">Tags</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_overview\">Overview</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Starter for swagger 2.x</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_version_information\">Version information</h3>\n<div class=\"paragraph\">\n<p><em>Version</em> : 1.9.0.RELEASE</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_contact_information\">Contact information</h3>\n<div class=\"paragraph\">\n<p><em>Contact</em> : didi<br>\n<em>Contact Email</em> : <a href=\"mailto:dyc87112@qq.com\">dyc87112@qq.com</a></p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_license_information\">License information</h3>\n<div class=\"paragraph\">\n<p><em>License</em> : Apache License, Version 2.0<br>\n<em>License URL</em> : <a href=\"https://www.apache.org/licenses/LICENSE-2.0.html\" class=\"bare\">https://www.apache.org/licenses/LICENSE-2.0.html</a><br>\n<em>Terms of service</em> : <a href=\"https://github.com/dyc87112/spring-boot-starter-swagger\" class=\"bare\">https://github.com/dyc87112/spring-boot-starter-swagger</a></p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_uri_scheme\">URI scheme</h3>\n<div class=\"paragraph\">\n<p><em>Host</em> : localhost:8080<br>\n<em>BasePath</em> : /</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_tags\">Tags</h3>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>用户管理 : User Controller</p>\n</li>\n</ul>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2019-10-15 10:39:03 CST\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/html/paths.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<!--[if IE]><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><![endif]-->\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 1.5.6.1\">\n<title>Paths</title>\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\">\n<style>\n/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */\n/* Remove comment around @import statement below when using as a custom stylesheet */\n/*@import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\";*/\narticle,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}\naudio,canvas,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\n[hidden],template{display:none}\nscript{display:none!important}\nhtml{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}\na{background:transparent}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nabbr[title]{border-bottom:1px dotted}\nb,strong{font-weight:bold}\ndfn{font-style:italic}\nhr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=\"checkbox\"],input[type=\"radio\"]{box-sizing:border-box;padding:0}\ninput[type=\"search\"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}\ninput[type=\"search\"]::-webkit-search-cancel-button,input[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.center{margin-left:auto;margin-right:auto}\n.spread{width:100%}\np.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:none}\np{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}\nul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}\nul.square{list-style-type:square}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nabbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}\nabbr{text-transform:none}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}\nblockquote cite:before{content:\"\\2014 \\0020\"}\nblockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}\ntable thead,table tfoot{background:#f7f8f7;font-weight:bold}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:\" \";display:table}\n.clearfix:after,.float-group:after{clear:both}\n*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}\n*:not(pre)>code.nobreak{word-wrap:normal}\n*:not(pre)>code.nowrap{white-space:nowrap}\npre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;text-rendering:optimizeSpeed}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button:before,b.button:after{position:relative;top:-1px;font-weight:400}\nb.button:before{content:\"[\";padding:0 3px 0 2px}\nb.button:after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:\" \";display:table}\n#header:after,#content:after,#footnotes:after,#footer:after{clear:both}\n#content{margin-top:1.25em}\n#content:before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}\n#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}\n#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span:before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author:before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark:before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber:after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media only screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\n#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}\n@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:rgba(255,255,255,.8);line-height:1.44}\n.sect1{padding-bottom:.625em}\n@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}\n.sect1+.sect1{border-top:1px solid #efefed}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\n.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}\n.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}\ntable.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:initial}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}\n.exampleblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child{margin-bottom:0}\n.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n.sidebarblock>:first-child{margin-top:0}\n.sidebarblock>:last-child{margin-bottom:0}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class=\"highlight\"],.listingblock pre[class^=\"highlight \"],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}\n.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class=\"highlight\"],.sidebarblock .listingblock pre[class^=\"highlight \"],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}\n.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}\n.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}\n@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}\n@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}\n.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.listingblock>.content{position:relative}\n.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}\n.listingblock:hover code[data-lang]:before{display:block}\n.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}\n.listingblock.terminal pre .command:not([data-prompt]):before{content:\"$\"}\ntable.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}\ntable.pyhltable td.code{padding-left:.75em;padding-right:0}\npre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}\npre.pygments .lineno{display:inline-block;margin-right:.25em}\ntable.pyhltable .linenodiv{background:none!important;padding-right:0!important}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote:before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}\n.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}\n.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}\n.quoteblock .quoteblock blockquote:before{display:none}\n.verseblock{margin:0 1em 1.25em 1em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract{margin:0 0 1.25em 0;display:block}\n.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}\n.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}\ntable.tableblock{max-width:100%;border-collapse:separate}\ntable.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}\ntable.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}\ntable.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}\ntable.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0}\ntable.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0}\ntable.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}\ntable.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}\ntable.frame-all{border-width:1px}\ntable.frame-sides{border-width:0 1px}\ntable.frame-topbot{border-width:1px 0}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\ntd>div.verse{white-space:pre}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nul.checklist{margin-left:.625em}\nul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist li>p:first-child>input[type=\"checkbox\"]:first-child{margin-right:.25em}\nul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}\nul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}\nul.inline>li>*{display:block}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top}\n.colist>table tr>td:first-of-type img{max-width:initial}\n.colist>table tr>td:last-of-type{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}\n.imageblock.left,.imageblock[style*=\"float: left\"]{margin:.25em .625em 1.25em 0}\n.imageblock.right,.imageblock[style*=\"float: right\"]{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\n.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}\n.gist .file-data>table td.line-data{width:99%}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background-color:#00fafa}\n.black{color:#000}\n.black-background{background-color:#000}\n.blue{color:#0000bf}\n.blue-background{background-color:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background-color:#fa00fa}\n.gray{color:#606060}\n.gray-background{background-color:#7d7d7d}\n.green{color:#006000}\n.green-background{background-color:#007d00}\n.lime{color:#00bf00}\n.lime-background{background-color:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background-color:#7d0000}\n.navy{color:#000060}\n.navy-background{background-color:#00007d}\n.olive{color:#606000}\n.olive-background{background-color:#7d7d00}\n.purple{color:#600060}\n.purple-background{background-color:#7d007d}\n.red{color:#bf0000}\n.red-background{background-color:#fa0000}\n.silver{color:#909090}\n.silver-background{background-color:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background-color:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background-color:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background-color:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note:before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip:before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning:before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution:before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important:before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]:after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,span.alt{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@media print{@page{margin:1.25cm .75cm}\n*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare):after,a[href^=\"https:\"]:not(.bare):after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]:after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}\n.sect1{padding-bottom:0!important}\n.sect1+.sect1{border:0!important}\n#header>h1:first-child{margin-top:1.25rem}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span:before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]:before{display:block}\n#footer{background:none!important;padding:0 .9375em}\n#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n</style>\n<style>\n/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */\n/*pre.CodeRay {background-color:#f7f7f8;}*/\n.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}\n.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}\n.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}\ntable.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}\ntable.CodeRay td{vertical-align: top;line-height:1.45}\ntable.CodeRay td.line-numbers{text-align:right}\ntable.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}\ntable.CodeRay td.code{padding:0 0 0 .5em}\ntable.CodeRay td.code>pre{padding:0}\n.CodeRay .debug{color:#fff !important;background:#000080 !important}\n.CodeRay .annotation{color:#007}\n.CodeRay .attribute-name{color:#000080}\n.CodeRay .attribute-value{color:#700}\n.CodeRay .binary{color:#509}\n.CodeRay .comment{color:#998;font-style:italic}\n.CodeRay .char{color:#04d}\n.CodeRay .char .content{color:#04d}\n.CodeRay .char .delimiter{color:#039}\n.CodeRay .class{color:#458;font-weight:bold}\n.CodeRay .complex{color:#a08}\n.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}\n.CodeRay .color{color:#099}\n.CodeRay .class-variable{color:#369}\n.CodeRay .decorator{color:#b0b}\n.CodeRay .definition{color:#099}\n.CodeRay .delimiter{color:#000}\n.CodeRay .doc{color:#970}\n.CodeRay .doctype{color:#34b}\n.CodeRay .doc-string{color:#d42}\n.CodeRay .escape{color:#666}\n.CodeRay .entity{color:#800}\n.CodeRay .error{color:#808}\n.CodeRay .exception{color:inherit}\n.CodeRay .filename{color:#099}\n.CodeRay .function{color:#900;font-weight:bold}\n.CodeRay .global-variable{color:#008080}\n.CodeRay .hex{color:#058}\n.CodeRay .integer,.CodeRay .float{color:#099}\n.CodeRay .include{color:#555}\n.CodeRay .inline{color:#000}\n.CodeRay .inline .inline{background:#ccc}\n.CodeRay .inline .inline .inline{background:#bbb}\n.CodeRay .inline .inline-delimiter{color:#d14}\n.CodeRay .inline-delimiter{color:#d14}\n.CodeRay .important{color:#555;font-weight:bold}\n.CodeRay .interpreted{color:#b2b}\n.CodeRay .instance-variable{color:#008080}\n.CodeRay .label{color:#970}\n.CodeRay .local-variable{color:#963}\n.CodeRay .octal{color:#40e}\n.CodeRay .predefined{color:#369}\n.CodeRay .preprocessor{color:#579}\n.CodeRay .pseudo-class{color:#555}\n.CodeRay .directive{font-weight:bold}\n.CodeRay .type{font-weight:bold}\n.CodeRay .predefined-type{color:inherit}\n.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}\n.CodeRay .key{color:#808}\n.CodeRay .key .delimiter{color:#606}\n.CodeRay .key .char{color:#80f}\n.CodeRay .value{color:#088}\n.CodeRay .regexp .delimiter{color:#808}\n.CodeRay .regexp .content{color:#808}\n.CodeRay .regexp .modifier{color:#808}\n.CodeRay .regexp .char{color:#d14}\n.CodeRay .regexp .function{color:#404;font-weight:bold}\n.CodeRay .string{color:#d20}\n.CodeRay .string .string .string{background:#ffd0d0}\n.CodeRay .string .content{color:#d14}\n.CodeRay .string .char{color:#d14}\n.CodeRay .string .delimiter{color:#d14}\n.CodeRay .shell{color:#d14}\n.CodeRay .shell .delimiter{color:#d14}\n.CodeRay .symbol{color:#990073}\n.CodeRay .symbol .content{color:#a60}\n.CodeRay .symbol .delimiter{color:#630}\n.CodeRay .tag{color:#008080}\n.CodeRay .tag-special{color:#d70}\n.CodeRay .variable{color:#036}\n.CodeRay .insert{background:#afa}\n.CodeRay .delete{background:#faa}\n.CodeRay .change{color:#aaf;background:#007}\n.CodeRay .head{color:#f8f;background:#505}\n.CodeRay .insert .insert{color:#080}\n.CodeRay .delete .delete{color:#800}\n.CodeRay .change .change{color:#66f}\n.CodeRay .head .head{color:#f4f}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_paths\">Paths</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_postuserusingpost\">创建用户</a></li>\n<li><a href=\"#_getuserlistusingget\">获取用户列表</a></li>\n<li><a href=\"#_getuserusingget\">获取用户详细信息</a></li>\n<li><a href=\"#_putuserusingput\">更新用户详细信息</a></li>\n<li><a href=\"#_deleteuserusingdelete\">删除用户</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_paths\">Paths</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_postuserusingpost\">创建用户</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>POST /users/</pre>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_description\">Description</h4>\n<div class=\"paragraph\">\n<p>根据User对象创建用户</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_parameters\">Parameters</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 11.1111%;\">\n<col style=\"width: 16.6666%;\">\n<col style=\"width: 50%;\">\n<col style=\"width: 22.2223%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>Body</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>user</strong><br>\n<em>required</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>user</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><a href=\"#_user\">User</a></p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_responses\">Responses</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 10%;\">\n<col style=\"width: 70%;\">\n<col style=\"width: 20%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">HTTP Code</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>200</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>OK</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>string</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>201</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Created</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>401</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Unauthorized</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>403</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Forbidden</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>404</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Not Found</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_consumes\">Consumes</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>application/json</code></p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_produces\">Produces</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>*/*</code></p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_tags\">Tags</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>用户管理</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_security\">Security</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 15%;\">\n<col style=\"width: 20%;\">\n<col style=\"width: 65%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Scopes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>apiKey</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong><a href=\"#_authorization\">Authorization</a></strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>global</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_getuserlistusingget\">获取用户列表</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>GET /users/</pre>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_responses_2\">Responses</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 10%;\">\n<col style=\"width: 70%;\">\n<col style=\"width: 20%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">HTTP Code</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>200</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>OK</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>&lt; <a href=\"#_user\">User</a> &gt; array</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>401</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Unauthorized</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>403</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Forbidden</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>404</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Not Found</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_produces_2\">Produces</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>*/*</code></p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_tags_2\">Tags</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>用户管理</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_security_2\">Security</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 15%;\">\n<col style=\"width: 20%;\">\n<col style=\"width: 65%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Scopes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>apiKey</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong><a href=\"#_authorization\">Authorization</a></strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>global</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_getuserusingget\">获取用户详细信息</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>GET /users/{id}</pre>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_description_2\">Description</h4>\n<div class=\"paragraph\">\n<p>根据url的id来获取用户详细信息</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_parameters_2\">Parameters</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 11.1111%;\">\n<col style=\"width: 16.6666%;\">\n<col style=\"width: 50%;\">\n<col style=\"width: 22.2223%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>Path</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>id</strong><br>\n<em>required</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>id</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>integer (int64)</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_responses_3\">Responses</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 10%;\">\n<col style=\"width: 70%;\">\n<col style=\"width: 20%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">HTTP Code</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>200</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>OK</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><a href=\"#_user\">User</a></p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>401</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Unauthorized</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>403</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Forbidden</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>404</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Not Found</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_produces_3\">Produces</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>*/*</code></p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_tags_3\">Tags</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>用户管理</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_security_3\">Security</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 15%;\">\n<col style=\"width: 20%;\">\n<col style=\"width: 65%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Scopes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>apiKey</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong><a href=\"#_authorization\">Authorization</a></strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>global</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_putuserusingput\">更新用户详细信息</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>PUT /users/{id}</pre>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_description_3\">Description</h4>\n<div class=\"paragraph\">\n<p>根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_parameters_3\">Parameters</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 11.1111%;\">\n<col style=\"width: 16.6666%;\">\n<col style=\"width: 50%;\">\n<col style=\"width: 22.2223%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>Path</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>id</strong><br>\n<em>required</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>用户编号</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>integer (int64)</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>Body</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>user</strong><br>\n<em>required</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>user</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><a href=\"#_user\">User</a></p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_responses_4\">Responses</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 10%;\">\n<col style=\"width: 70%;\">\n<col style=\"width: 20%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">HTTP Code</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>200</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>OK</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>string</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>201</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Created</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>401</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Unauthorized</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>403</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Forbidden</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>404</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Not Found</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_consumes_2\">Consumes</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>application/json</code></p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_produces_4\">Produces</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>*/*</code></p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_tags_4\">Tags</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>用户管理</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_security_4\">Security</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 15%;\">\n<col style=\"width: 20%;\">\n<col style=\"width: 65%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Scopes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>apiKey</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong><a href=\"#_authorization\">Authorization</a></strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>global</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_deleteuserusingdelete\">删除用户</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>DELETE /users/{id}</pre>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_description_4\">Description</h4>\n<div class=\"paragraph\">\n<p>根据url的id来指定删除对象</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_parameters_4\">Parameters</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 11.1111%;\">\n<col style=\"width: 16.6666%;\">\n<col style=\"width: 50%;\">\n<col style=\"width: 22.2223%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>Path</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>id</strong><br>\n<em>required</em></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>id</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>integer (int64)</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_responses_5\">Responses</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 10%;\">\n<col style=\"width: 70%;\">\n<col style=\"width: 20%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">HTTP Code</th>\n<th class=\"tableblock halign-left valign-middle\">Description</th>\n<th class=\"tableblock halign-left valign-middle\">Schema</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>200</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>OK</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>string</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>204</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>401</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Unauthorized</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>403</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>Forbidden</p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>No Content</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_produces_5\">Produces</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>*/*</code></p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_tags_5\">Tags</h4>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>用户管理</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_security_5\">Security</h4>\n<table class=\"tableblock frame-all grid-all spread\">\n<colgroup>\n<col style=\"width: 15%;\">\n<col style=\"width: 20%;\">\n<col style=\"width: 65%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-middle\">Type</th>\n<th class=\"tableblock halign-left valign-middle\">Name</th>\n<th class=\"tableblock halign-left valign-middle\">Scopes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong>apiKey</strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p><strong><a href=\"#_authorization\">Authorization</a></strong></p>\n</div></div></td>\n<td class=\"tableblock halign-left valign-middle\"><div><div class=\"paragraph\">\n<p>global</p>\n</div></div></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2019-10-15 10:39:03 CST\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter2-5/src/docs/asciidoc/html/security.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<!--[if IE]><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><![endif]-->\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 1.5.6.1\">\n<title>Security</title>\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\">\n<style>\n/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */\n/* Remove comment around @import statement below when using as a custom stylesheet */\n/*@import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\";*/\narticle,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}\naudio,canvas,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\n[hidden],template{display:none}\nscript{display:none!important}\nhtml{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}\na{background:transparent}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nabbr[title]{border-bottom:1px dotted}\nb,strong{font-weight:bold}\ndfn{font-style:italic}\nhr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=\"checkbox\"],input[type=\"radio\"]{box-sizing:border-box;padding:0}\ninput[type=\"search\"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}\ninput[type=\"search\"]::-webkit-search-cancel-button,input[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.center{margin-left:auto;margin-right:auto}\n.spread{width:100%}\np.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:none}\np{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}\nul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}\nul.square{list-style-type:square}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nabbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}\nabbr{text-transform:none}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}\nblockquote cite:before{content:\"\\2014 \\0020\"}\nblockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}\ntable thead,table tfoot{background:#f7f8f7;font-weight:bold}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:\" \";display:table}\n.clearfix:after,.float-group:after{clear:both}\n*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}\n*:not(pre)>code.nobreak{word-wrap:normal}\n*:not(pre)>code.nowrap{white-space:nowrap}\npre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;text-rendering:optimizeSpeed}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button:before,b.button:after{position:relative;top:-1px;font-weight:400}\nb.button:before{content:\"[\";padding:0 3px 0 2px}\nb.button:after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:\" \";display:table}\n#header:after,#content:after,#footnotes:after,#footer:after{clear:both}\n#content{margin-top:1.25em}\n#content:before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}\n#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}\n#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span:before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author:before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark:before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber:after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media only screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\n#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}\n@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:rgba(255,255,255,.8);line-height:1.44}\n.sect1{padding-bottom:.625em}\n@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}\n.sect1+.sect1{border-top:1px solid #efefed}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\n.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}\n.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}\ntable.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:initial}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}\n.exampleblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child{margin-bottom:0}\n.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}\n.sidebarblock>:first-child{margin-top:0}\n.sidebarblock>:last-child{margin-bottom:0}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class=\"highlight\"],.listingblock pre[class^=\"highlight \"],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}\n.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class=\"highlight\"],.sidebarblock .listingblock pre[class^=\"highlight \"],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}\n.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}\n.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}\n@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}\n@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}\n.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.listingblock>.content{position:relative}\n.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}\n.listingblock:hover code[data-lang]:before{display:block}\n.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}\n.listingblock.terminal pre .command:not([data-prompt]):before{content:\"$\"}\ntable.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}\ntable.pyhltable td.code{padding-left:.75em;padding-right:0}\npre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}\npre.pygments .lineno{display:inline-block;margin-right:.25em}\ntable.pyhltable .linenodiv{background:none!important;padding-right:0!important}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote:before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}\n.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}\n.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}\n.quoteblock .quoteblock blockquote:before{display:none}\n.verseblock{margin:0 1em 1.25em 1em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract{margin:0 0 1.25em 0;display:block}\n.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}\n.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}\ntable.tableblock{max-width:100%;border-collapse:separate}\ntable.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}\ntable.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}\ntable.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}\ntable.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0}\ntable.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0}\ntable.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}\ntable.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}\ntable.frame-all{border-width:1px}\ntable.frame-sides{border-width:0 1px}\ntable.frame-topbot{border-width:1px 0}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\ntd>div.verse{white-space:pre}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nul.checklist{margin-left:.625em}\nul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist li>p:first-child>input[type=\"checkbox\"]:first-child{margin-right:.25em}\nul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}\nul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}\nul.inline>li>*{display:block}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top}\n.colist>table tr>td:first-of-type img{max-width:initial}\n.colist>table tr>td:last-of-type{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}\n.imageblock.left,.imageblock[style*=\"float: left\"]{margin:.25em .625em 1.25em 0}\n.imageblock.right,.imageblock[style*=\"float: right\"]{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\n.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}\n.gist .file-data>table td.line-data{width:99%}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background-color:#00fafa}\n.black{color:#000}\n.black-background{background-color:#000}\n.blue{color:#0000bf}\n.blue-background{background-color:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background-color:#fa00fa}\n.gray{color:#606060}\n.gray-background{background-color:#7d7d7d}\n.green{color:#006000}\n.green-background{background-color:#007d00}\n.lime{color:#00bf00}\n.lime-background{background-color:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background-color:#7d0000}\n.navy{color:#000060}\n.navy-background{background-color:#00007d}\n.olive{color:#606000}\n.olive-background{background-color:#7d7d00}\n.purple{color:#600060}\n.purple-background{background-color:#7d007d}\n.red{color:#bf0000}\n.red-background{background-color:#fa0000}\n.silver{color:#909090}\n.silver-background{background-color:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background-color:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background-color:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background-color:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note:before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip:before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning:before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution:before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important:before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]:after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,span.alt{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@media print{@page{margin:1.25cm .75cm}\n*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare):after,a[href^=\"https:\"]:not(.bare):after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]:after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}\n.sect1{padding-bottom:0!important}\n.sect1+.sect1{border:0!important}\n#header>h1:first-child{margin-top:1.25rem}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span:before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]:before{display:block}\n#footer{background:none!important;padding:0 .9375em}\n#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n</style>\n<style>\n/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */\n/*pre.CodeRay {background-color:#f7f7f8;}*/\n.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}\n.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}\n.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}\ntable.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}\ntable.CodeRay td{vertical-align: top;line-height:1.45}\ntable.CodeRay td.line-numbers{text-align:right}\ntable.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}\ntable.CodeRay td.code{padding:0 0 0 .5em}\ntable.CodeRay td.code>pre{padding:0}\n.CodeRay .debug{color:#fff !important;background:#000080 !important}\n.CodeRay .annotation{color:#007}\n.CodeRay .attribute-name{color:#000080}\n.CodeRay .attribute-value{color:#700}\n.CodeRay .binary{color:#509}\n.CodeRay .comment{color:#998;font-style:italic}\n.CodeRay .char{color:#04d}\n.CodeRay .char .content{color:#04d}\n.CodeRay .char .delimiter{color:#039}\n.CodeRay .class{color:#458;font-weight:bold}\n.CodeRay .complex{color:#a08}\n.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}\n.CodeRay .color{color:#099}\n.CodeRay .class-variable{color:#369}\n.CodeRay .decorator{color:#b0b}\n.CodeRay .definition{color:#099}\n.CodeRay .delimiter{color:#000}\n.CodeRay .doc{color:#970}\n.CodeRay .doctype{color:#34b}\n.CodeRay .doc-string{color:#d42}\n.CodeRay .escape{color:#666}\n.CodeRay .entity{color:#800}\n.CodeRay .error{color:#808}\n.CodeRay .exception{color:inherit}\n.CodeRay .filename{color:#099}\n.CodeRay .function{color:#900;font-weight:bold}\n.CodeRay .global-variable{color:#008080}\n.CodeRay .hex{color:#058}\n.CodeRay .integer,.CodeRay .float{color:#099}\n.CodeRay .include{color:#555}\n.CodeRay .inline{color:#000}\n.CodeRay .inline .inline{background:#ccc}\n.CodeRay .inline .inline .inline{background:#bbb}\n.CodeRay .inline .inline-delimiter{color:#d14}\n.CodeRay .inline-delimiter{color:#d14}\n.CodeRay .important{color:#555;font-weight:bold}\n.CodeRay .interpreted{color:#b2b}\n.CodeRay .instance-variable{color:#008080}\n.CodeRay .label{color:#970}\n.CodeRay .local-variable{color:#963}\n.CodeRay .octal{color:#40e}\n.CodeRay .predefined{color:#369}\n.CodeRay .preprocessor{color:#579}\n.CodeRay .pseudo-class{color:#555}\n.CodeRay .directive{font-weight:bold}\n.CodeRay .type{font-weight:bold}\n.CodeRay .predefined-type{color:inherit}\n.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}\n.CodeRay .key{color:#808}\n.CodeRay .key .delimiter{color:#606}\n.CodeRay .key .char{color:#80f}\n.CodeRay .value{color:#088}\n.CodeRay .regexp .delimiter{color:#808}\n.CodeRay .regexp .content{color:#808}\n.CodeRay .regexp .modifier{color:#808}\n.CodeRay .regexp .char{color:#d14}\n.CodeRay .regexp .function{color:#404;font-weight:bold}\n.CodeRay .string{color:#d20}\n.CodeRay .string .string .string{background:#ffd0d0}\n.CodeRay .string .content{color:#d14}\n.CodeRay .string .char{color:#d14}\n.CodeRay .string .delimiter{color:#d14}\n.CodeRay .shell{color:#d14}\n.CodeRay .shell .delimiter{color:#d14}\n.CodeRay .symbol{color:#990073}\n.CodeRay .symbol .content{color:#a60}\n.CodeRay .symbol .delimiter{color:#630}\n.CodeRay .tag{color:#008080}\n.CodeRay .tag-special{color:#d70}\n.CodeRay .variable{color:#036}\n.CodeRay .insert{background:#afa}\n.CodeRay .delete{background:#faa}\n.CodeRay .change{color:#aaf;background:#007}\n.CodeRay .head{color:#f8f;background:#505}\n.CodeRay .insert .insert{color:#080}\n.CodeRay .delete .delete{color:#800}\n.CodeRay .change .change{color:#66f}\n.CodeRay .head .head{color:#f4f}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_securityscheme\">Security</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_authorization\">Authorization</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_securityscheme\">Security</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_authorization\">Authorization</h3>\n<div class=\"paragraph\">\n<p><em>Type</em> : apiKey<br>\n<em>Name</em> : TOKEN<br>\n<em>In</em> : HEADER</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2019-10-15 10:39:03 CST\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter2-5/src/docs/confluence/generated/definitions.txt",
    "content": "\nh2. Definitions {anchor:definitions}\n\nh3. User {anchor:user}\n用户实体\n\n\n||Name||Description||Schema||\n|*age*\\\\ \\\\ _optional_||用户年龄||integer (int32)|\n|*id*\\\\ \\\\ _optional_||用户编号||integer (int64)|\n|*name*\\\\ \\\\ _optional_||用户姓名||string|\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/confluence/generated/overview.txt",
    "content": "h1. spring-boot-starter-swagger\n\n\nh2. Overview {anchor:overview}\nStarter for swagger 2.x\n\n\nh3. Version information\n_Version_ : 1.9.0.RELEASE\n\n\nh3. Contact information\n_Contact_ : didi\\\\ \n_Contact Email_ : dyc87112@qq.com\n\n\nh3. License information\n_License_ : Apache License, Version 2.0\\\\ \n_License URL_ : https://www.apache.org/licenses/LICENSE-2.0.html\\\\ \n_Terms of service_ : https://github.com/dyc87112/spring-boot-starter-swagger\n\n\nh3. URI scheme\n_Host_ : localhost:8080\\\\ \n_BasePath_ : /\n\n\nh3. Tags\n\n* 用户管理 : User Controller\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/confluence/generated/paths.txt",
    "content": "\nh2. Paths {anchor:paths}\n\nh3. 创建用户 {anchor:postuserusingpost}\n{noformat}\nPOST /users/\n{noformat}\n\n\nh4. Description\n根据User对象创建用户\n\n\nh4. Parameters\n\n||Type||Name||Description||Schema||\n|*Body*|*user*\\\\ \\\\ _required_||user||[User|#user]|\n\n\nh4. Responses\n\n||HTTP Code||Description||Schema||\n|*200*||OK||string|\n|*201*||Created||No Content|\n|*401*||Unauthorized||No Content|\n|*403*||Forbidden||No Content|\n|*404*||Not Found||No Content|\n\n\nh4. Consumes\n\n* {noformat}application/json{noformat}\n\n\nh4. Produces\n\n* {noformat}\\*/*{noformat}\n\n\nh4. Tags\n\n* 用户管理\n\n\nh4. Security\n\n||Type||Name||Scopes||\n|*apiKey*|*[Authorization|#authorization]*||global|\n\n\nh3. 获取用户列表 {anchor:getuserlistusingget}\n{noformat}\nGET /users/\n{noformat}\n\n\nh4. Responses\n\n||HTTP Code||Description||Schema||\n|*200*||OK||< [User|#user] > array|\n|*401*||Unauthorized||No Content|\n|*403*||Forbidden||No Content|\n|*404*||Not Found||No Content|\n\n\nh4. Produces\n\n* {noformat}\\*/*{noformat}\n\n\nh4. Tags\n\n* 用户管理\n\n\nh4. Security\n\n||Type||Name||Scopes||\n|*apiKey*|*[Authorization|#authorization]*||global|\n\n\nh3. 获取用户详细信息 {anchor:getuserusingget}\n{noformat}\nGET /users/{id}\n{noformat}\n\n\nh4. Description\n根据url的id来获取用户详细信息\n\n\nh4. Parameters\n\n||Type||Name||Description||Schema||\n|*Path*|*id*\\\\ \\\\ _required_||id||integer (int64)|\n\n\nh4. Responses\n\n||HTTP Code||Description||Schema||\n|*200*||OK||[User|#user]|\n|*401*||Unauthorized||No Content|\n|*403*||Forbidden||No Content|\n|*404*||Not Found||No Content|\n\n\nh4. Produces\n\n* {noformat}\\*/*{noformat}\n\n\nh4. Tags\n\n* 用户管理\n\n\nh4. Security\n\n||Type||Name||Scopes||\n|*apiKey*|*[Authorization|#authorization]*||global|\n\n\nh3. 更新用户详细信息 {anchor:putuserusingput}\n{noformat}\nPUT /users/{id}\n{noformat}\n\n\nh4. Description\n根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\n\n\nh4. Parameters\n\n||Type||Name||Description||Schema||\n|*Path*|*id*\\\\ \\\\ _required_||用户编号||integer (int64)|\n|*Body*|*user*\\\\ \\\\ _required_||user||[User|#user]|\n\n\nh4. Responses\n\n||HTTP Code||Description||Schema||\n|*200*||OK||string|\n|*201*||Created||No Content|\n|*401*||Unauthorized||No Content|\n|*403*||Forbidden||No Content|\n|*404*||Not Found||No Content|\n\n\nh4. Consumes\n\n* {noformat}application/json{noformat}\n\n\nh4. Produces\n\n* {noformat}\\*/*{noformat}\n\n\nh4. Tags\n\n* 用户管理\n\n\nh4. Security\n\n||Type||Name||Scopes||\n|*apiKey*|*[Authorization|#authorization]*||global|\n\n\nh3. 删除用户 {anchor:deleteuserusingdelete}\n{noformat}\nDELETE /users/{id}\n{noformat}\n\n\nh4. Description\n根据url的id来指定删除对象\n\n\nh4. Parameters\n\n||Type||Name||Description||Schema||\n|*Path*|*id*\\\\ \\\\ _required_||id||integer (int64)|\n\n\nh4. Responses\n\n||HTTP Code||Description||Schema||\n|*200*||OK||string|\n|*204*||No Content||No Content|\n|*401*||Unauthorized||No Content|\n|*403*||Forbidden||No Content|\n\n\nh4. Produces\n\n* {noformat}\\*/*{noformat}\n\n\nh4. Tags\n\n* 用户管理\n\n\nh4. Security\n\n||Type||Name||Scopes||\n|*apiKey*|*[Authorization|#authorization]*||global|\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/confluence/generated/security.txt",
    "content": "\nh2. Security {anchor:securityscheme}\n\nh3. Authorization {anchor:authorization}\n_Type_ : apiKey\\\\ \n_Name_ : TOKEN\\\\ \n_In_ : HEADER\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/markdown/generated/definitions.md",
    "content": "\n<a name=\"definitions\"></a>\n## Definitions\n\n<a name=\"user\"></a>\n### User\n用户实体\n\n\n|Name|Description|Schema|\n|---|---|---|\n|**age**  <br>*optional*|用户年龄|integer (int32)|\n|**id**  <br>*optional*|用户编号|integer (int64)|\n|**name**  <br>*optional*|用户姓名|string|\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/markdown/generated/overview.md",
    "content": "# spring-boot-starter-swagger\n\n\n<a name=\"overview\"></a>\n## Overview\nStarter for swagger 2.x\n\n\n### Version information\n*Version* : 1.9.0.RELEASE\n\n\n### Contact information\n*Contact* : didi  \n*Contact Email* : dyc87112@qq.com\n\n\n### License information\n*License* : Apache License, Version 2.0  \n*License URL* : https://www.apache.org/licenses/LICENSE-2.0.html  \n*Terms of service* : https://github.com/dyc87112/spring-boot-starter-swagger\n\n\n### URI scheme\n*Host* : localhost:8080  \n*BasePath* : /\n\n\n### Tags\n\n* 用户管理 : User Controller\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/markdown/generated/paths.md",
    "content": "\n<a name=\"paths\"></a>\n## Paths\n\n<a name=\"postuserusingpost\"></a>\n### 创建用户\n```\nPOST /users/\n```\n\n\n#### Description\n根据User对象创建用户\n\n\n#### Parameters\n\n|Type|Name|Description|Schema|\n|---|---|---|---|\n|**Body**|**user**  <br>*required*|user|[User](#user)|\n\n\n#### Responses\n\n|HTTP Code|Description|Schema|\n|---|---|---|\n|**200**|OK|string|\n|**201**|Created|No Content|\n|**401**|Unauthorized|No Content|\n|**403**|Forbidden|No Content|\n|**404**|Not Found|No Content|\n\n\n#### Consumes\n\n* `application/json`\n\n\n#### Produces\n\n* `\\*/*`\n\n\n#### Tags\n\n* 用户管理\n\n\n#### Security\n\n|Type|Name|Scopes|\n|---|---|---|\n|**apiKey**|**[Authorization](#authorization)**|global|\n\n\n<a name=\"getuserlistusingget\"></a>\n### 获取用户列表\n```\nGET /users/\n```\n\n\n#### Responses\n\n|HTTP Code|Description|Schema|\n|---|---|---|\n|**200**|OK|< [User](#user) > array|\n|**401**|Unauthorized|No Content|\n|**403**|Forbidden|No Content|\n|**404**|Not Found|No Content|\n\n\n#### Produces\n\n* `\\*/*`\n\n\n#### Tags\n\n* 用户管理\n\n\n#### Security\n\n|Type|Name|Scopes|\n|---|---|---|\n|**apiKey**|**[Authorization](#authorization)**|global|\n\n\n<a name=\"getuserusingget\"></a>\n### 获取用户详细信息\n```\nGET /users/{id}\n```\n\n\n#### Description\n根据url的id来获取用户详细信息\n\n\n#### Parameters\n\n|Type|Name|Description|Schema|\n|---|---|---|---|\n|**Path**|**id**  <br>*required*|id|integer (int64)|\n\n\n#### Responses\n\n|HTTP Code|Description|Schema|\n|---|---|---|\n|**200**|OK|[User](#user)|\n|**401**|Unauthorized|No Content|\n|**403**|Forbidden|No Content|\n|**404**|Not Found|No Content|\n\n\n#### Produces\n\n* `\\*/*`\n\n\n#### Tags\n\n* 用户管理\n\n\n#### Security\n\n|Type|Name|Scopes|\n|---|---|---|\n|**apiKey**|**[Authorization](#authorization)**|global|\n\n\n<a name=\"putuserusingput\"></a>\n### 更新用户详细信息\n```\nPUT /users/{id}\n```\n\n\n#### Description\n根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\n\n\n#### Parameters\n\n|Type|Name|Description|Schema|\n|---|---|---|---|\n|**Path**|**id**  <br>*required*|用户编号|integer (int64)|\n|**Body**|**user**  <br>*required*|user|[User](#user)|\n\n\n#### Responses\n\n|HTTP Code|Description|Schema|\n|---|---|---|\n|**200**|OK|string|\n|**201**|Created|No Content|\n|**401**|Unauthorized|No Content|\n|**403**|Forbidden|No Content|\n|**404**|Not Found|No Content|\n\n\n#### Consumes\n\n* `application/json`\n\n\n#### Produces\n\n* `\\*/*`\n\n\n#### Tags\n\n* 用户管理\n\n\n#### Security\n\n|Type|Name|Scopes|\n|---|---|---|\n|**apiKey**|**[Authorization](#authorization)**|global|\n\n\n<a name=\"deleteuserusingdelete\"></a>\n### 删除用户\n```\nDELETE /users/{id}\n```\n\n\n#### Description\n根据url的id来指定删除对象\n\n\n#### Parameters\n\n|Type|Name|Description|Schema|\n|---|---|---|---|\n|**Path**|**id**  <br>*required*|id|integer (int64)|\n\n\n#### Responses\n\n|HTTP Code|Description|Schema|\n|---|---|---|\n|**200**|OK|string|\n|**204**|No Content|No Content|\n|**401**|Unauthorized|No Content|\n|**403**|Forbidden|No Content|\n\n\n#### Produces\n\n* `\\*/*`\n\n\n#### Tags\n\n* 用户管理\n\n\n#### Security\n\n|Type|Name|Scopes|\n|---|---|---|\n|**apiKey**|**[Authorization](#authorization)**|global|\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/docs/markdown/generated/security.md",
    "content": "\n<a name=\"securityscheme\"></a>\n## Security\n\n<a name=\"authorization\"></a>\n### Authorization\n*Type* : apiKey  \n*Name* : TOKEN  \n*In* : HEADER\n\n\n\n"
  },
  {
    "path": "2.x/chapter2-5/src/main/java/com/didispace/chapter25/Chapter25Application.java",
    "content": "package com.didispace.chapter25;\n\nimport com.spring4all.swagger.EnableSwagger2Doc;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@EnableSwagger2Doc\n@SpringBootApplication\npublic class Chapter25Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter25Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-5/src/main/java/com/didispace/chapter25/User.java",
    "content": "package com.didispace.chapter25;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n@Data\n@ApiModel(description=\"用户实体\")\npublic class User {\n\n    @ApiModelProperty(\"用户编号\")\n    private Long id;\n    @ApiModelProperty(\"用户姓名\")\n    private String name;\n    @ApiModelProperty(\"用户年龄\")\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter2-5/src/main/java/com/didispace/chapter25/UserController.java",
    "content": "package com.didispace.chapter25;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.*;\n\n@Api(tags = \"用户管理\")\n@RestController\n@RequestMapping(value = \"/users\")     // 通过这里配置使下面的映射都在/users下\npublic class UserController {\n\n    // 创建线程安全的Map，模拟users信息的存储\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());\n\n    @GetMapping(\"/\")\n    @ApiOperation(value = \"获取用户列表\")\n    public List<User> getUserList() {\n        List<User> r = new ArrayList<>(users.values());\n        return r;\n    }\n\n    @PostMapping(\"/\")\n    @ApiOperation(value = \"创建用户\", notes = \"根据User对象创建用户\")\n    public String postUser(@RequestBody User user) {\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"获取用户详细信息\", notes = \"根据url的id来获取用户详细信息\")\n    public User getUser(@PathVariable Long id) {\n        return users.get(id);\n    }\n\n    @PutMapping(\"/{id}\")\n    @ApiImplicitParam(paramType = \"path\", dataType = \"Long\", name = \"id\", value = \"用户编号\", required = true, example = \"1\")\n    @ApiOperation(value = \"更新用户详细信息\", notes = \"根据url的id来指定更新对象，并根据传过来的user信息来更新用户详细信息\")\n    public String putUser(@PathVariable Long id, @RequestBody User user) {\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除用户\", notes = \"根据url的id来指定删除对象\")\n    public String deleteUser(@PathVariable Long id) {\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-5/src/main/resources/application.properties",
    "content": "\n\nswagger.title=spring-boot-starter-swagger\nswagger.description=Starter for swagger 2.x\nswagger.version=1.9.0.RELEASE\nswagger.license=Apache License, Version 2.0\nswagger.licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.html\nswagger.termsOfServiceUrl=https://github.com/dyc87112/spring-boot-starter-swagger\nswagger.contact.name=didi\nswagger.contact.url=http://blog.didispace.com\nswagger.contact.email=dyc87112@qq.com\nswagger.base-package=com.didispace\nswagger.base-path=/**"
  },
  {
    "path": "2.x/chapter2-5/src/test/java/com/didispace/chapter25/DemoApplicationTests.java",
    "content": "package com.didispace.chapter25;\n\nimport io.github.swagger2markup.Swagger2MarkupConfig;\nimport io.github.swagger2markup.Swagger2MarkupConverter;\nimport io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;\nimport io.github.swagger2markup.markup.builder.MarkupLanguage;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.net.URL;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)\npublic class DemoApplicationTests {\n\n    @Test\n    public void generateAsciiDocs() throws Exception {\n\n        URL remoteSwaggerFile = new URL(\"http://localhost:8080/v2/api-docs\");\n        Path outputDirectory = Paths.get(\"src/docs/asciidoc/generated\");\n\n        //    输出Ascii格式\n        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()\n                .withMarkupLanguage(MarkupLanguage.ASCIIDOC)\n                .build();\n\n        Swagger2MarkupConverter.from(remoteSwaggerFile)\n                .withConfig(config)\n                .build()\n                .toFolder(outputDirectory);\n    }\n\n    @Test\n    public void generateMarkdownDocs() throws Exception {\n\n        URL remoteSwaggerFile = new URL(\"http://localhost:8080/v2/api-docs\");\n        Path outputDirectory = Paths.get(\"src/docs/markdown/generated\");\n\n        //    输出Ascii格式\n        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()\n                .withMarkupLanguage(MarkupLanguage.MARKDOWN)\n                .build();\n\n        Swagger2MarkupConverter.from(remoteSwaggerFile)\n                .withConfig(config)\n                .build()\n                .toFolder(outputDirectory);\n    }\n\n    @Test\n    public void generateConfluenceDocs() throws Exception {\n\n        URL remoteSwaggerFile = new URL(\"http://localhost:8080/v2/api-docs\");\n        Path outputDirectory = Paths.get(\"src/docs/confluence/generated\");\n\n        //    输出Ascii格式\n        Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()\n                .withMarkupLanguage(MarkupLanguage.CONFLUENCE_MARKUP)\n                .build();\n\n        Swagger2MarkupConverter.from(remoteSwaggerFile)\n                .withConfig(config)\n                .build()\n                .toFolder(outputDirectory);\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-6/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter2-6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.1.3.RELEASE</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter2-6</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>找回启动日志中的请求路径列表</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter2-6/src/main/java/com/didispace/chapter26/Chapter26Application.java",
    "content": "package com.didispace.chapter26;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter26Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter26Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-6/src/main/java/com/didispace/chapter26/User.java",
    "content": "package com.didispace.chapter26;\n\nimport lombok.Data;\n\n@Data\npublic class User {\n\n    private Long id;\n    private String name;\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter2-6/src/main/java/com/didispace/chapter26/UserController.java",
    "content": "package com.didispace.chapter26;\n\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.*;\n\n@RestController\n@RequestMapping(value = \"/users\")     // 通过这里配置使下面的映射都在/users下\npublic class UserController {\n\n    // 创建线程安全的Map，模拟users信息的存储\n    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());\n\n    @GetMapping(\"/\")\n    public List<User> getUserList() {\n        List<User> r = new ArrayList<>(users.values());\n        return r;\n    }\n\n    @PostMapping(\"/\")\n    public String postUser(@RequestBody User user) {\n        users.put(user.getId(), user);\n        return \"success\";\n    }\n\n    @GetMapping(\"/{id}\")\n    public User getUser(@PathVariable Long id) {\n        return users.get(id);\n    }\n\n    @PutMapping(\"/{id}\")\n    public String putUser(@PathVariable Long id, @RequestBody User user) {\n        User u = users.get(id);\n        u.setName(user.getName());\n        u.setAge(user.getAge());\n        users.put(id, u);\n        return \"success\";\n    }\n\n    @DeleteMapping(\"/{id}\")\n    public String deleteUser(@PathVariable Long id) {\n        users.remove(id);\n        return \"success\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-6/src/main/resources/application.properties",
    "content": "# 打印RequestMapping中的所有接口信息\nlogging.level.org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping=trace\n\n"
  },
  {
    "path": "2.x/chapter2-7/.gitignore",
    "content": "target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\nnbproject/private/\nbuild/\nnbbuild/\ndist/\nnbdist/\n.nb-gradle/"
  },
  {
    "path": "2.x/chapter2-7/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.2.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-7</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用SpringFox3生成Swagger文档</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>io.springfox</groupId>\n\t\t\t<artifactId>springfox-boot-starter</artifactId>\n\t\t\t<version>3.0.0</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<repositories>\n\t\t<repository>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>false</enabled>\n\t\t\t</snapshots>\n\t\t\t<id>jcenter-releases</id>\n\t\t\t<name>jcenter</name>\n\t\t\t<url>http://jcenter.bintray.com</url>\n\t\t</repository>\n\t</repositories>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter2-7/src/main/java/com/didispace/chapter27/Chapter27Application.java",
    "content": "package com.didispace.chapter27;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport springfox.documentation.oas.annotations.EnableOpenApi;\n\n@EnableOpenApi\n@SpringBootApplication\npublic class Chapter27Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter27Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-7/src/main/java/com/didispace/chapter27/User.java",
    "content": "package com.didispace.demo;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.validation.constraints.*;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"用户基本信息\")\npublic class User {\n\n    @ApiModelProperty(\"姓名\")\n    @Size(max = 20)\n    private String name;\n    @ApiModelProperty(\"年龄\")\n    @Max(150)\n    @Min(1)\n    private Integer age;\n    @NotNull\n    private String address;\n    @Pattern(regexp = \"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\\\.[a-zA-Z0-9_-]+)+$\")\n    private String email;\n\n}"
  },
  {
    "path": "2.x/chapter2-7/src/main/java/com/didispace/chapter27/UserController.java",
    "content": "package com.didispace.demo;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport io.swagger.annotations.ApiParam;\nimport org.springframework.web.bind.annotation.*;\nimport springfox.documentation.annotations.ApiIgnore;\n\nimport javax.validation.Valid;\nimport java.util.ArrayList;\nimport java.util.List;\n\n@Api(tags=\"用户管理\")\n@RestController\npublic class UserController {\n\n    @ApiOperation(\"创建用户\")\n    @PostMapping(\"/users\")\n    public User create(@RequestBody @Valid User user) {\n        return user;\n    }\n\n    @ApiOperation(\"用户详情\")\n    @GetMapping(\"/users/{id}\")\n    public User findById(@PathVariable Long id) {\n        return new User(\"bbb\", 21, \"上海\", \"aaa@bbb.com\");\n    }\n\n    @ApiOperation(\"用户列表\")\n    @GetMapping(\"/users\")\n    public List<User> list(@ApiParam(\"查看第几页\") @RequestParam int pageIndex,\n                           @ApiParam(\"每页多少条\") @RequestParam int pageSize) {\n        List<User> result = new ArrayList<>();\n        result.add(new User(\"aaa\", 50, \"北京\", \"aaa@ccc.com\"));\n        result.add(new User(\"bbb\", 21, \"广州\", \"aaa@ddd.com\"));\n        return result;\n    }\n\n    @ApiIgnore\n    @DeleteMapping(\"/users/{id}\")\n    public String deleteById(@PathVariable Long id) {\n        return \"delete user : \" + id;\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-7/src/main/resources/application.properties",
    "content": "logging.level.org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping=trace\n\n"
  },
  {
    "path": "2.x/chapter2-8/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-8</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\t<description>如何扩展XML格式的请求和响应</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.5.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.dataformat</groupId>\n\t\t\t<artifactId>jackson-dataformat-xml</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "2.x/chapter2-8/src/main/java/com/didispace/chapter28/Chapter28Application.java",
    "content": "package com.didispace.chapter28;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@SpringBootApplication\npublic class Chapter28Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter28Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-8/src/main/java/com/didispace/chapter28/User.java",
    "content": "package com.didispace.chapter28;\n\n\nimport com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;\nimport com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@JacksonXmlRootElement(localName = \"User\")\npublic class User {\n\n    @JacksonXmlProperty(localName = \"name\")\n    private String name;\n    @JacksonXmlProperty(localName = \"age\")\n    private Integer age;\n\n}\n"
  },
  {
    "path": "2.x/chapter2-8/src/main/java/com/didispace/chapter28/UserController.java",
    "content": "package com.didispace.chapter28;\n\nimport org.springframework.http.MediaType;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@Controller\npublic class UserController {\n\n    @PostMapping(value = \"/user\",\n            consumes = MediaType.APPLICATION_XML_VALUE,\n            produces = MediaType.APPLICATION_XML_VALUE)\n    @ResponseBody\n    public User create(@RequestBody User user) {\n        user.setName(\"didispace.com : \" + user.getName());\n        user.setAge(user.getAge() + 100);\n        return user;\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-8/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "2.x/chapter2-9/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter2-9</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.5.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.experimental</groupId>\n\t\t\t<artifactId>graphql-spring-boot-starter</artifactId>\n\t\t\t<version>1.0.0-SNAPSHOT</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.dataformat</groupId>\n\t\t\t<artifactId>jackson-dataformat-xml</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<repositories>\n\t\t<repository>\n\t\t\t<id>spring-snapshots</id>\n\t\t\t<url>https://repo.spring.io/snapshot</url>\n\t\t\t<snapshots><enabled>true</enabled></snapshots>\n\t\t</repository>\n\t\t<repository>\n\t\t\t<id>spring-milestones</id>\n\t\t\t<url>https://repo.spring.io/milestone</url>\n\t\t</repository>\n\t</repositories>\n\n</project>"
  },
  {
    "path": "2.x/chapter2-9/src/main/java/com/didispace/chapter29/Chapter29Application.java",
    "content": "package com.didispace.chapter29;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@SpringBootApplication\npublic class Chapter29Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter29Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter2-9/src/main/java/com/didispace/chapter29/User.java",
    "content": "package com.didispace.chapter29;\n\n\nimport com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;\nimport com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@JacksonXmlRootElement(localName = \"User\")\npublic class User {\n\n    @JacksonXmlProperty(localName = \"name\")\n    private String name;\n    @JacksonXmlProperty(localName = \"age\")\n    private Integer age;\n\n}\n"
  },
  {
    "path": "2.x/chapter2-9/src/main/java/com/didispace/chapter29/UserController.java",
    "content": "package com.didispace.chapter29;\n\nimport org.springframework.http.MediaType;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@Controller\npublic class UserController {\n\n    @PostMapping(value = \"/user\",\n            consumes = MediaType.APPLICATION_XML_VALUE,\n            produces = MediaType.APPLICATION_XML_VALUE)\n    @ResponseBody\n    public User create(@RequestBody User user) {\n        user.setName(\"didispace.com : \" + user.getName());\n        user.setAge(user.getAge() + 100);\n        return user;\n    }\n\n}"
  },
  {
    "path": "2.x/chapter2-9/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "2.x/chapter3-1/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-1</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用JdbcTemplate访问MySQL数据库</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-1/src/main/java/com/didispace/chapter31/Chapter31Application.java",
    "content": "package com.didispace.chapter31;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter31Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter31Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-1/src/main/java/com/didispace/chapter31/User.java",
    "content": "package com.didispace.chapter31;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class User {\n\n    private String name;\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter3-1/src/main/java/com/didispace/chapter31/UserService.java",
    "content": "package com.didispace.chapter31;\n\nimport java.util.List;\n\npublic interface UserService {\n\n    /**\n     * 新增一个用户\n     *\n     * @param name\n     * @param age\n     */\n    int create(String name, Integer age);\n\n    /**\n     * 根据name查询用户\n     *\n     * @param name\n     * @return\n     */\n    List<User> getByName(String name);\n\n    /**\n     * 根据name删除用户\n     *\n     * @param name\n     */\n    int deleteByName(String name);\n\n    /**\n     * 获取用户总量\n     */\n    int getAllUsers();\n\n    /**\n     * 删除所有用户\n     */\n    int deleteAllUsers();\n\n}"
  },
  {
    "path": "2.x/chapter3-1/src/main/java/com/didispace/chapter31/UserServiceImpl.java",
    "content": "package com.didispace.chapter31;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.List;\n\n@Service\npublic class UserServiceImpl implements UserService {\n\n    private JdbcTemplate jdbcTemplate;\n\n    UserServiceImpl(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    @Override\n    public int create(String name, Integer age) {\n        return jdbcTemplate.update(\"insert into USER(NAME, AGE) values(?, ?)\", name, age);\n    }\n\n    @Override\n    public List<User> getByName(String name) {\n        List<User> users = jdbcTemplate.query(\"select NAME, AGE from USER where NAME = ?\", (resultSet, i) -> {\n            User user = new User();\n            user.setName(resultSet.getString(\"NAME\"));\n            user.setAge(resultSet.getInt(\"AGE\"));\n            return user;\n        }, name);\n        return users;\n    }\n\n    @Override\n    public int deleteByName(String name) {\n        return jdbcTemplate.update(\"delete from USER where NAME = ?\", name);\n    }\n\n    @Override\n    public int getAllUsers() {\n        return jdbcTemplate.queryForObject(\"select count(1) from USER\", Integer.class);\n    }\n\n    @Override\n    public int deleteAllUsers() {\n        return jdbcTemplate.update(\"delete from USER\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-1/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver"
  },
  {
    "path": "2.x/chapter3-1/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java",
    "content": "package com.didispace.chapter31;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.RequestBuilder;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter31ApplicationTests {\n\n    @Autowired\n    private UserService userSerivce;\n\n    @Before\n    public void setUp() {\n        // 准备，清空user表\n        userSerivce.deleteAllUsers();\n    }\n\n    @Test\n    public void test() throws Exception {\n        // 插入5个用户\n        userSerivce.create(\"Tom\", 10);\n        userSerivce.create(\"Mike\", 11);\n        userSerivce.create(\"Didispace\", 30);\n        userSerivce.create(\"Oscar\", 21);\n        userSerivce.create(\"Linda\", 17);\n\n        // 查询名为Oscar的用户，判断年龄是否匹配\n        List<User> userList = userSerivce.getByName(\"Oscar\");\n        Assert.assertEquals(21, userList.get(0).getAge().intValue());\n\n        // 查数据库，应该有5个用户\n        Assert.assertEquals(5, userSerivce.getAllUsers());\n\n        // 删除两个用户\n        userSerivce.deleteByName(\"Tom\");\n        userSerivce.deleteByName(\"Mike\");\n\n        // 查数据库，应该有5个用户\n        Assert.assertEquals(3, userSerivce.getAllUsers());\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-10/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-10/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-10</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>事务管理入门</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-10/src/main/java/com/didispace/chapter310/Chapter310Application.java",
    "content": "package com.didispace.chapter310;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@SpringBootApplication\npublic class Chapter310Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter310Application.class, args);\n\t}\n\n\t@RestController\n\tstatic class TextController {\n\n\t\t@GetMapping(\"/hello\")\n\t\tpublic String hello() {\n\t\t\treturn \"hello world\";\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-10/src/main/java/com/didispace/chapter310/User.java",
    "content": "package com.didispace.chapter310;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.*;\nimport javax.validation.constraints.Max;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    @Max(50)\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-10/src/main/java/com/didispace/chapter310/UserRepository.java",
    "content": "package com.didispace.chapter310;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/7/9.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    User findByName(String name);\n\n    User findByNameAndAge(String name, Integer age);\n\n    @Query(\"from User u where u.name=:name\")\n    User findUser(@Param(\"name\") String name);\n\n}\n"
  },
  {
    "path": "2.x/chapter3-10/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nspring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect\nspring.jpa.hibernate.ddl-auto=create\n"
  },
  {
    "path": "2.x/chapter3-10/src/test/java/com/didispace/chapter310/Chapter310ApplicationTests.java",
    "content": "package com.didispace.chapter310;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter310ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Test\n    @Transactional\n    public void test() throws Exception {\n        // 创建10条记录\n        userRepository.save(new User(\"AAA\", 10));\n        userRepository.save(new User(\"BBB\", 20));\n        userRepository.save(new User(\"CCC\", 30));\n        userRepository.save(new User(\"DDD\", 40));\n        userRepository.save(new User(\"EEE\", 50));\n        userRepository.save(new User(\"FFF\", 60));\n        userRepository.save(new User(\"GGG\", 70));\n        userRepository.save(new User(\"HHH\", 80));\n        userRepository.save(new User(\"III\", 90));\n        userRepository.save(new User(\"JJJ\", 100));\n\n        // 测试findAll, 查询所有记录\n        Assert.assertEquals(10, userRepository.findAll().size());\n\n        // 测试findByName, 查询姓名为FFF的User\n        Assert.assertEquals(60, userRepository.findByName(\"FFF\").getAge().longValue());\n\n        // 测试findUser, 查询姓名为FFF的User\n        Assert.assertEquals(60, userRepository.findUser(\"FFF\").getAge().longValue());\n\n        // 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的User\n        Assert.assertEquals(\"FFF\", userRepository.findByNameAndAge(\"FFF\", 60).getName());\n\n        // 测试删除姓名为AAA的User\n        userRepository.delete(userRepository.findByName(\"AAA\"));\n\n        // 测试findAll, 查询所有记录, 验证上面的删除是否成功\n        Assert.assertEquals(9, userRepository.findAll().size());\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-11/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-11/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-11</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用Flyway管理数据库版本</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.flywaydb</groupId>\n\t\t\t<artifactId>flyway-core</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-11/src/main/java/com/didispace/chapter311/Chapter311Application.java",
    "content": "package com.didispace.chapter311;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter311Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter311Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-11/src/main/java/com/didispace/chapter311/User.java",
    "content": "package com.didispace.chapter311;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class User {\n\n    private Long id;\n    private String name;\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserService.java",
    "content": "package com.didispace.chapter311;\n\nimport java.util.List;\n\npublic interface UserService {\n\n    /**\n     * 新增一个用户\n     *\n     * @param name\n     * @param age\n     */\n    int create(String name, Integer age);\n\n    /**\n     * 根据name查询用户\n     *\n     * @param name\n     * @return\n     */\n    List<User> getByName(String name);\n\n    /**\n     * 根据name删除用户\n     *\n     * @param name\n     */\n    int deleteByName(String name);\n\n    /**\n     * 获取用户总量\n     */\n    int getAllUsers();\n\n    /**\n     * 删除所有用户\n     */\n    int deleteAllUsers();\n\n}"
  },
  {
    "path": "2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserServiceImpl.java",
    "content": "package com.didispace.chapter311;\n\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic class UserServiceImpl implements UserService {\n\n    private JdbcTemplate jdbcTemplate;\n\n    UserServiceImpl(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    @Override\n    public int create(String name, Integer age) {\n        return jdbcTemplate.update(\"insert into USER(NAME, AGE) values(?, ?)\", name, age);\n    }\n\n    @Override\n    public List<User> getByName(String name) {\n        List<User> users = jdbcTemplate.query(\"select * from USER where NAME = ?\", (resultSet, i) -> {\n            User user = new User();\n            user.setId(resultSet.getLong(\"ID\"));\n            user.setName(resultSet.getString(\"NAME\"));\n            user.setAge(resultSet.getInt(\"AGE\"));\n            return user;\n        }, name);\n        return users;\n    }\n\n    @Override\n    public int deleteByName(String name) {\n        return jdbcTemplate.update(\"delete from USER where NAME = ?\", name);\n    }\n\n    @Override\n    public int getAllUsers() {\n        return jdbcTemplate.queryForObject(\"select count(1) from USER\", Integer.class);\n    }\n\n    @Override\n    public int deleteAllUsers() {\n        return jdbcTemplate.update(\"delete from USER\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-11/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nspring.flyway.locations=classpath:db/migration"
  },
  {
    "path": "2.x/chapter3-11/src/main/resources/db/migration/V1_1__alter_table_user.sql",
    "content": "ALTER TABLE `user` ADD COLUMN `address` VARCHAR(20) DEFAULT NULL;\n"
  },
  {
    "path": "2.x/chapter3-11/src/main/resources/db/migration/V1__Base_version.sql",
    "content": "DROP TABLE IF EXISTS user ;\nCREATE TABLE `user` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',\n  `name` varchar(20) NOT NULL COMMENT '姓名',\n  `age` int(5) DEFAULT NULL COMMENT '年龄',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n"
  },
  {
    "path": "2.x/chapter3-11/src/test/java/com/didispace/chapter311/Chapter311ApplicationTests.java",
    "content": "package com.didispace.chapter311;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\nimport java.util.List;\n\n@Slf4j\n@SpringBootTest\npublic class Chapter311ApplicationTests {\n\n    @Autowired\n    private UserService userSerivce;\n\n    @Test\n    public void test() throws Exception {\n        userSerivce.deleteAllUsers();\n\n        // 插入5个用户\n        userSerivce.create(\"Tom\", 10);\n        userSerivce.create(\"Mike\", 11);\n        userSerivce.create(\"Didispace\", 30);\n        userSerivce.create(\"Oscar\", 21);\n        userSerivce.create(\"Linda\", 17);\n\n        // 查询名为Oscar的用户，判断年龄是否匹配\n        List<User> userList = userSerivce.getByName(\"Oscar\");\n        Assertions.assertEquals(21, userList.get(0).getAge().intValue());\n\n        // 查数据库，应该有5个用户\n        Assertions.assertEquals(5, userSerivce.getAllUsers());\n\n        // 删除两个用户\n        userSerivce.deleteByName(\"Tom\");\n        userSerivce.deleteByName(\"Mike\");\n\n        // 查数据库，应该有5个用户\n        Assertions.assertEquals(3, userSerivce.getAllUsers());\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-12/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-12/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.2</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-12</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用JTA实现多数据源的事务</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jta-atomikos</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-12/src/main/java/com/didispace/chapter312/Chapter312Application.java",
    "content": "package com.didispace.chapter312;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter312Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter312Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-12/src/main/java/com/didispace/chapter312/DataSourceConfiguration.java",
    "content": "package com.didispace.chapter312;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.jdbc.DataSourceBuilder;\nimport org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.sql.DataSource;\n\n@Configuration\npublic class DataSourceConfiguration {\n\n    @Primary\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.jta.atomikos.datasource.primary\")\n    public DataSource primaryDataSource() {\n        return new AtomikosDataSourceBean();\n    }\n\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.jta.atomikos.datasource.secondary\")\n    public DataSource secondaryDataSource() {\n        return new AtomikosDataSourceBean();\n    }\n\n    @Bean\n    public JdbcTemplate primaryJdbcTemplate(@Qualifier(\"primaryDataSource\") DataSource primaryDataSource) {\n        return new JdbcTemplate(primaryDataSource);\n    }\n\n    @Bean\n    public JdbcTemplate secondaryJdbcTemplate(@Qualifier(\"secondaryDataSource\") DataSource secondaryDataSource) {\n        return new JdbcTemplate(secondaryDataSource);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-12/src/main/java/com/didispace/chapter312/TestService.java",
    "content": "package com.didispace.chapter312;\n\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class TestService {\n\n    private JdbcTemplate primaryJdbcTemplate;\n    private JdbcTemplate secondaryJdbcTemplate;\n\n    public TestService(JdbcTemplate primaryJdbcTemplate, JdbcTemplate secondaryJdbcTemplate) {\n        this.primaryJdbcTemplate = primaryJdbcTemplate;\n        this.secondaryJdbcTemplate = secondaryJdbcTemplate;\n    }\n\n    @Transactional\n    public void tx() {\n        // 修改test1库中的数据\n        primaryJdbcTemplate.update(\"update user set age = ? where name = ?\", 30, \"aaa\");\n        // 修改test2库中的数据\n        secondaryJdbcTemplate.update(\"update user set age = ? where name = ?\", 30, \"aaa\");\n    }\n\n    @Transactional\n    public void tx2() {\n        // 修改test1库中的数据\n        primaryJdbcTemplate.update(\"update user set age = ? where name = ?\", 40, \"aaa\");\n        // 模拟：修改test2库之前抛出异常\n        throw new RuntimeException();\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-12/src/main/resources/application.properties",
    "content": "spring.jta.enabled=true\n\nspring.jta.atomikos.datasource.primary.xa-properties.url=jdbc:mysql://localhost:3306/test1\nspring.jta.atomikos.datasource.primary.xa-properties.user=root\nspring.jta.atomikos.datasource.primary.xa-properties.password=12345678\nspring.jta.atomikos.datasource.primary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource\nspring.jta.atomikos.datasource.primary.unique-resource-name=test1\nspring.jta.atomikos.datasource.primary.max-pool-size=25\nspring.jta.atomikos.datasource.primary.min-pool-size=3\nspring.jta.atomikos.datasource.primary.max-lifetime=20000\nspring.jta.atomikos.datasource.primary.borrow-connection-timeout=10000\n\nspring.jta.atomikos.datasource.secondary.xa-properties.url=jdbc:mysql://localhost:3306/test2\nspring.jta.atomikos.datasource.secondary.xa-properties.user=root\nspring.jta.atomikos.datasource.secondary.xa-properties.password=12345678\nspring.jta.atomikos.datasource.secondary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource\nspring.jta.atomikos.datasource.secondary.unique-resource-name=test2\nspring.jta.atomikos.datasource.secondary.max-pool-size=25\nspring.jta.atomikos.datasource.secondary.min-pool-size=3\nspring.jta.atomikos.datasource.secondary.max-lifetime=20000\nspring.jta.atomikos.datasource.secondary.borrow-connection-timeout=10000\n\n#spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1\n#spring.datasource.primary.username=root\n#spring.datasource.primary.password=12345678\n#spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver\n#\n#spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2\n#spring.datasource.secondary.username=root\n#spring.datasource.secondary.password=12345678\n#spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver"
  },
  {
    "path": "2.x/chapter3-12/src/test/java/com/didispace/chapter312/Chapter312ApplicationTests.java",
    "content": "package com.didispace.chapter312;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.transaction.annotation.Transactional;\n\n\n@SpringBootTest(classes = Chapter312Application.class)\npublic class Chapter312ApplicationTests {\n\n    @Autowired\n    protected JdbcTemplate primaryJdbcTemplate;\n    @Autowired\n    protected JdbcTemplate secondaryJdbcTemplate;\n\n    @Autowired\n    private TestService testService;\n\n    @Test\n    public void test1() throws Exception {\n        // 正确更新的情况\n        testService.tx();\n        Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject(\"select age from user where name=?\", Integer.class, \"aaa\"));\n        Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject(\"select age from user where name=?\", Integer.class, \"aaa\"));\n    }\n\n    @Test\n    public void test2() throws Exception {\n        // 更新失败的情况\n        try {\n            testService.tx2();\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            // 部分更新失败，test1中的更新应该回滚\n            Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject(\"select age from user where name=?\", Integer.class, \"aaa\"));\n            Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject(\"select age from user where name=?\", Integer.class, \"aaa\"));\n        }\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-13/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-13/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.5.0</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-13</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>2.5版本之后的数据脚本初始化</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-13/src/main/java/com/didispace/chapter313/Chapter313Application.java",
    "content": "package com.didispace.chapter313;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter313Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter313Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-13/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\n# Spring Boot 2.5.0 init schema & data\nspring.sql.init.username=root\nspring.sql.init.password=\nspring.sql.init.schema-locations=classpath*:schema-all.sql\n#spring.sql.init.enabled=true\n#spring.sql.init.data-locations=classpath*:\n#spring.sql.init.encoding=UTF-8\n#spring.sql.init.separator=;\n#spring.sql.init.continue-on-error=true\n\n"
  },
  {
    "path": "2.x/chapter3-13/src/main/resources/schema-all.sql",
    "content": "create table test.user_info\n(\n    id          int unsigned auto_increment comment '用户id'\n        primary key,\n    open_id     varchar(255)     default '' null comment '微信小程序openid',\n    nick_name   varchar(255)     default '' null comment '微信名',\n    head_img    varchar(255)     default '' null comment '微信头像',\n    sex         varchar(255)     default '' null comment '性别',\n    phone       varchar(255)     default '' null comment '手机',\n    province    varchar(255)     default '' null comment '注册地址：省',\n    city        varchar(255)     default '' null comment '注册地址：城市',\n    country     varchar(255)     default '' null comment '注册地址：县/区',\n    status      tinyint unsigned default 0  not null comment '是否标记删除 0：否 1：是',\n    create_time datetime                    not null comment '创建时间',\n    update_time datetime                    not null comment '更新时间'\n)\n    comment '用户表';\n\n"
  },
  {
    "path": "2.x/chapter3-13/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java",
    "content": "package com.didispace.chapter31;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n\n@SpringBootTest\npublic class Chapter31ApplicationTests {\n\n\n    @Test\n    public void test() throws Exception {\n\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-2/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-2</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>默认数据源Hikari的配置详解</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-2/src/main/java/com/didispace/chapter32/Chapter32Application.java",
    "content": "package com.didispace.chapter32;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter32Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter32Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-2/src/main/java/com/didispace/chapter32/User.java",
    "content": "package com.didispace.chapter32;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class User {\n\n    private String name;\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter3-2/src/main/java/com/didispace/chapter32/UserService.java",
    "content": "package com.didispace.chapter32;\n\nimport java.util.List;\n\npublic interface UserService {\n\n    /**\n     * 新增一个用户\n     *\n     * @param name\n     * @param age\n     */\n    int create(String name, Integer age);\n\n    /**\n     * 根据name查询用户\n     *\n     * @param name\n     * @return\n     */\n    List<User> getByName(String name);\n\n    /**\n     * 根据name删除用户\n     *\n     * @param name\n     */\n    int deleteByName(String name);\n\n    /**\n     * 获取用户总量\n     */\n    int getAllUsers();\n\n    /**\n     * 删除所有用户\n     */\n    int deleteAllUsers();\n\n}"
  },
  {
    "path": "2.x/chapter3-2/src/main/java/com/didispace/chapter32/UserServiceImpl.java",
    "content": "package com.didispace.chapter32;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.List;\n\n@Service\npublic class UserServiceImpl implements UserService {\n\n    private JdbcTemplate jdbcTemplate;\n\n    UserServiceImpl(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    @Override\n    public int create(String name, Integer age) {\n        return jdbcTemplate.update(\"insert into USER(NAME, AGE) values(?, ?)\", name, age);\n    }\n\n    @Override\n    public List<User> getByName(String name) {\n        List<User> users = jdbcTemplate.query(\"select NAME, AGE from USER where NAME = ?\", (resultSet, i) -> {\n            User user = new User();\n            user.setName(resultSet.getString(\"NAME\"));\n            user.setAge(resultSet.getInt(\"AGE\"));\n            return user;\n        }, name);\n        return users;\n    }\n\n    @Override\n    public int deleteByName(String name) {\n        return jdbcTemplate.update(\"delete from USER where NAME = ?\", name);\n    }\n\n    @Override\n    public int getAllUsers() {\n        return jdbcTemplate.queryForObject(\"select count(1) from USER\", Integer.class);\n    }\n\n    @Override\n    public int deleteAllUsers() {\n        return jdbcTemplate.update(\"delete from USER\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-2/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\n# 最小空闲连接，默认值10，小于0或大于maximum-pool-size，都会重置为maximum-pool-size\nspring.datasource.hikari.minimum-idle=10\n# 最大连接数，小于等于0会被重置为默认值10；大于零小于1会被重置为minimum-idle的值\nspring.datasource.hikari.maximum-pool-size=20\n# 空闲连接超时时间，默认值600000（10分钟），大于等于max-lifetime且max-lifetime>0，会被重置为0；不等于0且小于10秒，会被重置为10秒。\nspring.datasource.hikari.idle-timeout=500000\n# 连接最大存活时间.不等于0且小于30秒，会被重置为默认值30分钟.设置应该比mysql设置的超时时间短\nspring.datasource.hikari.max-lifetime=540000\n# 连接超时时间：毫秒，小于250毫秒，否则被重置为默认值30秒\nspring.datasource.hikari.connection-timeout=60000\n# 用于测试连接是否可用的查询语句\nspring.datasource.hikari.connection-test-query=SELECT 1\n"
  },
  {
    "path": "2.x/chapter3-2/src/test/java/com/didispace/chapter32/Chapter32ApplicationTests.java",
    "content": "package com.didispace.chapter32;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.RequestBuilder;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.sql.DataSource;\nimport java.util.List;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter32ApplicationTests {\n\n    @Autowired\n    private UserService userSerivce;\n\n    @Autowired\n    private DataSource dataSource;\n\n    @Before\n    public void setUp() {\n        // 准备，清空user表\n        userSerivce.deleteAllUsers();\n\n    }\n\n    @Test\n    public void test() throws Exception {\n        // 插入5个用户\n        userSerivce.create(\"Tom\", 10);\n        userSerivce.create(\"Mike\", 11);\n        userSerivce.create(\"Didispace\", 30);\n        userSerivce.create(\"Oscar\", 21);\n        userSerivce.create(\"Linda\", 17);\n\n        // 查询名为Oscar的用户，判断年龄是否匹配\n        List<User> userList = userSerivce.getByName(\"Oscar\");\n        Assert.assertEquals(21, userList.get(0).getAge().intValue());\n\n        // 查数据库，应该有5个用户\n        Assert.assertEquals(5, userSerivce.getAllUsers());\n\n        // 删除两个用户\n        userSerivce.deleteByName(\"Tom\");\n        userSerivce.deleteByName(\"Mike\");\n\n        // 查数据库，应该有5个用户\n        Assert.assertEquals(3, userSerivce.getAllUsers());\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-3/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-3</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用国产数据库连接池Druid</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>druid-spring-boot-starter</artifactId>\n\t\t\t<version>1.1.21</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-3/src/main/java/com/didispace/chapter33/Chapter33Application.java",
    "content": "package com.didispace.chapter33;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@SpringBootApplication\npublic class Chapter33Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter33Application.class, args);\n\t}\n\n\t@RestController\n\tstatic class TextController {\n\n\t\t@GetMapping(\"/hello\")\n\t\tpublic String hello() {\n\t\t\treturn \"hello world\";\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-3/src/main/java/com/didispace/chapter33/User.java",
    "content": "package com.didispace.chapter33;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class User {\n\n    private String name;\n    private Integer age;\n\n}"
  },
  {
    "path": "2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserController.java",
    "content": "package com.didispace.chapter33;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/2/8.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\n@Data\n@AllArgsConstructor\n@RestController\npublic class UserController {\n\n    private UserService userService;\n\n    @PostMapping(\"/user\")\n    public int create(@RequestBody User user) {\n        return userService.create(user.getName(), user.getAge());\n    }\n\n    @GetMapping(\"/user/{name}\")\n    public List<User> getByName(@PathVariable String name) {\n        return userService.getByName(name);\n    }\n\n    @DeleteMapping(\"/user/{name}\")\n    public int deleteByName(@PathVariable String name) {\n        return userService.deleteByName(name);\n    }\n\n    @GetMapping(\"/user/count\")\n    public int getAllUsers() {\n        return userService.getAllUsers();\n    }\n\n    @DeleteMapping(\"/user/all\")\n    public int deleteAllUsers() {\n        return userService.deleteAllUsers();\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserService.java",
    "content": "package com.didispace.chapter33;\n\nimport java.util.List;\n\npublic interface UserService {\n\n    /**\n     * 新增一个用户\n     *\n     * @param name\n     * @param age\n     */\n    int create(String name, Integer age);\n\n    /**\n     * 根据name查询用户\n     *\n     * @param name\n     * @return\n     */\n    List<User> getByName(String name);\n\n    /**\n     * 根据name删除用户\n     *\n     * @param name\n     */\n    int deleteByName(String name);\n\n    /**\n     * 获取用户总量\n     */\n    int getAllUsers();\n\n    /**\n     * 删除所有用户\n     */\n    int deleteAllUsers();\n\n}"
  },
  {
    "path": "2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserServiceImpl.java",
    "content": "package com.didispace.chapter33;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.List;\n\n@Service\npublic class UserServiceImpl implements UserService {\n\n    private JdbcTemplate jdbcTemplate;\n\n    UserServiceImpl(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    @Override\n    public int create(String name, Integer age) {\n        return jdbcTemplate.update(\"insert into USER(NAME, AGE) values(?, ?)\", name, age);\n    }\n\n    @Override\n    public List<User> getByName(String name) {\n        List<User> users = jdbcTemplate.query(\"select NAME, AGE from USER where NAME = ?\", (resultSet, i) -> {\n            User user = new User();\n            user.setName(resultSet.getString(\"NAME\"));\n            user.setAge(resultSet.getInt(\"AGE\"));\n            return user;\n        }, name);\n        return users;\n    }\n\n    @Override\n    public int deleteByName(String name) {\n        return jdbcTemplate.update(\"delete from USER where NAME = ?\", name);\n    }\n\n    @Override\n    public int getAllUsers() {\n        return jdbcTemplate.queryForObject(\"select count(1) from USER\", Integer.class);\n    }\n\n    @Override\n    public int deleteAllUsers() {\n        return jdbcTemplate.update(\"delete from USER\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-3/src/main/resources/application.properties",
    "content": "\n# 基础配置\nspring.datasource.druid.url=jdbc:mysql://localhost:3306/test\nspring.datasource.druid.username=root\nspring.datasource.druid.password=\nspring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver\n\n# 连接池配置\nspring.datasource.druid.initialSize=10\nspring.datasource.druid.maxActive=20\nspring.datasource.druid.maxWait=60000\nspring.datasource.druid.minIdle=1\nspring.datasource.druid.timeBetweenEvictionRunsMillis=60000\nspring.datasource.druid.minEvictableIdleTimeMillis=300000\nspring.datasource.druid.testWhileIdle=true\nspring.datasource.druid.testOnBorrow=true\nspring.datasource.druid.testOnReturn=false\nspring.datasource.druid.poolPreparedStatements=true\nspring.datasource.druid.maxOpenPreparedStatements=20\nspring.datasource.druid.validationQuery=SELECT 1\nspring.datasource.druid.validation-query-timeout=500\nspring.datasource.druid.filters=stat,wall\n\n# 监控配置\nspring.datasource.druid.stat-view-servlet.enabled=true\nspring.datasource.druid.stat-view-servlet.url-pattern=/druid/*\nspring.datasource.druid.stat-view-servlet.reset-enable=true\nspring.datasource.druid.stat-view-servlet.login-username=admin\nspring.datasource.druid.stat-view-servlet.login-password=admin\n"
  },
  {
    "path": "2.x/chapter3-3/src/test/java/com/didispace/chapter33/Chapter33ApplicationTests.java",
    "content": "package com.didispace.chapter33;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.RequestBuilder;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.sql.DataSource;\nimport java.util.List;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter33ApplicationTests {\n\n    @Autowired\n    private UserService userSerivce;\n\n    @Autowired\n    private DataSource dataSource;\n\n    @Before\n    public void setUp() {\n        // 准备，清空user表\n        userSerivce.deleteAllUsers();\n\n    }\n\n    @Test\n    public void test() throws Exception {\n        // 插入5个用户\n        userSerivce.create(\"Tom\", 10);\n        userSerivce.create(\"Mike\", 11);\n        userSerivce.create(\"Didispace\", 30);\n        userSerivce.create(\"Oscar\", 21);\n        userSerivce.create(\"Linda\", 17);\n\n        // 查询名为Oscar的用户，判断年龄是否匹配\n        List<User> userList = userSerivce.getByName(\"Oscar\");\n        Assert.assertEquals(21, userList.get(0).getAge().intValue());\n\n        // 查数据库，应该有5个用户\n        Assert.assertEquals(5, userSerivce.getAllUsers());\n\n        // 删除两个用户\n        userSerivce.deleteByName(\"Tom\");\n        userSerivce.deleteByName(\"Mike\");\n\n        // 查数据库，应该有5个用户\n        Assert.assertEquals(3, userSerivce.getAllUsers());\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-4/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-4</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用Spring Data JPA访问MySQL</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-4/src/main/java/com/didispace/chapter34/Chapter34Application.java",
    "content": "package com.didispace.chapter34;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@SpringBootApplication\npublic class Chapter34Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter34Application.class, args);\n\t}\n\n\t@RestController\n\tstatic class TextController {\n\n\t\t@GetMapping(\"/hello\")\n\t\tpublic String hello() {\n\t\t\treturn \"hello world\";\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-4/src/main/java/com/didispace/chapter34/User.java",
    "content": "package com.didispace.chapter34;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter3-4/src/main/java/com/didispace/chapter34/UserRepository.java",
    "content": "package com.didispace.chapter34;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/2/15.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    User findByName(String name);\n\n    User findByNameAndAge(String name, Integer age);\n\n    @Query(\"from User u where u.name=:name\")\n    User findUser(@Param(\"name\") String name);\n\n}\n"
  },
  {
    "path": "2.x/chapter3-4/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nspring.jpa.properties.hibernate.hbm2ddl.auto=create-drop"
  },
  {
    "path": "2.x/chapter3-4/src/test/java/com/didispace/chapter34/Chapter34ApplicationTests.java",
    "content": "package com.didispace.chapter34;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport javax.sql.DataSource;\nimport java.util.List;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter34ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Test\n    public void test() throws Exception {\n        // 创建10条记录\n        userRepository.save(new User(\"AAA\", 10));\n        userRepository.save(new User(\"BBB\", 20));\n        userRepository.save(new User(\"CCC\", 30));\n        userRepository.save(new User(\"DDD\", 40));\n        userRepository.save(new User(\"EEE\", 50));\n        userRepository.save(new User(\"FFF\", 60));\n        userRepository.save(new User(\"GGG\", 70));\n        userRepository.save(new User(\"HHH\", 80));\n        userRepository.save(new User(\"III\", 90));\n        userRepository.save(new User(\"JJJ\", 100));\n\n        // 测试findAll, 查询所有记录\n        Assert.assertEquals(10, userRepository.findAll().size());\n\n        // 测试findByName, 查询姓名为FFF的User\n        Assert.assertEquals(60, userRepository.findByName(\"FFF\").getAge().longValue());\n\n        // 测试findUser, 查询姓名为FFF的User\n        Assert.assertEquals(60, userRepository.findUser(\"FFF\").getAge().longValue());\n\n        // 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的User\n        Assert.assertEquals(\"FFF\", userRepository.findByNameAndAge(\"FFF\", 60).getName());\n\n        // 测试删除姓名为AAA的User\n        userRepository.delete(userRepository.findByName(\"AAA\"));\n\n        // 测试findAll, 查询所有记录, 验证上面的删除是否成功\n        Assert.assertEquals(9, userRepository.findAll().size());\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-5/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-5</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用MyBatis访问MySQL</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t\t<version>2.1.1</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-5/src/main/java/com/didispace/chapter35/Chapter35Application.java",
    "content": "package com.didispace.chapter35;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter35Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter35Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-5/src/main/java/com/didispace/chapter35/User.java",
    "content": "package com.didispace.chapter35;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\npublic class User {\n\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter3-5/src/main/java/com/didispace/chapter35/UserMapper.java",
    "content": "package com.didispace.chapter35;\n\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/2/15.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\n@Mapper\npublic interface UserMapper {\n\n    @Select(\"SELECT * FROM USER WHERE NAME = #{name}\")\n    User findByName(@Param(\"name\") String name);\n\n    @Insert(\"INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})\")\n    int insert(@Param(\"name\") String name, @Param(\"age\") Integer age);\n\n}\n"
  },
  {
    "path": "2.x/chapter3-5/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n"
  },
  {
    "path": "2.x/chapter3-5/src/test/java/com/didispace/chapter35/Chapter35ApplicationTests.java",
    "content": "package com.didispace.chapter35;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.sql.DataSource;\nimport java.util.List;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\n@Transactional\npublic class Chapter35ApplicationTests {\n\n    @Autowired\n    private UserMapper userMapper;\n\n    @Test\n    @Rollback\n    public void test() throws Exception {\n        userMapper.insert(\"AAA\", 20);\n        User u = userMapper.findByName(\"AAA\");\n        Assert.assertEquals(20, u.getAge().intValue());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-6/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-6</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用MyBatis（xml配置方式）</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t\t<version>2.1.1</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-6/src/main/java/com/didispace/chapter36/Chapter36Application.java",
    "content": "package com.didispace.chapter36;\n\nimport org.mybatis.spring.annotation.MapperScan;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@MapperScan(\"com.didispace.chapter36.mapper\")\n@SpringBootApplication\npublic class Chapter36Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter36Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-6/src/main/java/com/didispace/chapter36/entity/User.java",
    "content": "package com.didispace.chapter36.entity;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\npublic class User {\n\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter3-6/src/main/java/com/didispace/chapter36/mapper/UserMapper.java",
    "content": "package com.didispace.chapter36.mapper;\n\nimport com.didispace.chapter36.entity.User;\nimport org.apache.ibatis.annotations.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/2/28.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface UserMapper {\n\n    User findByName(@Param(\"name\") String name);\n\n    int insert(@Param(\"name\") String name, @Param(\"age\") Integer age);\n\n}\n"
  },
  {
    "path": "2.x/chapter3-6/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nmybatis.mapper-locations=classpath:mapper/*.xml\n"
  },
  {
    "path": "2.x/chapter3-6/src/main/resources/mapper/UserMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper\n        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didispace.chapter36.mapper.UserMapper\">\n    <select id=\"findByName\" resultType=\"com.didispace.chapter36.entity.User\">\n        SELECT * FROM USER WHERE NAME = #{name}\n    </select>\n\n    <insert id=\"insert\">\n        INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})\n    </insert>\n</mapper>"
  },
  {
    "path": "2.x/chapter3-6/src/test/java/com/didispace/chapter36/Chapter36ApplicationTests.java",
    "content": "package com.didispace.chapter36;\n\nimport com.didispace.chapter36.entity.User;\nimport com.didispace.chapter36.mapper.UserMapper;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\n@Transactional\npublic class Chapter36ApplicationTests {\n\n    @Autowired\n    private UserMapper userMapper;\n\n    @Test\n    @Rollback\n    public void test() throws Exception {\n        userMapper.insert(\"AAA\", 20);\n        User u = userMapper.findByName(\"AAA\");\n        Assert.assertEquals(20, u.getAge().intValue());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-7/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-7/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-7</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>JdbcTemplate的多数据源配置</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-jdbc</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-7/src/main/java/com/didispace/chapter37/Chapter37Application.java",
    "content": "package com.didispace.chapter37;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter37Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter37Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-7/src/main/java/com/didispace/chapter37/DataSourceConfiguration.java",
    "content": "package com.didispace.chapter37;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.jdbc.DataSourceBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.sql.DataSource;\n\n@Configuration\npublic class DataSourceConfiguration {\n\n    @Primary\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.datasource.primary\")\n    public DataSource primaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.datasource.secondary\")\n    public DataSource secondaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n    @Bean\n    public JdbcTemplate primaryJdbcTemplate(@Qualifier(\"primaryDataSource\") DataSource primaryDataSource) {\n        return new JdbcTemplate(primaryDataSource);\n    }\n\n    @Bean\n    public JdbcTemplate secondaryJdbcTemplate(@Qualifier(\"secondaryDataSource\") DataSource secondaryDataSource) {\n        return new JdbcTemplate(secondaryDataSource);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-7/src/main/resources/application.properties",
    "content": "# pring boot 1.x的配置：spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.username=root\nspring.datasource.primary.password=123456\nspring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver\n\n# spring boot 1.x的配置：spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.username=root\nspring.datasource.secondary.password=123456\nspring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver"
  },
  {
    "path": "2.x/chapter3-7/src/test/java/com/didispace/chapter37/Chapter37ApplicationTests.java",
    "content": "package com.didispace.chapter37;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter37ApplicationTests {\n\n    @Autowired\n    protected JdbcTemplate primaryJdbcTemplate;\n\n    @Autowired\n    protected JdbcTemplate secondaryJdbcTemplate;\n\n    @Before\n    public void setUp() {\n        primaryJdbcTemplate.update(\"DELETE  FROM  USER \");\n        secondaryJdbcTemplate.update(\"DELETE  FROM  USER \");\n    }\n\n    @Test\n    public void test() throws Exception {\n        // 往第一个数据源中插入 2 条数据\n        primaryJdbcTemplate.update(\"insert into user(name,age) values(?, ?)\", \"aaa\", 20);\n        primaryJdbcTemplate.update(\"insert into user(name,age) values(?, ?)\", \"bbb\", 30);\n\n        // 往第二个数据源中插入 1 条数据，若插入的是第一个数据源，则会主键冲突报错\n        secondaryJdbcTemplate.update(\"insert into user(name,age) values(?, ?)\", \"ccc\", 20);\n\n        // 查一下第一个数据源中是否有 2 条数据，验证插入是否成功\n        Assert.assertEquals(\"2\", primaryJdbcTemplate.queryForObject(\"select count(1) from user\", String.class));\n\n        // 查一下第一个数据源中是否有 1 条数据，验证插入是否成功\n        Assert.assertEquals(\"1\", secondaryJdbcTemplate.queryForObject(\"select count(1) from user\", String.class));\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-8/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-8/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-8</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>Spring Data JPA的多数据源配置</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/Chapter38Application.java",
    "content": "package com.didispace.chapter38;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@SpringBootApplication\npublic class Chapter38Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter38Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/DataSourceConfiguration.java",
    "content": "package com.didispace.chapter38;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.jdbc.DataSourceBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\nimport javax.sql.DataSource;\n\n@Configuration\npublic class DataSourceConfiguration {\n\n    @Primary\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.datasource.primary\")\n    public DataSource primaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.datasource.secondary\")\n    public DataSource secondaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/PrimaryConfig.java",
    "content": "package com.didispace.chapter38;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;\nimport org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;\nimport org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;\nimport org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\nimport org.springframework.orm.jpa.JpaTransactionManager;\nimport org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;\nimport org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;\nimport org.springframework.transaction.PlatformTransactionManager;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\nimport javax.persistence.EntityManager;\nimport javax.sql.DataSource;\nimport java.util.Map;\n\n@Configuration\n@EnableTransactionManagement\n@EnableJpaRepositories(\n        entityManagerFactoryRef=\"entityManagerFactoryPrimary\",\n        transactionManagerRef=\"transactionManagerPrimary\",\n        basePackages= { \"com.didispace.chapter38.p\" }) //设置Repository所在位置\npublic class PrimaryConfig {\n\n    @Autowired\n    @Qualifier(\"primaryDataSource\")\n    private DataSource primaryDataSource;\n\n    @Autowired\n    private JpaProperties jpaProperties;\n    @Autowired\n    private HibernateProperties hibernateProperties;\n\n    private Map<String, Object> getVendorProperties() {\n        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());\n    }\n\n    @Primary\n    @Bean(name = \"entityManagerPrimary\")\n    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {\n        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();\n    }\n\n    @Primary\n    @Bean(name = \"entityManagerFactoryPrimary\")\n    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {\n//        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();\n//        jpaVendorAdapter.setGenerateDdl(true);\n        return builder\n                .dataSource(primaryDataSource)\n                .packages(\"com.didispace.chapter38.p\") //设置实体类所在位置\n                .persistenceUnit(\"primaryPersistenceUnit\")\n                .properties(getVendorProperties())\n                .build();\n    }\n\n    @Primary\n    @Bean(name = \"transactionManagerPrimary\")\n    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {\n        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());\n    }\n\n\n}"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/SecondaryConfig.java",
    "content": "package com.didispace.chapter38;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;\nimport org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;\nimport org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;\nimport org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\nimport org.springframework.orm.jpa.JpaTransactionManager;\nimport org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;\nimport org.springframework.transaction.PlatformTransactionManager;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\nimport javax.persistence.EntityManager;\nimport javax.sql.DataSource;\nimport java.util.Map;\n\n@Configuration\n@EnableTransactionManagement\n@EnableJpaRepositories(\n        entityManagerFactoryRef=\"entityManagerFactorySecondary\",\n        transactionManagerRef=\"transactionManagerSecondary\",\n        basePackages= { \"com.didispace.chapter38.s\" }) //设置Repository所在位置\npublic class SecondaryConfig {\n\n    @Autowired\n    @Qualifier(\"secondaryDataSource\")\n    private DataSource secondaryDataSource;\n\n    @Autowired\n    private JpaProperties jpaProperties;\n    @Autowired\n    private HibernateProperties hibernateProperties;\n\n    private Map<String, Object> getVendorProperties() {\n        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());\n    }\n\n    @Bean(name = \"entityManagerSecondary\")\n    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {\n        return entityManagerFactorySecondary(builder).getObject().createEntityManager();\n    }\n\n    @Bean(name = \"entityManagerFactorySecondary\")\n    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {\n        return builder\n                .dataSource(secondaryDataSource)\n                .packages(\"com.didispace.chapter38.s\") //设置实体类所在位置\n                .persistenceUnit(\"secondaryPersistenceUnit\")\n                .properties(getVendorProperties())\n                .build();\n    }\n\n    @Bean(name = \"transactionManagerSecondary\")\n    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {\n        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/User.java",
    "content": "package com.didispace.chapter38.p;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/UserRepository.java",
    "content": "package com.didispace.chapter38.p;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on  2020/6/22.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n}\n"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/Message.java",
    "content": "package com.didispace.chapter38.s;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class Message {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String title;\n    private String message;\n\n    public Message(String title, String message) {\n        this.title = title;\n        this.message = message;\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/MessageRepository.java",
    "content": "package com.didispace.chapter38.s;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/6/22.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface MessageRepository extends JpaRepository<Message, Long> {\n\n\n}\n"
  },
  {
    "path": "2.x/chapter3-8/src/main/resources/application.properties",
    "content": "# pring boot 1.x的配置：spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.username=root\nspring.datasource.primary.password=12345678\nspring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver\n\n# spring boot 1.x的配置：spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.username=root\nspring.datasource.secondary.password=12345678\nspring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver\n\n# 日志打印执行的SQL\nspring.jpa.show-sql=true\n# Hibernate的DDL策略\nspring.jpa.hibernate.ddl-auto=create-drop\n"
  },
  {
    "path": "2.x/chapter3-8/src/test/java/com/didispace/chapter38/Chapter38ApplicationTests.java",
    "content": "package com.didispace.chapter38;\n\nimport com.didispace.chapter38.p.User;\nimport com.didispace.chapter38.p.UserRepository;\nimport com.didispace.chapter38.s.Message;\nimport com.didispace.chapter38.s.MessageRepository;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter38ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n    @Autowired\n    private MessageRepository messageRepository;\n\n    @Test\n    public void test() throws Exception {\n        userRepository.save(new User(\"aaa\", 10));\n        userRepository.save(new User(\"bbb\", 20));\n        userRepository.save(new User(\"ccc\", 30));\n        userRepository.save(new User(\"ddd\", 40));\n        userRepository.save(new User(\"eee\", 50));\n\n        Assert.assertEquals(5, userRepository.findAll().size());\n\n        messageRepository.save(new Message(\"o1\", \"aaaaaaaaaa\"));\n        messageRepository.save(new Message(\"o2\", \"bbbbbbbbbb\"));\n        messageRepository.save(new Message(\"o3\", \"cccccccccc\"));\n\n        Assert.assertEquals(3, messageRepository.findAll().size());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-9/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter3-9/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter3-9</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>MyBatis的多数据源配置</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis.spring.boot</groupId>\n\t\t\t<artifactId>mybatis-spring-boot-starter</artifactId>\n\t\t\t<version>2.1.1</version>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/Chapter39Application.java",
    "content": "package com.didispace.chapter39;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter39Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter39Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/DataSourceConfiguration.java",
    "content": "package com.didispace.chapter39;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.jdbc.DataSourceBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\n\nimport javax.sql.DataSource;\n\n@Configuration\npublic class DataSourceConfiguration {\n\n    @Primary\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.datasource.primary\")\n    public DataSource primaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n    @Bean\n    @ConfigurationProperties(prefix = \"spring.datasource.secondary\")\n    public DataSource secondaryDataSource() {\n        return DataSourceBuilder.create().build();\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/PrimaryConfig.java",
    "content": "package com.didispace.chapter39;\n\nimport org.apache.ibatis.session.SqlSessionFactory;\nimport org.mybatis.spring.SqlSessionFactoryBean;\nimport org.mybatis.spring.SqlSessionTemplate;\nimport org.mybatis.spring.annotation.MapperScan;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport javax.sql.DataSource;\n\n@Configuration\n@MapperScan(\n        basePackages = \"com.didispace.chapter39.p\",\n        sqlSessionFactoryRef = \"sqlSessionFactoryPrimary\",\n        sqlSessionTemplateRef = \"sqlSessionTemplatePrimary\")\npublic class PrimaryConfig {\n\n    private DataSource primaryDataSource;\n\n    public PrimaryConfig(@Qualifier(\"primaryDataSource\") DataSource primaryDataSource) {\n        this.primaryDataSource = primaryDataSource;\n    }\n\n    @Bean\n    public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {\n        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();\n        bean.setDataSource(primaryDataSource);\n        return bean.getObject();\n    }\n\n    @Bean\n    public SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {\n        return new SqlSessionTemplate(sqlSessionFactoryPrimary());\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/SecondaryConfig.java",
    "content": "package com.didispace.chapter39;\n\nimport org.apache.ibatis.session.SqlSessionFactory;\nimport org.mybatis.spring.SqlSessionFactoryBean;\nimport org.mybatis.spring.SqlSessionTemplate;\nimport org.mybatis.spring.annotation.MapperScan;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport javax.sql.DataSource;\n\n@Configuration\n@MapperScan(\n        basePackages = \"com.didispace.chapter39.s\",\n        sqlSessionFactoryRef = \"sqlSessionFactorySecondary\",\n        sqlSessionTemplateRef = \"sqlSessionTemplateSecondary\")\npublic class SecondaryConfig {\n\n    private DataSource secondaryDataSource;\n\n    public SecondaryConfig(@Qualifier(\"secondaryDataSource\") DataSource secondaryDataSource) {\n        this.secondaryDataSource = secondaryDataSource;\n    }\n\n    @Bean\n    public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {\n        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();\n        bean.setDataSource(secondaryDataSource);\n        return bean.getObject();\n    }\n\n    @Bean\n    public SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {\n        return new SqlSessionTemplate(sqlSessionFactorySecondary());\n    }\n\n}"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/entity/UserPrimary.java",
    "content": "package com.didispace.chapter39.p.entity;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\npublic class UserPrimary {\n\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public UserPrimary(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/mapper/UserMapperPrimary.java",
    "content": "package com.didispace.chapter39.p.mapper;\n\nimport com.didispace.chapter39.p.entity.UserPrimary;\nimport org.apache.ibatis.annotations.Delete;\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/2/28.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface UserMapperPrimary {\n\n    @Select(\"SELECT * FROM USER WHERE NAME = #{name}\")\n    UserPrimary findByName(@Param(\"name\") String name);\n\n    @Insert(\"INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})\")\n    int insert(@Param(\"name\") String name, @Param(\"age\") Integer age);\n\n    @Delete(\"DELETE FROM USER\")\n    int deleteAll();\n\n}\n"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/entity/UserSecondary.java",
    "content": "package com.didispace.chapter39.s.entity;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\npublic class UserSecondary {\n\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public UserSecondary(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/mapper/UserMapperSecondary.java",
    "content": "package com.didispace.chapter39.s.mapper;\n\nimport com.didispace.chapter39.s.entity.UserSecondary;\nimport org.apache.ibatis.annotations.Delete;\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/2/28.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface UserMapperSecondary {\n\n    @Select(\"SELECT * FROM USER WHERE NAME = #{name}\")\n    UserSecondary findByName(@Param(\"name\") String name);\n\n    @Insert(\"INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})\")\n    int insert(@Param(\"name\") String name, @Param(\"age\") Integer age);\n\n    @Delete(\"DELETE FROM USER\")\n    int deleteAll();\n}\n"
  },
  {
    "path": "2.x/chapter3-9/src/main/resources/application.properties",
    "content": "# pring boot 1.x的配置：spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1\nspring.datasource.primary.username=root\nspring.datasource.primary.password=12345678\nspring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver\n\n# spring boot 1.x的配置：spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2\nspring.datasource.secondary.username=root\nspring.datasource.secondary.password=12345678\nspring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver\n\n#mybatis.mapper-locations=classpath:mapper/*.xml\n"
  },
  {
    "path": "2.x/chapter3-9/src/main/resources/mapper.primary/UserMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper\n        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.didispace.chapter39.p.mapper.UserMapperPrimary\">\n    <select id=\"findByName\" resultType=\"com.didispace.chapter39.p.entity.UserPrimary\">\n        SELECT * FROM USER WHERE NAME = #{name}\n    </select>\n\n    <insert id=\"insert\">\n        INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})\n    </insert>\n\n</mapper>"
  },
  {
    "path": "2.x/chapter3-9/src/main/resources/mapper.secondary/UserMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper\n        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.didispace.chapter39.s.mapper.UserMapperSecondary\">\n\n    <select id=\"findByName\" resultType=\"com.didispace.chapter39.s.entity.UserSecondary\">\n        SELECT * FROM USER WHERE NAME = #{name}\n    </select>\n\n    <insert id=\"insert\">\n        INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})\n    </insert>\n\n</mapper>"
  },
  {
    "path": "2.x/chapter3-9/src/test/java/com/didispace/chapter39/Chapter39ApplicationTests.java",
    "content": "package com.didispace.chapter39;\n\nimport com.didispace.chapter39.p.entity.UserPrimary;\nimport com.didispace.chapter39.p.mapper.UserMapperPrimary;\nimport com.didispace.chapter39.s.entity.UserSecondary;\nimport com.didispace.chapter39.s.mapper.UserMapperSecondary;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\n@Transactional\npublic class Chapter39ApplicationTests {\n\n    @Autowired\n    private UserMapperPrimary userMapperPrimary;\n    @Autowired\n    private UserMapperSecondary userMapperSecondary;\n\n    @Before\n    public void setUp() {\n        // 清空测试表，保证每次结果一样\n        userMapperPrimary.deleteAll();\n        userMapperSecondary.deleteAll();\n    }\n\n    @Test\n    public void test() throws Exception {\n        // 往Primary数据源插入一条数据\n        userMapperPrimary.insert(\"AAA\", 20);\n\n        // 从Primary数据源查询刚才插入的数据，配置正确就可以查询到\n        UserPrimary userPrimary = userMapperPrimary.findByName(\"AAA\");\n        Assert.assertEquals(20, userPrimary.getAge().intValue());\n\n        // 从Secondary数据源查询刚才插入的数据，配置正确应该是查询不到的\n        UserSecondary userSecondary = userMapperSecondary.findByName(\"AAA\");\n        Assert.assertNull(userSecondary);\n\n        // 往Secondary数据源插入一条数据\n        userMapperSecondary.insert(\"BBB\", 20);\n\n        // 从Primary数据源查询刚才插入的数据，配置正确应该是查询不到的\n        userPrimary = userMapperPrimary.findByName(\"BBB\");\n        Assert.assertNull(userPrimary);\n\n        // 从Secondary数据源查询刚才插入的数据，配置正确就可以查询到\n        userSecondary = userMapperSecondary.findByName(\"BBB\");\n        Assert.assertEquals(20, userSecondary.getAge().intValue());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter4-1/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter4-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter4-1</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用 Thymeleaf开发Web页面</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter4-1/src/main/java/com/didispace/chapter41/Chapter41Application.java",
    "content": "package com.didispace.chapter41;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter41Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter41Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter4-1/src/main/java/com/didispace/chapter41/HelloController.java",
    "content": "package com.didispace.chapter41;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.ModelMap;\nimport org.springframework.web.bind.annotation.GetMapping;\n\n@Controller\npublic class HelloController {\n\n    @GetMapping(\"/\")\n    public String index(ModelMap map) {\n        // 加入一个属性，用来在模板中读取\n        map.addAttribute(\"host\", \"http://blog.didispace.com\");\n\n        // return模板文件的名称，对应src/main/resources/templates/index.html\n        return \"index\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter4-1/src/main/resources/application.properties",
    "content": "\n"
  },
  {
    "path": "2.x/chapter4-1/src/main/resources/templates/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title></title>\n</head>\n<body>\n<h1 th:text=\"${host}\">Hello World</h1>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter4-2/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter4-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter4-2</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用 ECharts 绘制折线图 </description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter4-2/src/main/java/com/didispace/chapter42/Chapter42Application.java",
    "content": "package com.didispace.chapter42;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter42Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter42Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter4-2/src/main/java/com/didispace/chapter42/HelloController.java",
    "content": "package com.didispace.chapter42;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.ModelMap;\nimport org.springframework.web.bind.annotation.GetMapping;\n\n@Controller\npublic class HelloController {\n\n    @GetMapping(\"/\")\n    public String index(ModelMap map) {\n        // return模板文件的名称，对应src/main/resources/templates/index.html\n        return \"index\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter4-2/src/main/resources/application.properties",
    "content": "\n"
  },
  {
    "path": "2.x/chapter4-2/src/main/resources/templates/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title>Spring Boot中使用ECharts</title>\n    <script src=\"https://cdn.bootcss.com/echarts/4.6.0/echarts.min.js\"></script>\n</head>\n<body>\n<div id=\"main\" style=\"width: 1000px;height:400px;\"></div>\n</body>\n\n<script type=\"text/javascript\">\n    let myChart = echarts.init(document.getElementById('main'));\n    let option = {\n        title: {\n            text: 'Spring Boot中使用ECharts'\n        },\n        tooltip: {},\n        xAxis: {\n            data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']\n        },\n        yAxis: {},\n        series: [{\n            data: [820, 932, 901, 934, 1290, 1330, 1320],\n            type: 'line'\n        }]\n    };\n    myChart.setOption(option);\n</script>\n</html>"
  },
  {
    "path": "2.x/chapter4-3/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter4-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter4-3</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>文件上传</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter4-3/src/main/java/com/didispace/chapter43/Chapter43Application.java",
    "content": "package com.didispace.chapter43;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter43Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter43Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter4-3/src/main/java/com/didispace/chapter43/UploadController.java",
    "content": "package com.didispace.chapter43;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestPart;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.Files;\n\n@Controller\n@Slf4j\npublic class UploadController {\n\n    @Value(\"${file.upload.path}\")\n    private String path;\n\n    @GetMapping(\"/\")\n    public String uploadPage() {\n        return \"upload\";\n    }\n\n    @PostMapping(\"/upload\")\n    @ResponseBody\n    public String create(@RequestPart MultipartFile file) throws IOException {\n        String fileName = file.getOriginalFilename();\n        String filePath = path + fileName;\n\n        File dest = new File(filePath);\n        Files.copy(file.getInputStream(), dest.toPath());\n        return \"Upload file success : \" + dest.getAbsolutePath();\n    }\n\n}"
  },
  {
    "path": "2.x/chapter4-3/src/main/resources/application.properties",
    "content": "\nspring.servlet.multipart.max-file-size=2MB\nspring.servlet.multipart.max-request-size=2MB\n\nfile.upload.path=/Users/zhaiyongchao/"
  },
  {
    "path": "2.x/chapter4-3/src/main/resources/templates/upload.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title>文件上传页面</title>\n</head>\n<body>\n<h1>文件上传页面</h1>\n<form method=\"post\" action=\"/upload\" enctype=\"multipart/form-data\">\n    选择要上传的文件：<input type=\"file\" name=\"file\"><br>\n    <hr>\n    <input type=\"submit\" value=\"提交\">\n</form>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter4-3/src/test/java/FileTest.java",
    "content": "import com.didispace.chapter43.Chapter43Application;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.mock.web.MockMultipartFile;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.MvcResult;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\nimport org.springframework.web.context.WebApplicationContext;\n\nimport static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n\n@SpringBootTest(classes = Chapter43Application.class)\npublic class FileTest {\n\n    @Autowired\n    protected WebApplicationContext context;\n    protected MockMvc mvc;\n\n    @BeforeEach\n    public void setUp() {\n        mvc = MockMvcBuilders.webAppContextSetup(context).build();\n    }\n\n    @Test\n    public void uploadFile() throws Exception {\n        MockMultipartFile file = new MockMultipartFile(\n                \"file\",\n                \"hello.txt\",\n                MediaType.TEXT_PLAIN_VALUE,\n                \"Hello, World!\".getBytes()\n        );\n\n        final MvcResult result = mvc.perform(\n                MockMvcRequestBuilders\n                        .multipart(\"/upload\")\n                        .file(file))\n                .andDo(print())\n                .andExpect(status().isOk())\n                .andReturn();\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter4-4/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter4-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter4-4</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>多文件上传</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter4-4/src/main/java/com/didispace/chapter44/Chapter44Application.java",
    "content": "package com.didispace.chapter44;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter44Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter44Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter4-4/src/main/java/com/didispace/chapter44/UploadController.java",
    "content": "package com.didispace.chapter44;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestPart;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.Files;\n\n@Controller\n@Slf4j\npublic class UploadController {\n\n    @Value(\"${file.upload.path}\")\n    private String path;\n\n    @GetMapping(\"/\")\n    public String uploadPage() {\n        return \"upload\";\n    }\n\n    @PostMapping(\"/upload\")\n    @ResponseBody\n    public String create(@RequestPart MultipartFile[] files) throws IOException {\n        StringBuffer message = new StringBuffer();\n\n        for (MultipartFile file : files) {\n            String fileName = file.getOriginalFilename();\n            String filePath = path + fileName;\n\n            File dest = new File(filePath);\n            Files.copy(file.getInputStream(), dest.toPath());\n            message.append(\"Upload file success : \" + dest.getAbsolutePath()).append(\"<br>\");\n        }\n        return message.toString();\n    }\n\n}"
  },
  {
    "path": "2.x/chapter4-4/src/main/resources/application.properties",
    "content": "\nspring.servlet.multipart.max-file-size=2MB\nspring.servlet.multipart.max-request-size=2MB\n\nfile.upload.path=/Users/didi/"
  },
  {
    "path": "2.x/chapter4-4/src/main/resources/templates/upload.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\" />\n    <title>文件上传页面</title>\n</head>\n<body>\n<h1>文件上传页面</h1>\n<form method=\"post\" action=\"/upload\" enctype=\"multipart/form-data\">\n    文件1：<input type=\"file\" name=\"files\"><br>\n    文件2：<input type=\"file\" name=\"files\"><br>\n    <hr>\n    <input type=\"submit\" value=\"提交\">\n</form>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter4-4/src/test/java/FileTest.java",
    "content": "import org.junit.jupiter.api.Test;\n\npublic class FileTest {\n\n    @Test\n    public void uploadFile() throws Exception {\n\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter4-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.5.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter4-5</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>Spring Security快速入门</description>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-security</artifactId>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "2.x/chapter4-5/src/main/java/com/didispace/chapter45/Application.java",
    "content": "package com.didispace.chapter45;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(Application.class, args);\n\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter4-5/src/main/java/com/didispace/chapter45/HelloController.java",
    "content": "package com.didispace.chapter45;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.ModelMap;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\n\n/**\n *\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n *\n */\n@Controller\npublic class HelloController {\n\n    @RequestMapping(\"/\")\n    public String index() {\n        return \"index\";\n    }\n\n    @RequestMapping(\"/hello\")\n    public String hello() {\n        return \"hello\";\n    }\n\n    @RequestMapping(value = \"/login\", method = RequestMethod.GET)\n    public String login() {\n        return \"login\";\n    }\n\n}"
  },
  {
    "path": "2.x/chapter4-5/src/main/java/com/didispace/chapter45/WebSecurityConfig.java",
    "content": "package com.didispace.chapter45;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\n\n@Configuration\n@EnableWebSecurity\npublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http\n            .authorizeRequests()\n                .antMatchers(\"/\", \"/home\").permitAll()\n                .anyRequest().authenticated()\n                .and()\n            .formLogin()\n                .loginPage(\"/login\")\n                .permitAll()\n                .and()\n            .logout()\n                .permitAll();\n    }\n\n    @Autowired\n    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {\n        auth\n            .inMemoryAuthentication()\n                .withUser(\"user\").password(\"password\").roles(\"USER\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter4-5/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "2.x/chapter4-5/src/main/resources/templates/hello.html",
    "content": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.thymeleaf.org\"\n      xmlns:sec=\"http://www.thymeleaf.org/thymeleaf-extras-springsecurity3\">\n<head>\n    <title>Hello World!</title>\n</head>\n<body>\n<h1 th:inline=\"text\">Hello [[${#httpServletRequest.remoteUser}]]!</h1>\n<form th:action=\"@{/logout}\" method=\"post\">\n    <input type=\"submit\" value=\"注销\"/>\n</form>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter4-5/src/main/resources/templates/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.thymeleaf.org\"\n      xmlns:sec=\"http://www.thymeleaf.org/thymeleaf-extras-springsecurity3\">\n<head>\n    <title>Spring Security入门</title>\n</head>\n<body>\n<h1>欢迎使用Spring Security!</h1>\n\n<p>点击 <a th:href=\"@{/hello}\">这里</a> 打个招呼吧</p>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter4-5/src/main/resources/templates/login.html",
    "content": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\"\n      xmlns:th=\"http://www.thymeleaf.org\"\n      xmlns:sec=\"http://www.thymeleaf.org/thymeleaf-extras-springsecurity3\">\n<head>\n    <title>Spring Security Example </title>\n</head>\n<body>\n<div th:if=\"${param.error}\">\n    用户名或密码错\n</div>\n<div th:if=\"${param.logout}\">\n    您已注销成功\n</div>\n<form th:action=\"@{/login}\" method=\"post\">\n    <div><label> 用户名 : <input type=\"text\" name=\"username\"/> </label></div>\n    <div><label> 密 码 : <input type=\"password\" name=\"password\"/> </label></div>\n    <div><input type=\"submit\" value=\"登录\"/></div>\n</form>\n</body>\n</html>"
  },
  {
    "path": "2.x/chapter5-1/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter5-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter5-1</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用进程内缓存</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-cache</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter5-1/src/main/java/com/didispace/chapter51/Chapter51Application.java",
    "content": "package com.didispace.chapter51;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\n\n@EnableCaching\n@SpringBootApplication\npublic class Chapter51Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter51Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter5-1/src/main/java/com/didispace/chapter51/User.java",
    "content": "package com.didispace.chapter51;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter5-1/src/main/java/com/didispace/chapter51/UserRepository.java",
    "content": "package com.didispace.chapter51;\n\nimport org.springframework.cache.annotation.CacheConfig;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/7/13.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\n@CacheConfig(cacheNames = \"users\")\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    @Cacheable\n    User findByName(String name);\n\n    User findByNameAndAge(String name, Integer age);\n\n    @Query(\"from User u where u.name=:name\")\n    User findUser(@Param(\"name\") String name);\n\n}\n"
  },
  {
    "path": "2.x/chapter5-1/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nspring.jpa.show-sql=true\nspring.jpa.hibernate.ddl-auto=create-drop"
  },
  {
    "path": "2.x/chapter5-1/src/test/java/com/didispace/chapter51/Chapter51ApplicationTests.java",
    "content": "package com.didispace.chapter51;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter51ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Autowired\n    private CacheManager cacheManager;\n\n    @Test\n    public void test() throws Exception {\n        // 创建1条记录\n        userRepository.save(new User(\"AAA\", 10));\n\n        User u1 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第一次查询：\" + u1.getAge());\n\n        User u2 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第二次查询：\" + u2.getAge());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter5-2/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter5-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter5-2</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用进程内缓存 EhCache</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-cache</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>net.sf.ehcache</groupId>\n\t\t\t<artifactId>ehcache</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter5-2/src/main/java/com/didispace/chapter52/Chapter52Application.java",
    "content": "package com.didispace.chapter52;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\n\n@EnableCaching\n@SpringBootApplication\npublic class Chapter52Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter52Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter5-2/src/main/java/com/didispace/chapter52/User.java",
    "content": "package com.didispace.chapter52;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class User {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter5-2/src/main/java/com/didispace/chapter52/UserRepository.java",
    "content": "package com.didispace.chapter52;\n\nimport org.springframework.cache.annotation.CacheConfig;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/7/14.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\n@CacheConfig(cacheNames = \"users\")\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    @Cacheable\n    User findByName(String name);\n\n}\n"
  },
  {
    "path": "2.x/chapter5-2/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nspring.jpa.show-sql=true\nspring.jpa.hibernate.ddl-auto=create-drop"
  },
  {
    "path": "2.x/chapter5-2/src/main/resources/ehcache.xml",
    "content": "<ehcache xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"ehcache.xsd\">\n\n    <cache name=\"users\"\n           maxEntriesLocalHeap=\"200\"\n           timeToLiveSeconds=\"600\">\n    </cache>\n\n</ehcache>"
  },
  {
    "path": "2.x/chapter5-2/src/test/java/com/didispace/chapter52/Chapter52ApplicationTests.java",
    "content": "package com.didispace.chapter52;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter52ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Autowired\n    private CacheManager cacheManager;\n\n    @Test\n    public void test() throws Exception {\n        System.out.println(\"CacheManager type : \" + cacheManager.getClass());\n\n        // 创建1条记录\n        userRepository.save(new User(\"AAA\", 10));\n\n        User u1 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第一次查询：\" + u1.getAge());\n\n        User u2 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第二次查询：\" + u2.getAge());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter5-3/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter5-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter5-3</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用EhCache缓存集群</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-cache</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>net.sf.ehcache</groupId>\n\t\t\t<artifactId>ehcache</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter5-3/src/main/java/com/didispace/chapter53/Chapter53Application.java",
    "content": "package com.didispace.chapter53;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.rmi.registry.LocateRegistry;\n\n@EnableCaching\n@SpringBootApplication\npublic class Chapter53Application {\n\n\tpublic static void main(String[] args) throws Exception {\n//\t\tLocateRegistry.createRegistry(Integer.valueOf(System.getProperty(\"rmi.port\")));\n\t\tSpringApplication.run(Chapter53Application.class, args);\n\t}\n\n\t@RestController\n\tstatic class HelloController {\n\n\t\t@Autowired\n\t\tprivate UserRepository userRepository;\n\n\t\t@GetMapping(\"/create\")\n\t\tpublic void create() {\n\t\t\tuserRepository.save(new User(\"AAA\", 10));\n\t\t}\n\n\t\t@GetMapping(\"/update\")\n\t\tpublic User update() {\n\t\t\tUser u1 = userRepository.findByName(\"AAA\");\n\t\t\tu1.setAge(20);\n\t\t\tu1 = userRepository.save(u1);\n\t\t\treturn u1;\n\t\t}\n\n\t\t@GetMapping(\"/find\")\n\t\tpublic User find() {\n\t\t\tUser u1 = userRepository.findByName(\"AAA\");\n\t\t\tSystem.out.println(\"查询AAA用户：\" + u1.getAge());\n\t\t\treturn u1;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter5-3/src/main/java/com/didispace/chapter53/User.java",
    "content": "package com.didispace.chapter53;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport java.io.Serializable;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class User implements Serializable {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}\n"
  },
  {
    "path": "2.x/chapter5-3/src/main/java/com/didispace/chapter53/UserRepository.java",
    "content": "package com.didispace.chapter53;\n\nimport org.springframework.cache.annotation.CacheConfig;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/7/16.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\n@CacheConfig(cacheNames = \"users\")\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    @Cacheable\n    User findByName(String name);\n\n}\n"
  },
  {
    "path": "2.x/chapter5-3/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nspring.jpa.show-sql=true\nspring.jpa.hibernate.ddl-auto=create\n\n#logging.level.net.sf.ehcache=debug\n\n# 不同实例的配置\n#spring.cache.ehcache.config=classpath:ehcache-1.xml\n#spring.cache.ehcache.config=classpath:ehcache-2.xml\n\n# 用不同命令启动不同实例\n#-Dserver.port=8001 -Dspring.cache.ehcache.config=classpath:ehcache-1.xml\n#-Dserver.port=8002 -Dspring.cache.ehcache.config=classpath:ehcache-2.xml\n"
  },
  {
    "path": "2.x/chapter5-3/src/main/resources/ehcache-1.xml",
    "content": "<ehcache xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"ehcache.xsd\">\n\n    <defaultCache maxElementsInMemory=\"10000\" eternal=\"false\" timeToIdleSeconds=\"600\" timeToLiveSeconds=\"600\" overflowToDisk=\"true\" />\n\n    <cache name=\"users\"\n           maxEntriesLocalHeap=\"200\"\n           timeToLiveSeconds=\"600\">\n        <cacheEventListenerFactory\n                class=\"net.sf.ehcache.distribution.RMICacheReplicatorFactory\"\n                properties=\"replicateAsynchronously=true,\n            replicatePuts=true,\n            replicateUpdates=true,\n            replicateUpdatesViaCopy=false,\n            replicateRemovals=true \"/>\n\n        <bootstrapCacheLoaderFactory class=\"net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory\"\n                                     properties=\"bootstrapAsynchronously=true\" />\n    </cache>\n\n    <cacheManagerPeerProviderFactory\n            class=\"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory\"\n            properties=\"hostName=10.10.0.101,\n                        port=40001,\n                        socketTimeoutMillis=2000,\n                        peerDiscovery=manual,\n                        rmiUrls=//10.10.0.102:40001/users\" />\n\n</ehcache>"
  },
  {
    "path": "2.x/chapter5-3/src/main/resources/ehcache-2.xml",
    "content": "<ehcache xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"ehcache.xsd\">\n\n    <defaultCache maxElementsInMemory=\"10000\" eternal=\"false\" timeToIdleSeconds=\"600\" timeToLiveSeconds=\"600\" overflowToDisk=\"true\" />\n\n    <cache name=\"users\"\n           maxEntriesLocalHeap=\"200\"\n           timeToLiveSeconds=\"600\">\n        <cacheEventListenerFactory\n                class=\"net.sf.ehcache.distribution.RMICacheReplicatorFactory\"\n                properties=\"replicateAsynchronously=true,\n            replicatePuts=true,\n            replicateUpdates=true,\n            replicateUpdatesViaCopy=false,\n            replicateRemovals=true \"/>\n\n        <bootstrapCacheLoaderFactory class=\"net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory\"\n                                     properties=\"bootstrapAsynchronously=true\" />\n    </cache>\n\n    <cacheManagerPeerProviderFactory\n            class=\"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory\"\n            properties=\"hostName=10.10.0.102,\n                        port=40001,\n                        socketTimeoutMillis=2000,\n                        peerDiscovery=manual,\n                        rmiUrls=//10.10.0.101:40001/users\" />\n\n</ehcache>"
  },
  {
    "path": "2.x/chapter5-3/src/test/java/com/didispace/chapter53/Chapter53ApplicationTests.java",
    "content": "package com.didispace.chapter53;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter53ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Autowired\n    private CacheManager cacheManager;\n\n    @Test\n    public void test() throws Exception {\n        System.out.println(\"CacheManager type : \" + cacheManager.getClass());\n\n        // 创建1条记录\n        userRepository.save(new User(\"AAA\", 10));\n\n        User u1 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第一次查询：\" + u1.getAge());\n\n        User u2 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第二次查询：\" + u2.getAge());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter5-4/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter5-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.1.3.RELEASE</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter5-4</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用集中式缓存Redis</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-jpa</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-redis</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-pool2</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>mysql</groupId>\n\t\t\t<artifactId>mysql-connector-java</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter5-4/src/main/java/com/didispace/chapter54/Chapter54Application.java",
    "content": "package com.didispace.chapter54;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\n\n@EnableCaching\n@SpringBootApplication\npublic class Chapter54Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter54Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter5-4/src/main/java/com/didispace/chapter54/User.java",
    "content": "package com.didispace.chapter54;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport java.io.Serializable;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class User implements Serializable {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public User(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter5-4/src/main/java/com/didispace/chapter54/UserRepository.java",
    "content": "package com.didispace.chapter54;\n\nimport org.springframework.cache.annotation.CacheConfig;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2020/7/26.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\n@CacheConfig(cacheNames = \"users\")\npublic interface UserRepository extends JpaRepository<User, Long> {\n\n    @Cacheable\n    User findByName(String name);\n\n    User findByNameAndAge(String name, Integer age);\n\n    @Query(\"from User u where u.name=:name\")\n    User findUser(@Param(\"name\") String name);\n\n}\n"
  },
  {
    "path": "2.x/chapter5-4/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:mysql://localhost:3306/test\nspring.datasource.username=root\nspring.datasource.password=12345678\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n\nspring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect\nspring.jpa.show-sql=true\nspring.jpa.hibernate.ddl-auto=create-drop\n\nspring.redis.host=localhost\nspring.redis.port=6379\nspring.redis.lettuce.pool.max-idle=8\nspring.redis.lettuce.pool.max-active=8\nspring.redis.lettuce.pool.max-wait=-1ms\nspring.redis.lettuce.pool.min-idle=0\nspring.redis.lettuce.shutdown-timeout=100ms\n"
  },
  {
    "path": "2.x/chapter5-4/src/test/java/com/didispace/chapter54/Chapter54ApplicationTests.java",
    "content": "package com.didispace.chapter54;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@Slf4j\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class Chapter54ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Autowired\n    private CacheManager cacheManager;\n\n    @Test\n    public void test() throws Exception {\n        System.out.println(\"CacheManager type : \" + cacheManager.getClass());\n\n        // 创建1条记录\n        userRepository.save(new User(\"AAA\", 10));\n\n        User u1 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第一次查询：\" + u1.getAge());\n\n        User u2 = userRepository.findByName(\"AAA\");\n        System.out.println(\"第二次查询：\" + u2.getAge());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter5-5/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "2.x/chapter5-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.5.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter5-5</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用Redis的发布订阅</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-redis</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-pool2</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-actuator</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter5-5/src/main/java/com/didispace/chapter55/Chapter55Application.java",
    "content": "package com.didispace.chapter55;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.data.redis.connection.Message;\nimport org.springframework.data.redis.connection.MessageListener;\nimport org.springframework.data.redis.connection.RedisConnection;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.nio.charset.StandardCharsets;\n\n@SpringBootApplication\npublic class Chapter55Application {\n\n    private static String CHANNEL = \"didispace\";\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter55Application.class, args);\n    }\n\n    @RestController\n    static class RedisController {\n\n        private RedisTemplate<String, String> redisTemplate;\n\n        public RedisController(RedisTemplate<String, String> redisTemplate) {\n            this.redisTemplate = redisTemplate;\n        }\n\n        @GetMapping(\"/publish\")\n        public void publish(@RequestParam String message) {\n            // 发送消息\n            redisTemplate.convertAndSend(CHANNEL, message);\n        }\n\n    }\n\n    @Slf4j\n    @Service\n    static class MessageSubscriber {\n\n        public MessageSubscriber(RedisTemplate redisTemplate) {\n            RedisConnection redisConnection = redisTemplate.getConnectionFactory().getConnection();\n            redisConnection.subscribe(new MessageListener() {\n                @Override\n                public void onMessage(Message message, byte[] bytes) {\n                    // 收到消息的处理逻辑\n                    log.info(\"Receive message : \" + message);\n                }\n            }, CHANNEL.getBytes(StandardCharsets.UTF_8));\n\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter5-5/src/main/resources/application.properties",
    "content": "spring.redis.host=localhost\nspring.redis.port=6379\nspring.redis.lettuce.pool.max-idle=8\nspring.redis.lettuce.pool.max-active=8\nspring.redis.lettuce.pool.max-wait=-1ms\nspring.redis.lettuce.pool.min-idle=0\nspring.redis.lettuce.shutdown-timeout=100ms\n"
  },
  {
    "path": "2.x/chapter6-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.4.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter6-1</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用MongoDB</description>\n\n\t<properties>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-mongodb</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter6-1/src/main/java/com/didispace/chapter61/Chapter61Application.java",
    "content": "package com.didispace.chapter61;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter61Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter61Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter6-1/src/main/java/com/didispace/chapter61/User.java",
    "content": "package com.didispace.chapter61;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport org.springframework.data.annotation.Id;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\n@Data\n@AllArgsConstructor\npublic class User {\n\n    @Id\n    private Long id;\n\n    private String username;\n    private Integer age;\n\n}\n"
  },
  {
    "path": "2.x/chapter6-1/src/main/java/com/didispace/chapter61/UserRepository.java",
    "content": "package com.didispace.chapter61;\n\nimport org.springframework.data.mongodb.repository.MongoRepository;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog http://blog.didispace.com\n */\npublic interface UserRepository extends MongoRepository<User, Long> {\n\n    User findByUsername(String username);\n\n}\n"
  },
  {
    "path": "2.x/chapter6-1/src/main/resources/application.properties",
    "content": "spring.data.mongodb.uri=mongodb://localhost:27017/test\n\n\n"
  },
  {
    "path": "2.x/chapter6-1/src/test/java/com/didispace/chapter61/ApplicationTests.java",
    "content": "package com.didispace.chapter61;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest(classes = Chapter61Application.class)\npublic class ApplicationTests {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Test\n    public void test() throws Exception {\n        userRepository.deleteAll();\n\n        // 创建三个User，并验证User总数\n        userRepository.save(new User(1L, \"didi\", 30));\n        userRepository.save(new User(2L, \"mama\", 40));\n        userRepository.save(new User(3L, \"kaka\", 50));\n        Assertions.assertEquals(3, userRepository.findAll().size());\n\n        // 删除一个User，再验证User总数\n        User u = userRepository.findById(1L).get();\n        userRepository.delete(u);\n        Assertions.assertEquals(2, userRepository.findAll().size());\n\n        // 删除一个User，再验证User总数\n        u = userRepository.findByUsername(\"mama\");\n        userRepository.delete(u);\n        Assertions.assertEquals(1, userRepository.findAll().size());\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter6-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter6-2</artifactId>\n\t<version>1.0.0</version>\n\t<packaging>jar</packaging>\n\t<description>使用轻量级树状存储 LDAP</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.5.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-ldap</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.unboundid</groupId>\n\t\t\t<artifactId>unboundid-ldapsdk</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "2.x/chapter6-2/src/main/java/com/didispace/chapter62/Chapter62Application.java",
    "content": "package com.didispace.chapter62;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter62Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter62Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter6-2/src/main/java/com/didispace/chapter62/Person.java",
    "content": "package com.didispace.chapter62;\n\nimport lombok.Data;\nimport org.springframework.ldap.odm.annotations.*;\n\nimport javax.naming.Name;\n\n@Entry(base = \"ou=people,dc=didispace,dc=com\", objectClasses = \"inetOrgPerson\")\n@Data\npublic class Person {\n\n    @Id\n    private Name id;\n    @DnAttribute(value = \"uid\", index = 3)\n    private String uid;\n    @Attribute(name = \"cn\")\n    private String commonName;\n    @Attribute(name = \"sn\")\n    private String userName;\n    private String userPassword;\n\n}\n"
  },
  {
    "path": "2.x/chapter6-2/src/main/java/com/didispace/chapter62/PersonRepository.java",
    "content": "package com.didispace.chapter62;\n\nimport org.springframework.data.repository.CrudRepository;\n\nimport javax.naming.Name;\n\npublic interface PersonRepository extends CrudRepository<Person, Name> {\n\n\n}"
  },
  {
    "path": "2.x/chapter6-2/src/main/resources/application.properties",
    "content": "#spring.ldap.urls=ldap://localhost:1235\n#spring.ldap.base=dc=didispace,dc=com\n#spring.ldap.username=didispace\n#spring.ldap.password=123456\n"
  },
  {
    "path": "2.x/chapter6-2/src/test/java/com/didispace/chapter62/ApplicationTests.java",
    "content": "package com.didispace.chapter62;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@Slf4j\n@SpringBootTest\npublic class ApplicationTests {\n\n    @Autowired\n    private PersonRepository personRepository;\n\n    @Test\n    public void findAll() {\n\n        personRepository.findAll().forEach(p -> {\n            System.out.println(p);\n        });\n\n    }\n\n    @Test\n    public void save() {\n        Person person = new Person();\n        person.setUid(\"uid:1\");\n        person.setUserName(\"AAA\");\n        person.setCommonName(\"aaa\");\n        person.setUserPassword(\"123456\");\n        personRepository.save(person);\n\n        personRepository.findAll().forEach(p -> {\n            System.out.println(p);\n        });\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter6-2/src/test/resources/application.properties",
    "content": "spring.ldap.embedded.ldif=classpath:ldap-server.ldif\nspring.ldap.embedded.base-dn=dc=didispace,dc=com\n\n"
  },
  {
    "path": "2.x/chapter6-2/src/test/resources/ldap-server.ldif",
    "content": "dn: dc=didispace,dc=com\nobjectClass: top\nobjectClass: domain\nobjectclass: extensibleObject\ndc: didispace\n\ndn: ou=people,dc=didispace,dc=com\nobjectclass: top\nobjectclass: organizationalUnit\nou: people\n\ndn: uid=ben,ou=people,dc=didispace,dc=com\nobjectclass: top\nobjectclass: person\nobjectclass: organizationalPerson\nobjectclass: inetOrgPerson\ncn: didi\nsn: zhaiyongchao\nuid: didi\nuserPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=\n"
  },
  {
    "path": "2.x/chapter6-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter6-3</artifactId>\n    <version>1.0.0</version>\n    <packaging>jar</packaging>\n    <description>使用时序数据库InfluxDB</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.influxdb</groupId>\n            <artifactId>influxdb-java</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "2.x/chapter6-3/src/main/java/com/didispace/chapter63/Chapter63Application.java",
    "content": "package com.didispace.chapter63;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n@EnableScheduling\n@SpringBootApplication\npublic class Chapter63Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Chapter63Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "2.x/chapter6-3/src/main/java/com/didispace/chapter63/Monitor.java",
    "content": "package com.didispace.chapter63;\n\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.influxdb.InfluxDB;\nimport org.influxdb.dto.Point;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Random;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by 程序猿DD on 2021/8/2.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\n@Service\n@AllArgsConstructor\n@Slf4j\npublic class Monitor {\n\n    private InfluxDB influxDB;\n\n    @Scheduled(fixedRate = 5000)\n    public void writeQPS() {\n        // 模拟要上报的统计数据\n        int count = (int) (Math.random() * 100);\n\n        Point point = Point.measurement(\"ApiQPS\")     // ApiQPS表\n                .tag(\"url\", \"/hello\")  // url字段\n                .addField(\"count\", count)        // 统计数据\n                .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)  // 时间\n                .build();\n\n        // 往test库写数据\n        influxDB.write(\"test\", \"autogen\", point);\n\n        log.info(\"上报统计数据：\" + count);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter6-3/src/main/resources/application.properties",
    "content": "\nspring.influx.url=http://localhost:8086\nspring.influx.user=admin\nspring.influx.password=\n\n"
  },
  {
    "path": "2.x/chapter6-3/src/test/java/com/didispace/chapter63/ApplicationTests.java",
    "content": "package com.didispace.chapter63;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@Slf4j\n@SpringBootTest\npublic class ApplicationTests {\n\n    @Test\n    public void findAll() {\n\n    }\n\n    @Test\n    public void save() {\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter6-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter6-4</artifactId>\n    <version>1.0.0</version>\n    <packaging>jar</packaging>\n    <description>使用PostgreSQL数据库</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-jpa</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.postgresql</groupId>\n            <artifactId>postgresql</artifactId>\n            <scope>runtime</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "2.x/chapter6-4/src/main/java/com/didispace/chapter64/Chapter64Application.java",
    "content": "package com.didispace.chapter64;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n@SpringBootApplication\npublic class Chapter64Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter64Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfo.java",
    "content": "package com.didispace.chapter64;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n@Entity\n@Data\n@NoArgsConstructor\npublic class UserInfo {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    private String name;\n    private Integer age;\n\n    public UserInfo(String name, Integer age) {\n        this.name = name;\n        this.age = age;\n    }\n}"
  },
  {
    "path": "2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfoRepository.java",
    "content": "package com.didispace.chapter64;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.query.Param;\n\n/**\n * Created by 程序猿DD/翟永超 on 2021/10/08.\n * <p>\n * Blog: http://blog.didispace.com/\n * Github: https://github.com/dyc87112/\n */\npublic interface UserInfoRepository extends JpaRepository<UserInfo, Long> {\n\n    UserInfo findByName(String name);\n\n    UserInfo findByNameAndAge(String name, Integer age);\n\n    @Query(\"from UserInfo u where u.name=:name\")\n    UserInfo findUser(@Param(\"name\") String name);\n\n}\n"
  },
  {
    "path": "2.x/chapter6-4/src/main/resources/application.properties",
    "content": "spring.datasource.url=jdbc:postgresql://localhost:5432/test\nspring.datasource.username=postgres\nspring.datasource.password=123456\nspring.datasource.driver-class-name=org.postgresql.Driver\n\nspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect\nspring.jpa.properties.hibernate.hbm2ddl.auto=create"
  },
  {
    "path": "2.x/chapter6-4/src/test/java/com/didispace/chapter64/ApplicationTests.java",
    "content": "package com.didispace.chapter64;\n\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@Slf4j\n@SpringBootTest\npublic class ApplicationTests {\n\n    @Autowired\n    private UserInfoRepository userRepository;\n\n    @Test\n    public void test() throws Exception {\n        // 创建10条记录\n        userRepository.save(new UserInfo(\"AAA\", 10));\n        userRepository.save(new UserInfo(\"BBB\", 20));\n        userRepository.save(new UserInfo(\"CCC\", 30));\n        userRepository.save(new UserInfo(\"DDD\", 40));\n        userRepository.save(new UserInfo(\"EEE\", 50));\n        userRepository.save(new UserInfo(\"FFF\", 60));\n        userRepository.save(new UserInfo(\"GGG\", 70));\n        userRepository.save(new UserInfo(\"HHH\", 80));\n        userRepository.save(new UserInfo(\"III\", 90));\n        userRepository.save(new UserInfo(\"JJJ\", 100));\n\n        // 测试findAll, 查询所有记录\n        Assertions.assertEquals(10, userRepository.findAll().size());\n\n        // 测试findByName, 查询姓名为FFF的User\n        Assertions.assertEquals(60, userRepository.findByName(\"FFF\").getAge().longValue());\n\n        // 测试findUser, 查询姓名为FFF的User\n        Assertions.assertEquals(60, userRepository.findUser(\"FFF\").getAge().longValue());\n\n        // 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的User\n        Assertions.assertEquals(\"FFF\", userRepository.findByNameAndAge(\"FFF\", 60).getName());\n\n        // 测试删除姓名为AAA的User\n        userRepository.delete(userRepository.findByName(\"AAA\"));\n\n        // 测试findAll, 查询所有记录, 验证上面的删除是否成功\n        Assertions.assertEquals(9, userRepository.findAll().size());\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-1</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>使用@Scheduled实现定时任务</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-1/src/main/java/com/didispace/chapter71/Chapter71Application.java",
    "content": "package com.didispace.chapter71;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n@EnableScheduling\n@SpringBootApplication\npublic class Chapter71Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter71Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-1/src/main/java/com/didispace/chapter71/ScheduledTasks.java",
    "content": "package com.didispace.chapter71;\n\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n@Slf4j\n@Component\n@AllArgsConstructor\npublic class ScheduledTasks {\n\n    private static final SimpleDateFormat dateFormat = new SimpleDateFormat(\"HH:mm:ss\");\n\n\n    @Scheduled(fixedRate = 5000)\n    public void reportCurrentTime() {\n        log.info(\"现在时间：\" + dateFormat.format(new Date()));\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-1/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "2.x/chapter7-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-2</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>使用Elastic Job实现定时任务</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.apache.shardingsphere.elasticjob</groupId>\n            <artifactId>elasticjob-lite-spring-boot-starter</artifactId>\n            <version>3.0.0</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-2/src/main/java/com/didispace/chapter72/Chapter72Application.java",
    "content": "package com.didispace.chapter72;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter72Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter72Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-2/src/main/java/com/didispace/chapter72/MySimpleJob.java",
    "content": "package com.didispace.chapter72;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.shardingsphere.elasticjob.api.ShardingContext;\nimport org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;\nimport org.springframework.stereotype.Service;\n\n@Slf4j\n@Service\npublic class MySimpleJob implements SimpleJob {\n\n    @Override\n    public void execute(ShardingContext context) {\n        log.info(\"MySimpleJob start : didispace.com {}\", System.currentTimeMillis());\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-2/src/main/resources/application.properties",
    "content": "\nelasticjob.reg-center.server-lists=localhost:2181\nelasticjob.reg-center.namespace=didispace\n\nelasticjob.jobs.my-simple-job.elastic-job-class=com.didispace.chapter72.MySimpleJob\nelasticjob.jobs.my-simple-job.cron=0/5 * * * * ?\nelasticjob.jobs.my-simple-job.sharding-total-count=1\n"
  },
  {
    "path": "2.x/chapter7-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-3</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>使用Elastic Job的分片配置</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.apache.shardingsphere.elasticjob</groupId>\n            <artifactId>elasticjob-lite-spring-boot-starter</artifactId>\n            <version>3.0.0</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-3/src/main/java/com/didispace/chapter73/Chapter73Application.java",
    "content": "package com.didispace.chapter73;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter73Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter73Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-3/src/main/java/com/didispace/chapter73/MyShardingJob.java",
    "content": "package com.didispace.chapter73;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.shardingsphere.elasticjob.api.ShardingContext;\nimport org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;\nimport org.springframework.stereotype.Service;\n\n@Slf4j\n@Service\npublic class MyShardingJob implements SimpleJob {\n\n    @Override\n    public void execute(ShardingContext context) {\n        // sharding-total-count=3，所以任务被分为三个分片\n        switch (context.getShardingItem()) {\n            case 0:\n                log.info(\"分片1：执行任务\");\n                break;\n            case 1:\n                log.info(\"分片2：执行任务\");\n                break;\n            case 2:\n                log.info(\"分片3：执行任务\");\n                break;\n        }\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-3/src/main/resources/application.properties",
    "content": "elasticjob.reg-center.server-lists=localhost:2181\nelasticjob.reg-center.namespace=didispace\n\nelasticjob.jobs.my-sharding-job.elastic-job-class=com.didispace.chapter73.MyShardingJob\nelasticjob.jobs.my-sharding-job.cron=0/5 * * * * ?\nelasticjob.jobs.my-sharding-job.sharding-total-count=3\n"
  },
  {
    "path": "2.x/chapter7-4/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-4</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>Elastic Job的错误处理策略</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.apache.shardingsphere.elasticjob</groupId>\n            <artifactId>elasticjob-lite-spring-boot-starter</artifactId>\n            <version>3.0.0</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-4/src/main/java/com/didispace/chapter74/Chapter74Application.java",
    "content": "package com.didispace.chapter74;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class Chapter74Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter74Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-4/src/main/java/com/didispace/chapter74/MySimpleJob.java",
    "content": "package com.didispace.chapter74;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.shardingsphere.elasticjob.api.ShardingContext;\nimport org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;\nimport org.springframework.stereotype.Service;\n\n@Slf4j\n@Service\npublic class MySimpleJob implements SimpleJob {\n\n    @Override\n    public void execute(ShardingContext context) {\n        log.info(\"MySimpleJob start : didispace.com {}\", System.currentTimeMillis());\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-4/src/main/resources/application.properties",
    "content": "spring.application.name=chapter74\n\nelasticjob.reg-center.server-lists=localhost:2181\nelasticjob.reg-center.namespace=${spring.application.name}\n\nelasticjob.jobs.my-simple-job.elastic-job-class=com.didispace.chapter74.MySimpleJob\nelasticjob.jobs.my-simple-job.cron=0/5 * * * * ?\nelasticjob.jobs.my-simple-job.sharding-total-count=1\n"
  },
  {
    "path": "2.x/chapter7-5/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-5</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>使用@Async实现异步任务</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-5/src/main/java/com/didispace/chapter75/AsyncTasks.java",
    "content": "package com.didispace.chapter75;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\nimport java.util.concurrent.CompletableFuture;\n\n@Slf4j\n@Component\npublic class AsyncTasks {\n\n    public static Random random = new Random();\n\n    @Async\n    public CompletableFuture<String> doTaskOne() throws Exception {\n        log.info(\"开始做任务一\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务一，耗时：\" + (end - start) + \"毫秒\");\n        return CompletableFuture.completedFuture(\"任务一完成\");\n    }\n\n    @Async\n    public CompletableFuture<String> doTaskTwo() throws Exception {\n        log.info(\"开始做任务二\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务二，耗时：\" + (end - start) + \"毫秒\");\n        return CompletableFuture.completedFuture(\"任务二完成\");\n    }\n\n    @Async\n    public CompletableFuture<String>  doTaskThree() throws Exception {\n        log.info(\"开始做任务三\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务三，耗时：\" + (end - start) + \"毫秒\");\n        return CompletableFuture.completedFuture(\"任务三完成\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-5/src/main/java/com/didispace/chapter75/Chapter75Application.java",
    "content": "package com.didispace.chapter75;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\n@EnableAsync\n@SpringBootApplication\npublic class Chapter75Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter75Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-5/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "2.x/chapter7-5/src/test/java/com/didispace/chapter75/Chapter75ApplicationTests.java",
    "content": "package com.didispace.chapter75;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.Future;\n\n@Slf4j\n@SpringBootTest\npublic class Chapter75ApplicationTests {\n\n    @Autowired\n    private AsyncTasks asyncTasks;\n\n    @Test\n    public void test() throws Exception {\n        long start = System.currentTimeMillis();\n\n        CompletableFuture<String> task1 = asyncTasks.doTaskOne();\n        CompletableFuture<String> task2 = asyncTasks.doTaskTwo();\n        CompletableFuture<String> task3 = asyncTasks.doTaskThree();\n\n        CompletableFuture.allOf(task1, task2, task3).join();\n\n        long end = System.currentTimeMillis();\n\n        log.info(\"任务全部完成，总耗时：\" + (end - start) + \"毫秒\");\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-6</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>@Async异步任务的线程池配置</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-6/src/main/java/com/didispace/chapter76/AsyncTasks.java",
    "content": "package com.didispace.chapter76;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.Future;\n\n@Slf4j\n@Component\npublic class AsyncTasks {\n\n    public static Random random = new Random();\n\n    @Async\n    public CompletableFuture<String> doTaskOne() throws Exception {\n        log.info(\"开始做任务一\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务一，耗时：\" + (end - start) + \"毫秒\");\n        return CompletableFuture.completedFuture(\"任务一完成\");\n    }\n\n    @Async\n    public CompletableFuture<String> doTaskTwo() throws Exception {\n        log.info(\"开始做任务二\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务二，耗时：\" + (end - start) + \"毫秒\");\n        return CompletableFuture.completedFuture(\"任务二完成\");\n    }\n\n    @Async\n    public CompletableFuture<String>  doTaskThree() throws Exception {\n        log.info(\"开始做任务三\");\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务三，耗时：\" + (end - start) + \"毫秒\");\n        return CompletableFuture.completedFuture(\"任务三完成\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-6/src/main/java/com/didispace/chapter76/Chapter76Application.java",
    "content": "package com.didispace.chapter76;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\n@EnableAsync\n@SpringBootApplication\npublic class Chapter76Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter76Application.class, args);\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-6/src/main/resources/application.properties",
    "content": "spring.task.execution.pool.core-size=2\nspring.task.execution.pool.max-size=5\nspring.task.execution.pool.queue-capacity=10\nspring.task.execution.pool.keep-alive=60s\nspring.task.execution.pool.allow-core-thread-timeout=true\nspring.task.execution.thread-name-prefix=task-\n\nspring.task.execution.shutdown.await-termination=false\nspring.task.execution.shutdown.await-termination-period=30s"
  },
  {
    "path": "2.x/chapter7-6/src/test/java/com/didispace/chapter76/Chapter76ApplicationTests.java",
    "content": "package com.didispace.chapter76;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\nimport java.util.concurrent.CompletableFuture;\n\n@Slf4j\n@SpringBootTest\npublic class Chapter76ApplicationTests {\n\n    @Autowired\n    private AsyncTasks asyncTasks;\n\n    @Test\n    public void test1() throws Exception {\n        long start = System.currentTimeMillis();\n\n        CompletableFuture<String> task1 = asyncTasks.doTaskOne();\n        CompletableFuture<String> task2 = asyncTasks.doTaskTwo();\n        CompletableFuture<String> task3 = asyncTasks.doTaskThree();\n\n        CompletableFuture.allOf(task1, task2, task3).join();\n\n        long end = System.currentTimeMillis();\n\n        log.info(\"任务全部完成，总耗时：\" + (end - start) + \"毫秒\");\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-7/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-7</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>如何隔离@Async异步任务的线程池</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-7/src/main/java/com/didispace/chapter77/AsyncTasks.java",
    "content": "package com.didispace.chapter77;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\nimport java.util.concurrent.CompletableFuture;\n\n@Slf4j\n@Component\npublic class AsyncTasks {\n\n    public static Random random = new Random();\n\n    @Async(\"taskExecutor1\")\n    public CompletableFuture<String> doTaskOne(String taskNo) throws Exception {\n        log.info(\"开始任务：{}\", taskNo);\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务：{}，耗时：{} 毫秒\", taskNo, end - start);\n        return CompletableFuture.completedFuture(\"任务完成\");\n    }\n\n    @Async(\"taskExecutor2\")\n    public CompletableFuture<String> doTaskTwo(String taskNo) throws Exception {\n        log.info(\"开始任务：{}\", taskNo);\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务：{}，耗时：{} 毫秒\", taskNo, end - start);\n        return CompletableFuture.completedFuture(\"任务完成\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-7/src/main/java/com/didispace/chapter77/Chapter77Application.java",
    "content": "package com.didispace.chapter77;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.ThreadPoolExecutor;\n\n@EnableAsync\n@SpringBootApplication\npublic class Chapter77Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter77Application.class, args);\n    }\n\n    @EnableAsync\n    @Configuration\n    class TaskPoolConfig {\n\n        @Bean\n        public Executor taskExecutor1() {\n            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n            executor.setCorePoolSize(2);\n            executor.setMaxPoolSize(2);\n            executor.setQueueCapacity(10);\n            executor.setKeepAliveSeconds(60);\n            executor.setThreadNamePrefix(\"executor-1-\");\n            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());\n            return executor;\n        }\n\n        @Bean\n        public Executor taskExecutor2() {\n            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n            executor.setCorePoolSize(2);\n            executor.setMaxPoolSize(2);\n            executor.setQueueCapacity(10);\n            executor.setKeepAliveSeconds(60);\n            executor.setThreadNamePrefix(\"executor-2-\");\n            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());\n            return executor;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-7/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "2.x/chapter7-7/src/test/java/com/didispace/chapter77/Chapter77ApplicationTests.java",
    "content": "package com.didispace.chapter77;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.Future;\n\n@Slf4j\n@SpringBootTest\npublic class Chapter77ApplicationTests {\n\n    @Autowired\n    private AsyncTasks asyncTasks;\n\n    @Test\n    public void test() throws Exception {\n        long start = System.currentTimeMillis();\n\n        // 线程池1\n        CompletableFuture<String> task1 = asyncTasks.doTaskOne(\"1\");\n        CompletableFuture<String> task2 = asyncTasks.doTaskOne(\"2\");\n        CompletableFuture<String> task3 = asyncTasks.doTaskOne(\"3\");\n\n        // 线程池2\n        CompletableFuture<String> task4 = asyncTasks.doTaskTwo(\"4\");\n        CompletableFuture<String> task5 = asyncTasks.doTaskTwo(\"5\");\n        CompletableFuture<String> task6 = asyncTasks.doTaskTwo(\"6\");\n\n        // 一起执行\n        CompletableFuture.allOf(task1, task2, task3, task4, task5, task6).join();\n\n        long end = System.currentTimeMillis();\n\n        log.info(\"任务全部完成，总耗时：\" + (end - start) + \"毫秒\");\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-8/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.5.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter7-8</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>为@Async异步任务线程池配置拒绝策略</description>\n\n    <properties>\n        <java.version>1.8</java.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "2.x/chapter7-8/src/main/java/com/didispace/chapter78/AsyncTasks.java",
    "content": "package com.didispace.chapter78;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\nimport java.util.concurrent.CompletableFuture;\n\n@Slf4j\n@Component\npublic class AsyncTasks {\n\n    public static Random random = new Random();\n\n    @Async(\"taskExecutor1\")\n    public CompletableFuture<String> doTaskOne(String taskNo) throws Exception {\n        log.info(\"开始任务：{}\", taskNo);\n        long start = System.currentTimeMillis();\n        Thread.sleep(random.nextInt(10000));\n        long end = System.currentTimeMillis();\n        log.info(\"完成任务：{}，耗时：{} 毫秒\", taskNo, end - start);\n        return CompletableFuture.completedFuture(\"任务完成\");\n    }\n\n}"
  },
  {
    "path": "2.x/chapter7-8/src/main/java/com/didispace/chapter78/Chapter78Application.java",
    "content": "package com.didispace.chapter78;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.scheduling.annotation.EnableAsync;\nimport org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;\n\nimport java.util.concurrent.Executor;\n\n@EnableAsync\n@SpringBootApplication\npublic class Chapter78Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter78Application.class, args);\n    }\n\n    @EnableAsync\n    @Configuration\n    class TaskPoolConfig {\n\n        @Bean\n        public Executor taskExecutor1() {\n            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n            executor.setCorePoolSize(2);\n            executor.setMaxPoolSize(2);\n            executor.setQueueCapacity(2);\n            executor.setKeepAliveSeconds(60);\n            executor.setThreadNamePrefix(\"executor-1-\");\n\n            /**配置拒绝策略**/\n\n            // AbortPolicy策略：默认策略，如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException异常。\n//            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());\n\n            // DiscardPolicy策略：如果线程池队列满了，会直接丢掉这个任务并且不会有任何异常。\n//            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());\n\n            // DiscardOldestPolicy策略：如果队列满了，会将最早进入队列的任务删掉腾出空间，再尝试加入队列。\n//            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());\n\n            // CallerRunsPolicy策略：如果添加到线程池失败，那么主线程会自己去执行该任务，不会等待线程池中的线程去执行。\n//            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());\n\n            // 自定义策略\n//            executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {\n//                @Override\n//                public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {\n//\n//                }\n//            });\n\n            return executor;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter7-8/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "2.x/chapter7-8/src/test/java/com/didispace/chapter78/Chapter78ApplicationTests.java",
    "content": "package com.didispace.chapter78;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.Future;\n\n@Slf4j\n@SpringBootTest\npublic class Chapter78ApplicationTests {\n\n    @Autowired\n    private AsyncTasks asyncTasks;\n\n    @Test\n    public void test() throws Exception {\n        // 线程池配置：core-2,max-2,queue=2，可以容纳4个任务提交\n\n        long start = System.currentTimeMillis();\n\n        // 线程池1\n        CompletableFuture<String> task1 = asyncTasks.doTaskOne(\"1\");\n        CompletableFuture<String> task2 = asyncTasks.doTaskOne(\"2\");\n        CompletableFuture<String> task3 = asyncTasks.doTaskOne(\"3\");\n        CompletableFuture<String> task4 = asyncTasks.doTaskOne(\"4\");\n\n        // 一起执行\n        CompletableFuture.allOf(task1, task2, task3, task4).join();\n\n        long end = System.currentTimeMillis();\n\n        log.info(\"任务全部完成，总耗时：\" + (end - start) + \"毫秒\");\n    }\n\n    @Test\n    public void test2() throws Exception {\n        // 线程池配置：core-2,max-2,queue=2，同时有5个任务，出现下面异常：\n        // org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@59901c4d[Running, pool size = 2,\n        // active threads = 0, queued tasks = 2, completed tasks = 4]] did not accept task: java.util.concurrent.CompletableFuture$AsyncSupply@408e96d9\n\n        long start = System.currentTimeMillis();\n\n        // 线程池1\n        CompletableFuture<String> task1 = asyncTasks.doTaskOne(\"1\");\n        CompletableFuture<String> task2 = asyncTasks.doTaskOne(\"2\");\n        CompletableFuture<String> task3 = asyncTasks.doTaskOne(\"3\");\n        CompletableFuture<String> task4 = asyncTasks.doTaskOne(\"4\");\n        CompletableFuture<String> task5 = asyncTasks.doTaskOne(\"5\");\n\n        // 一起执行\n        CompletableFuture.allOf(task1, task2, task3, task4, task5).join();\n\n        long end = System.currentTimeMillis();\n\n        log.info(\"任务全部完成，总耗时：\" + (end - start) + \"毫秒\");\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter8-1/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.5.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter8-1</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>默认日志管理与Logback配置详解</description>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "2.x/chapter8-1/src/main/java/com/didispace/chapter81/Chapter81Application.java",
    "content": "package com.didispace.chapter81;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog https://blog.didispace.com\n */\n@Slf4j\n@SpringBootApplication\npublic class Chapter81Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter81Application.class, args);\n\n        log.error(\"Hello World\");\n        log.warn(\"Hello World\");\n        log.info(\"Hello World\");\n        log.debug(\"Hello World\");\n        log.trace(\"Hello World\");\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter8-1/src/main/resources/application.properties",
    "content": "debug=true\n\nspring.output.ansi.enabled=detect\n\nlogging.file.name=run.log\nlogging.file.path=./\n\nlogging.level.com.didispace=debug\n\nlogging.logback.rollingpolicy.clean-history-on-start=false\nlogging.logback.rollingpolicy.file-name-pattern=\nlogging.logback.rollingpolicy.max-history=7\nlogging.logback.rollingpolicy.max-file-size=10MB\nlogging.logback.rollingpolicy.total-size-cap=0B\n"
  },
  {
    "path": "2.x/chapter8-2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.6.1</version>\n\t\t<relativePath/> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>com.didispace</groupId>\n\t<artifactId>chapter8-2</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<description>使用log4j2记录日志</description>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<java.version>1.8</java.version>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t\t<artifactId>spring-boot-starter-logging</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-log4j2</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<fork>true</fork>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>"
  },
  {
    "path": "2.x/chapter8-2/src/main/java/com/didispace/chapter82/Chapter82Application.java",
    "content": "package com.didispace.chapter82;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog https://blog.didispace.com\n */\n@Slf4j\n@SpringBootApplication\npublic class Chapter82Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter82Application.class, args);\n\n        log.error(\"Hello World\");\n        log.warn(\"Hello World\");\n        log.info(\"Hello World\");\n        log.debug(\"Hello World\");\n        log.trace(\"Hello World\");\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter8-2/src/main/resources/application.properties",
    "content": "\nlogging.config=classpath:log4j2.xml"
  },
  {
    "path": "2.x/chapter8-2/src/main/resources/log4j2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Configuration status=\"INFO\">\n    <Appenders>\n        <Console name=\"Console\" target=\"SYSTEM_OUT\">\n            <PatternLayout pattern=\"%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n\"/>\n        </Console>\n    </Appenders>\n    <Loggers>\n        <Root level=\"INFO\">\n            <AppenderRef ref=\"Console\"/>\n        </Root>\n    </Loggers>\n</Configuration>\n"
  },
  {
    "path": "2.x/chapter8-3/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.6.1</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>chapter8-3</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <description>使用tinylog记录日志</description>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <java.version>1.8</java.version>\n        <tinylog.version>2.4.1</tinylog.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.boot</groupId>\n                    <artifactId>spring-boot-starter-logging</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.tinylog</groupId>\n            <artifactId>tinylog-api</artifactId>\n            <version>${tinylog.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.tinylog</groupId>\n            <artifactId>tinylog-impl</artifactId>\n            <version>${tinylog.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.tinylog</groupId>\n            <artifactId>slf4j-tinylog</artifactId>\n            <version>${tinylog.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.tinylog</groupId>\n            <artifactId>jcl-tinylog</artifactId>\n            <version>${tinylog.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.tinylog</groupId>\n            <artifactId>log4j1.2-api</artifactId>\n            <version>${tinylog.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <scope>provided</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n                <configuration>\n                    <fork>true</fork>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "2.x/chapter8-3/src/main/java/com/didispace/chapter83/Chapter83Application.java",
    "content": "package com.didispace.chapter83;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * @author 程序猿DD\n * @version 1.0.0\n * @blog https://blog.didispace.com\n */\n@Slf4j\n@SpringBootApplication\npublic class Chapter83Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Chapter83Application.class, args);\n\n        log.error(\"Hello World\");\n        log.warn(\"Hello World\");\n        log.info(\"Hello World\");\n        log.debug(\"Hello World\");\n        log.trace(\"Hello World\");\n    }\n\n}\n"
  },
  {
    "path": "2.x/chapter8-3/src/main/resources/application.properties",
    "content": "\n"
  },
  {
    "path": "2.x/chapter8-3/src/main/resources/tinylog.properties",
    "content": "writer=console\nwriter.format={date: HH:mm:ss.SSS} {level}: {message}"
  },
  {
    "path": "2.x/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>2.x</artifactId>\n    <version>2.0-SNAPSHOT</version>\n    <packaging>pom</packaging>\n    <description>全网Star最多的Spring Boot基础教程</description>\n\n    <modules>\n        <!--快速入门-->\n        <module>chapter1-1</module>\n\n        <!--配置文件-->\n        <module>chapter1-2</module>  <!-- 2.4版本前后的多环境配置与配置激活 -->\n        <module>chapter1-3</module>  <!-- 2.4版本前后的配置分组配置 -->\n        <module>chapter1-4</module>  <!-- 配置元数据的应用 -->\n        <module>chapter1-5</module>  <!-- 加密配置文件中的敏感信息 -->\n\n        <!--API开发-->\n        <module>chapter2-1</module>  <!-- 构建RESTful API与单元测试 -->\n        <module>chapter2-2</module>  <!-- 使用Swagger2构建强大的API文档 -->\n        <module>chapter2-3</module>  <!-- JSR-303实现请求参数校验 -->\n        <module>chapter2-4</module>  <!-- Swagger接口分类与各元素排序问题详解 -->\n        <module>chapter2-5</module>  <!-- Swagger静态文档的生成 -->\n        <module>chapter2-6</module>  <!-- 找回启动日志中的请求路径列表 -->\n        <module>chapter2-7</module>  <!-- 使用SpringFox3生成Swagger文档 -->\n        <module>chapter2-8</module>  <!-- 如何扩展XML格式的请求和响应 -->\n<!--        <module>chapter2-9</module>  &lt;!&ndash; 使用spring-graphql构建API &ndash;&gt;-->\n        <!-- 2-x 使用Webflux编写API接口 -->\n\n        <!--数据访问（关系型数据库）-->\n        <module>chapter3-1</module>  <!-- 使用JdbcTemplate访问MySQL数据库 -->\n        <module>chapter3-2</module>  <!-- 默认数据源Hikari的配置详解 -->\n        <module>chapter3-3</module>  <!-- 使用国产数据库连接池Druid -->\n        <module>chapter3-4</module>  <!-- 使用Spring Data JPA访问MySQL -->\n        <module>chapter3-5</module>  <!-- 使用MyBatis访问MySQL -->\n        <module>chapter3-6</module>  <!-- 使用MyBatis（xml配置方式）-->\n        <module>chapter3-7</module>  <!-- JdbcTemplate的多数据源配置 -->\n        <module>chapter3-8</module>  <!-- Spring Data JPA的多数据源配置 -->\n        <module>chapter3-9</module>  <!-- MyBatis的多数据源配置 -->\n        <module>chapter3-10</module> <!-- 事务管理入门 -->\n        <module>chapter3-11</module> <!-- 使用Flyway管理数据库版本 -->\n        <module>chapter3-12</module> <!-- 使用JTA实现多数据源的事务 -->\n        <module>chapter3-13</module>  <!--2.5版本之后的数据脚本初始化 -->\n\n        <!-- 3-12 使用Liquibase管理数据库版本 -->\n        <!-- 3-13 分布式事务 -->\n\n        <!-- Web开发 -->\n        <module>chapter4-1</module>  <!-- 使用 Thymeleaf开发Web页面 -->\n        <module>chapter4-2</module>  <!-- 使用 ECharts 绘制折线图 -->\n        <module>chapter4-3</module>  <!-- 文件上传 -->\n        <module>chapter4-4</module>  <!-- 多文件上传 -->\n        <module>chapter4-5</module>  <!-- 整合Spring Security -->\n\n        <!-- 各种缓存 -->\n        <module>chapter5-1</module>  <!-- 使用进程内缓存 -->\n        <module>chapter5-2</module>  <!-- 使用进程内缓存 EhCache -->\n        <module>chapter5-3</module>  <!-- 使用EhCache缓存集群 -->\n        <module>chapter5-4</module>  <!-- 使用集中式缓存Redis -->\n        <module>chapter5-5</module>  <!-- 使用Redis的发布订阅-->\n<!--        <module>chapter5-6</module>  &lt;!&ndash; 5-6 Redis + EhCache的二连组合拳 &ndash;&gt;-->\n\n        <!-- 其他常见数据储存的使用 -->\n        <module>chapter6-1</module>  <!-- 6-1 使用MongoDB -->\n        <module>chapter6-2</module>  <!-- 6-2 使用轻量级树状存储 LDAP -->\n        <module>chapter6-3</module>  <!-- 6-3 使用时序数据库 InfluxDB -->\n        <module>chapter6-4</module>  <!-- 6-4 使用PostgreSQL数据库 -->\n        <!-- 6-5 使用Elasticsearch -->\n\n        <!-- 任务管理 -->\n        <module>chapter7-1</module>  <!-- 7-1 使用@Scheduled实现定时任务 -->\n        <module>chapter7-2</module>  <!-- 7-2 使用Elastic Job实现定时任务 -->\n        <module>chapter7-3</module>  <!-- 7-3 使用Elastic Job的分片配置 -->\n        <module>chapter7-4</module>  <!-- 7-4 使用Elastic Job的namespace防止任务名冲突 -->\n        <module>chapter7-5</module>  <!-- 7-5 使用@Async实现异步任务 -->\n        <module>chapter7-6</module>  <!-- 7-6 配置@Async异步任务的线程池 -->\n        <module>chapter7-7</module>  <!-- 7-7 如何隔离@Async异步任务的线程池 -->\n        <module>chapter7-8</module>  <!-- 7-8 为@Async异步任务线程池配置拒绝策略 -->\n        <!-- 7-9 为@Async异步任务添加超时时间 -->\n\n        <!-- 日志管理 -->\n        <module>chapter8-1</module>  <!-- 8-1 默认日志管理与Logback配置详解 -->\n        <module>chapter8-2</module>  <!-- 8-2 使用log4j2记录日志 -->\n        <module>chapter8-3</module>  <!-- 8-3 使用tinylog记录日志 -->\n\n        <!-- 其他内容 -->\n        <!-- 9-1 如何生成二维码 -->\n\n    </modules>\n</project>\n"
  },
  {
    "path": "README.md",
    "content": "# Spring Boot基础教程\n\n**专题目标**：打造全网内容最全，比收费教程更好的Spring Boot免费教程！\n\n**如何支持**：\n\n1. 关注我的公众号”**程序猿DD**“\n2. 点个`Star`并`Follow`我\n3. 把该仓库分享给更多的朋友\n\n**加入社群**：如果你正在学习Spring Boot，不妨加入我们的[Spring技术交流群](https://blog.didispace.com/join-group-spring/index.html) ，一起成长\n\n**Spring社区**：如果您在学习过程中碰到问题，可以访问[SpringForAll社区](http://spring4all.com)，描述你的问题，我们会尽快给你答复。当然，如果你想分享你的学习经验，也可以在这里发表你的文章\n\n## 教程目录\n\n该教程自2016年连载至今，因内容较多，经历过多个版本的迭代。\n\n为方便查看学习，这里重新做了整理，根据1.x版本和2.x版本做了区分汇总，后续还会继续跟进3.x版本！\n\n可以通过下面的链接，进入具体版本的教程目录：\n\n- [Spring Boot 2.x](./2.x)\n- [Spring Boot 1.x](./1.x)\n\n> **关注公众号：“程序猿DD”**，领取我整理的免费学习资料。<br>\n\n## 推荐内容\n\n- [我的博客](http://blog.didispace.com)：分享平时学习和实践过的技术内容\n- [Spring Boot教程](https://blog.didispace.com/spring-boot-learning-2x/)：全网Star最多的免费Spring Boot基础教程\n- [Spring Cloud教程](https://blog.didispace.com/spring-cloud-learning/)：全网最早最全的免费Spring Cloud基础教程\n- [知识星球](https://t.xiaomiquan.com/zfEiY3v)：聊聊技术人的斜杠生活\n\n**关注公众号，获得更多技术资讯**\n\n<img src=\"http://blog.didispace.com/css/images/weixin.jpg\" style=\"width:150px;height:150px;\" />\n"
  },
  {
    "path": "README_zh.md",
    "content": "# Spring Boot基础教程\n\n**专题目标**：打造全网内容最全，比收费教程更好的Spring Boot免费教程！\n\n**如何支持**：\n\n1. 关注我的公众号”**程序猿DD**“\n2. 点个`Star`并`Follow`我\n3. 把该仓库分享给更多的朋友\n\n**加入社群**：如果你正在学习Spring Boot，不妨加入我们的[Spring技术交流群](https://blog.didispace.com/join-group-spring/index.html) ，一起成长\n\n**Spring社区**：如果您在学习过程中碰到问题，可以访问[SpringForAll社区](http://spring4all.com)，描述你的问题，我们会尽快给你答复。当然，如果你想分享你的学习经验，也可以在这里发表你的文章\n\n## 教程目录\n\n该教程自2016年连载至今，因内容较多，经历过多个版本的迭代。\n\n为方便查看学习，这里重新做了整理，根据1.x版本和2.x版本做了区分汇总。\n\n可以通过下面的链接，进入具体版本的教程目录：\n\n- [Spring Boot 2.x](./2.x)\n- [Spring Boot 1.x](./1.x)\n\n> **关注公众号：“程序猿DD”**，领取我整理的免费学习资料。<br>\n\n## 推荐内容\n\n- [我的博客](http://blog.didispace.com)：分享平时学习和实践过的技术内容\n- [Spring Boot教程](https://blog.didispace.com/spring-boot-learning-2x/)：全网Star最多的免费Spring Boot基础教程\n- [Spring Cloud教程](https://blog.didispace.com/spring-cloud-learning/)：全网最早最全的免费Spring Cloud基础教程\n- [知识星球](https://t.xiaomiquan.com/zfEiY3v)：聊聊技术人的斜杠生活\n\n**关注公众号，获得更多技术资讯**\n\n<img src=\"http://blog.didispace.com/css/images/weixin.jpg\" style=\"width:150px;height:150px;\" />\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didispace</groupId>\n    <artifactId>SpringBoot-Learning</artifactId>\n    <version>1.0-SNAPSHOT</version>\n    <packaging>pom</packaging>\n\n    <modules>\n        <!-- 默认使用2.x教程下的工程，如果要用1.x的可修改下面的module -->\n        <module>2.x</module>\n    </modules>\n\n</project>\n"
  }
]