diff --git a/.DS_Store b/.DS_Store
index 91a7914..ef0c2ac 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/README.md b/README.md
index 0dafcc7..d334a82 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,255 @@
# springboot学习实战
+## 全新内容
+
+新增全新springboot2的框架技术点(代码位于当前仓库的spring-boot2-study目录下)
+
+基于springboot 2.0.6.RELEASE版本实现的代码演示集合,欢迎star/fork
+
+[新仓库代码位置](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent)
+
+### 新子项目列表
+
+ [一、sprint-boot2-autotest](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest)
+
+介绍Springboot2【自动化单元测试】的用法:
+
+1. 如何编写测试案例,具体用法有哪些
+2. 单元测试场景:四种业务场景,例如如何进行接口api测试,服务层代码测试,MockMvc用法等
+
+
+[二、spring-boot2-interceptor](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor)
+
+介绍Springboot2【拦截器】的用法:
+
+1. 拦截器用法详细介绍
+2. 如何把服务层对象注入到拦截器中,调用相关方法
+3. 开启跨域访问功能
+
+
+[三、spring-boot2-rocketmq](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq)
+
+介绍Springboot2【RocketMQ集成】的用法:
+
+1. 如何与springboot集成
+2. 如何建立连接,发送不同消息数据类型
+3. 如何订阅,且消费不同消息数据类型
+4. 场景案例分析
+
+
+[四、spring-boot2-schedule](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule)
+
+介绍Springboot2【@scheduled定时器】的用法:
+
+1. 定时器计划用法介绍
+2. 开启并行多线程任务两种方式
+3. 场景案例分析
+
+
+[五、spring-boot2-tomcat](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat)
+
+介绍Springboot2【Tomcat容器自定义】的用法:
+
+1. Tomcat容器配置用法,使用.yml文件方式
+2. 设置tomcat的最大连接数和最大并发数
+3. Springboot1和Springboot2版本之间的差异用法
+
+
+[六、spring-boot2-mysql-mybatis-xml](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml)
+
+介绍Springboot2【Mysql和Mybatis+XML用法详解】的用法:
+
+1. Mysql+Datasource集成
+2. Mybatis+XML用法详解
+
+
+[七、spring-boot2-mysql-multi-datasource](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource)
+
+介绍Springboot2【Mysql多数据源和Hikari用法详解】的用法:
+
+1. Mysql多数据源配置用法
+2. Hikari用法
+
+
+[八、spring-boot2-multi-resources](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources)
+
+介绍Springboot2【多环境配置文件用法】的用法:
+
+1. 多环境配置文件用法
+
+[九、spring-boot2-docker](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-docker)
+
+介绍Springboot2【Docker集成+容器化部署详解-上篇】的用法:
+
+1. 使用Maven插件构建Docker镜像
+
+[十、spring-boot2-dockerfile](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile)
+
+介绍Springboot2【Docker集成+容器化部署详解-下篇】的用法:
+
+1. 使用Dockerfile构建Docker镜像
+
+[十一、spring-boot2-redis](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-redis)
+
+介绍Springboot2【Redis分布式缓存服务集成】的用法:
+
+1. Redis集成,常用api用法
+2. 统一封装工具类(兼容解决中文乱码问题)
+
+[十二、spring-boot2-dubbo-provider](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider)
+
+介绍Springboot2【Dubbo服务提供者、服务消费者整合/Zookeeper集成】的用法:
+
+1. Dubbo服务提供者、服务消费者整合/Zookeeper集成
+
+[服务提供者-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider)
+
+[服务消费者-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer)
+
+[十三、spring-boot2-distributed-id](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id)
+
+介绍Springboot2【全局唯一ID/分布式ID解决方案】的用法:
+
+1. 分布式ID解决方案
+
+[十四、spring-boot2-mysql-druid](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid)
+
+介绍Springboot2【Druid连接池集成】的用法:
+
+1. Druid连接池集成
+2. Druid Web界面用法
+
+[十五、spring-boot2-logback](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-logback)
+
+介绍Springboot2【Logback日志框架集成】的用法:
+
+1. Logback日志文件讲解说明
+
+[十六、spring-boot2-logback-elk](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk)
+
+介绍Springboot2【ELK日志集成】的用法:
+
+1. ELK日志集成说明
+
+[十七、spring-boot2-logback-async](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async)
+
+介绍Springboot2【日志异步化处理用法】的用法:
+
+1. 日志异步化处理
+
+[十八、spring-boot2-exception](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-exception)
+
+介绍Springboot2【全局异常处理】的用法:
+
+1. 全局异常处理方式(自定义error请求返回结果)
+
+[十九、spring-boot2-api-protect](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect)
+
+介绍Springboot2【接口防刷机制】的用法:
+
+1. 接口防刷机制
+
+[二十、spring-boot2-distributed-lock](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock)
+
+介绍Springboot2【分布式锁用法】的用法:
+
+1. 分布式锁用法(基于Redis实现)
+
+[二十一、spring-boot2-mongodb](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb)
+
+介绍Springboot2【MongoDB集成】的用法:
+
+1. MongoDB集成用法
+
+[二十二、spring-boot2-oauth2-opaque-server](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server)
+
+介绍Springboot2【Oauth2+Token详细用法/SpringSecurity】的用法:
+
+[认证服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server)
+
+[资源服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource)
+
+[二十三、spring-boot2-oauth2-jwt-server](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server)
+
+介绍Springboot2【Oauth2+JWT集成/SpringSecurity集成】的用法:
+
+[认证服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server)
+
+[资源服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource)
+
+[二十四、spring-boot2-swagger](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger)
+
+介绍Springboot2【Swagger集成用法】的用法:
+
+1. Swagger2集成用法
+
+[二十五、spring-boot2-mybatis-plus](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+
+介绍Springboot2【Mybatis-Plus快速开发框架用法】的用法:
+
+1. Mybatis-Plus快速开发框架用法
+
+[二十六、spring-boot2-swagger-req-params](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params)
+
+介绍Springboot2【header/body接口参数+Swagger2集成用法】的用法:
+
+1. header/body接口参数+Swagger2集成用法
+2. 接口常用规范用法
+
+[二十七、spring-boot2-valid](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-valid)
+
+介绍Springboot2【@Valid注解用法详解+全局处理器Exception优雅处理参数验证用法】的用法:
+
+1. @Valid注解用法详解
+2. 全局处理器Exception优雅处理参数验证
+
+[二十八、spring-boot2-log-level](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level)
+
+介绍Springboot2【动态修改日志输出级别】的用法:
+
+1. 动态修改日志输出级别用法
+
+[二十九、spring-boot2-wechat-pay](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay)
+
+介绍Springboot2【微信企业支付集成(五分钟集成)】的用法:
+
+1. 微信企业支付集成(五分钟集成)
+
+[三十、spring-boot2-alipay](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay)
+
+介绍Springboot2【支付宝企业支付集成(五分钟集成)】的用法:
+
+1. 支付宝企业支付集成(五分钟集成)
+
+[三十一、spring-boot2-crawler](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler)
+
+介绍Springboot2【爬虫框架集成】的用法:
+
+1. 爬虫框架集成
+
+[三十二、spring-boot2-mybatis-plus-multi-datasource](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource)
+
+介绍Springboot2【MybatisPlus框架动态数据源用法】的用法:
+
+1. MybatisPlus框架动态数据源用法:支持多个DB,切换数据源
+
+
+
+其他内容,持续更新中,敬请期待
+
+
+
+## 该系列文档教程
+
+[SpringBoot系列教程-从入门到精通](https://hemin.blog.csdn.net/column/info/40170)
+
+
+
+
+
+
+## 当前项目中包含的内容已是旧内容了,后续不再更新,知悉
+
项目工具使用的是Eclipse mars+maven3+jdk1.8
该项目中包含了以下内容:
@@ -22,6 +272,7 @@
16. security安全验证
17. rabbitMq集成
18. kafka集成
+19. rocketMq集成
@@ -55,8 +306,16 @@ JAVA爬虫框架源码:https://github.com/hemin1003/java-spider
## [关于我](http://heminit.com/about/)
-欢迎交流问题,可加QQ469580884,一起探讨交流问题
+欢迎交流问题,可加我的个人QQ 469580884,或群号 751925591,一起探讨交流问题
[我的博客地址](http://blog.csdn.net/hemin1003)
[个人域名](http://heminit.com)
+
+
+
+## 感谢
+如果觉得内容赞,您可以请我喝杯咖啡:
+
+
+
diff --git a/pay/alipay.jpeg b/pay/alipay.jpeg
new file mode 100644
index 0000000..c4de1b2
Binary files /dev/null and b/pay/alipay.jpeg differ
diff --git a/pay/wechat.jpeg b/pay/wechat.jpeg
new file mode 100644
index 0000000..6567c65
Binary files /dev/null and b/pay/wechat.jpeg differ
diff --git a/pom.xml b/pom.xml
index efea243..5521e35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,8 +78,12 @@
org.springframework.kafka
spring-kafka
- 1.1.2.RELEASE
+
+ org.apache.rocketmq
+ rocketmq-client
+ 4.3.0
+
diff --git a/spring-boot2-study/README.md b/spring-boot2-study/README.md
new file mode 100644
index 0000000..d7f6f34
--- /dev/null
+++ b/spring-boot2-study/README.md
@@ -0,0 +1,28 @@
+# spring-boot2-parent
+
+新增全新springboot2的框架技术点
+
+基于springboot 2.0.6.RELEASE版本,实现的代码演示集合
+
+# 技术内容
+
+包含且不限于本身springboot2,如dubbo、mq、zk、分布式id框架等内容
+
+
+
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
diff --git a/spring-boot2-study/spring-boot2-parent/.DS_Store b/spring-boot2-study/spring-boot2-parent/.DS_Store
new file mode 100644
index 0000000..babb235
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/.project b/spring-boot2-study/spring-boot2-parent/.project
new file mode 100644
index 0000000..58d56ed
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/.project
@@ -0,0 +1,17 @@
+
+
+ spring-boot2-parent
+
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/.settings/org.eclipse.core.resources.prefs b/spring-boot2-study/spring-boot2-parent/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/spring-boot2-study/spring-boot2-parent/.settings/org.eclipse.m2e.core.prefs b/spring-boot2-study/spring-boot2-parent/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/spring-boot2-study/spring-boot2-parent/README.md b/spring-boot2-study/spring-boot2-parent/README.md
new file mode 100644
index 0000000..70b69d9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/README.md
@@ -0,0 +1,272 @@
+# spring-boot2-parent
+
+基于springboot 2.0.6.RELEASE版本的代码演示集合
+
+因以前在一个项目中集成技术点的内容太多,导致有时不好剥离,介绍演示时职责不单一
+
+现在优化成:每一个技术点,会新建一个小项目,彼此不影响,能独立运行,便于学习和上手
+
+# 项目列表
+
+ [一、sprint-boot2-autotest](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest)
+
+介绍Springboot2【自动化单元测试】的用法:
+
+1. 如何编写测试案例,具体用法有哪些
+2. 单元测试场景:四种业务场景,例如如何进行接口api测试,服务层代码测试,MockMvc用法等
+
+
+[二、spring-boot2-interceptor](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor)
+
+介绍Springboot2【拦截器】的用法:
+
+1. 拦截器用法详细介绍
+2. 如何把服务层对象注入到拦截器中,调用相关方法
+3. 开启跨域访问功能
+
+
+[三、spring-boot2-rocketmq](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq)
+
+介绍Springboot2【RocketMQ集成】的用法:
+
+1. 如何与springboot集成
+2. 如何建立连接,发送不同消息数据类型
+3. 如何订阅,且消费不同消息数据类型
+4. 场景案例分析
+
+
+[四、spring-boot2-schedule](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule)
+
+介绍Springboot2【@scheduled定时器】的用法:
+
+1. 定时器计划用法介绍
+2. 开启并行多线程任务两种方式
+3. 场景案例分析
+
+
+[五、spring-boot2-tomcat](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat)
+
+介绍Springboot2【Tomcat容器自定义】的用法:
+
+1. Tomcat容器配置用法,使用.yml文件方式
+2. 设置tomcat的最大连接数和最大并发数
+3. Springboot1和Springboot2版本之间的差异用法
+
+
+[六、spring-boot2-mysql-mybatis-xml](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml)
+
+介绍Springboot2【Mysql和Mybatis+XML用法详解】的用法:
+
+1. Mysql+Datasource集成
+2. Mybatis+XML用法详解
+
+
+[七、spring-boot2-mysql-multi-datasource](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource)
+
+介绍Springboot2【Mysql多数据源和Hikari用法详解】的用法:
+
+1. Mysql多数据源配置用法
+2. Hikari用法
+
+
+[八、spring-boot2-multi-resources](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources)
+
+介绍Springboot2【多环境配置文件用法】的用法:
+
+1. 多环境配置文件用法
+
+[九、spring-boot2-docker](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-docker)
+
+介绍Springboot2【Docker集成+容器化部署详解-上篇】的用法:
+
+1. 使用Maven插件构建Docker镜像
+
+[十、spring-boot2-dockerfile](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile)
+
+介绍Springboot2【Docker集成+容器化部署详解-下篇】的用法:
+
+1. 使用Dockerfile构建Docker镜像
+
+[十一、spring-boot2-redis](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-redis)
+
+介绍Springboot2【Redis分布式缓存服务集成】的用法:
+
+1. Redis集成,常用api用法
+2. 统一封装工具类(兼容解决中文乱码问题)
+
+[十二、spring-boot2-dubbo-provider](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider)
+
+介绍Springboot2【Dubbo服务提供者、服务消费者整合/Zookeeper集成】的用法:
+
+1. Dubbo服务提供者、服务消费者整合/Zookeeper集成
+
+[服务提供者-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider)
+
+[服务消费者-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer)
+
+[十三、spring-boot2-distributed-id](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id)
+
+介绍Springboot2【全局唯一ID/分布式ID解决方案】的用法:
+
+1. 分布式ID解决方案
+
+[十四、spring-boot2-mysql-druid](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid)
+
+介绍Springboot2【Druid连接池集成】的用法:
+
+1. Druid连接池集成
+2. Druid Web界面用法
+
+[十五、spring-boot2-logback](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-logback)
+
+介绍Springboot2【Logback日志框架集成】的用法:
+
+1. Logback日志文件讲解说明
+
+[十六、spring-boot2-logback-elk](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk)
+
+介绍Springboot2【ELK日志集成】的用法:
+
+1. ELK日志集成说明
+
+[十七、spring-boot2-logback-async](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async)
+
+介绍Springboot2【日志异步化处理用法】的用法:
+
+1. 日志异步化处理
+
+[十八、spring-boot2-exception](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-exception)
+
+介绍Springboot2【全局异常处理】的用法:
+
+1. 全局异常处理方式(自定义error请求返回结果)
+
+[十九、spring-boot2-api-protect](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect)
+
+介绍Springboot2【接口防刷机制】的用法:
+
+1. 接口防刷机制
+
+[二十、spring-boot2-distributed-lock](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock)
+
+介绍Springboot2【分布式锁用法】的用法:
+
+1. 分布式锁用法(基于Redis实现)
+
+[二十一、spring-boot2-mongodb](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb)
+
+介绍Springboot2【MongoDB集成】的用法:
+
+1. MongoDB集成用法
+
+[二十二、spring-boot2-oauth2-opaque-server](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server)
+
+介绍Springboot2【Oauth2+Token详细用法/SpringSecurity】的用法:
+
+[认证服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server)
+
+[资源服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource)
+
+[二十三、spring-boot2-oauth2-jwt-server](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server)
+
+介绍Springboot2【Oauth2+JWT集成/SpringSecurity集成】的用法:
+
+[认证服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server)
+
+[资源服务-源码](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource)
+
+[二十四、spring-boot2-swagger](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger)
+
+介绍Springboot2【Swagger集成用法】的用法:
+
+1. Swagger2集成用法
+
+[二十五、spring-boot2-mybatis-plus](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+
+介绍Springboot2【Mybatis-Plus快速开发框架用法】的用法:
+
+1. Mybatis-Plus快速开发框架用法
+
+[二十六、spring-boot2-swagger-req-params](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params)
+
+介绍Springboot2【header/body接口参数+Swagger2集成用法】的用法:
+
+1. header/body接口参数+Swagger2集成用法
+2. 接口常用规范用法
+
+[二十七、spring-boot2-valid](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-valid)
+
+介绍Springboot2【@Valid注解用法详解+全局处理器Exception优雅处理参数验证用法】的用法:
+
+1. @Valid注解用法详解
+2. 全局处理器Exception优雅处理参数验证
+
+[二十八、spring-boot2-log-level](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level)
+
+介绍Springboot2【动态修改日志输出级别】的用法:
+
+1. 动态修改日志输出级别用法
+
+[二十九、spring-boot2-wechat-pay](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay)
+
+介绍Springboot2【微信企业支付集成(五分钟集成)】的用法:
+
+1. 微信企业支付集成(五分钟集成)
+
+[三十、spring-boot2-alipay](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay)
+
+介绍Springboot2【支付宝企业支付集成(五分钟集成)】的用法:
+
+1. 支付宝企业支付集成(五分钟集成)
+
+[三十一、spring-boot2-crawler](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler)
+
+介绍Springboot2【爬虫框架集成】的用法:
+
+1. 爬虫框架集成
+
+[三十二、spring-boot2-mybatis-plus-multi-datasource](https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource)
+
+介绍Springboot2【MybatisPlus框架动态数据源用法】的用法:
+
+1. MybatisPlus框架动态数据源用法:支持多个DB,切换数据源
+
+
+
+
+
+
+其他内容,持续更新中,敬请期待
+
+
+
+
+
+## 该系列文档教程
+
+[SpringBoot系列教程-从入门到精通](https://hemin.blog.csdn.net/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
+
+## 感谢
+如果觉得内容赞,您可以请我喝一杯咖啡:
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/pay/alipay.jpeg b/spring-boot2-study/spring-boot2-parent/pay/alipay.jpeg
new file mode 100644
index 0000000..c4de1b2
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/pay/alipay.jpeg differ
diff --git a/spring-boot2-study/spring-boot2-parent/pay/wechat.jpeg b/spring-boot2-study/spring-boot2-parent/pay/wechat.jpeg
new file mode 100644
index 0000000..6567c65
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/pay/wechat.jpeg differ
diff --git a/spring-boot2-study/spring-boot2-parent/pom.xml b/spring-boot2-study/spring-boot2-parent/pom.xml
new file mode 100755
index 0000000..d1a3cd0
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/pom.xml
@@ -0,0 +1,242 @@
+
+ 4.0.0
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ spring-boot2-parent
+ pom
+ 聚合
+
+
+ UTF-8
+ UTF-8
+ 2.0.6.RELEASE
+ 2.9.2
+
+
+
+ spring-boot2-autotest
+ spring-boot2-interceptor
+ spring-boot2-rocketmq
+ spring-boot2-schedule
+ spring-boot2-tomcat
+ spring-boot2-mysql-mybatis-xml
+ spring-boot2-mysql-multi-datasource
+
+ spring-boot2-multi-resources
+ spring-boot2-docker
+ spring-boot2-dockerfile
+ spring-boot2-redis
+
+ spring-boot2-dubbo-provider
+ spring-boot2-dubbo-consumer
+ spring-boot2-distributed-id
+ spring-boot2-distributed-id-core-leafid
+ spring-boot2-mysql-druid
+
+ spring-boot2-logback
+ spring-boot2-logback-elk
+ spring-boot2-logback-async
+ spring-boot2-exception
+ spring-boot2-api-protect
+ spring-boot2-distributed-lock
+
+ spring-boot2-mongodb
+ spring-boot2-oauth2-jwt-server
+ spring-boot2-oauth2-jwt-resource
+ spring-boot2-oauth2-opaque-server
+ spring-boot2-oauth2-opaque-resource
+
+ spring-boot2-swagger
+ spring-boot2-mybatis-plus
+ spring-boot2-sharding-jdbc
+
+ spring-boot2-swagger-req-params
+ spring-boot2-swagger-req-params-log
+
+ spring-boot2-valid
+ spring-boot2-log-level
+ spring-boot2-wechat-pay
+ spring-boot2-alipay
+ spring-boot2-crawler
+
+ spring-boot2-mybatis-plus-multi-datasource
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.6.RELEASE
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+ ${spring-boot-version}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring-boot-version}
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring-boot-version}
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+ ${spring-boot-version}
+
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+ 3.1.0
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+ 5.1.41
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+ ${spring-boot-version}
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+ ${spring-boot-version}
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 1.1.1
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+ 1.0.2
+
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+ 5.0
+
+
+ com.jayway.jsonpath
+ json-path
+ 0.8.1
+
+
+ com.alibaba
+ dubbo
+ 2.4.10
+
+
+ org.apache.zookeeper
+ zookeeper
+ 3.4.6
+
+
+ com.github.sgroschupf
+ zkclient
+ 0.1
+
+
+ com.google.code.gson
+ gson
+ 2.8.5
+
+
+
+ org.bouncycastle
+ bcprov-jdk16
+ 1.46
+
+
+ com.google.inject
+ guice
+ 4.0
+
+
+
+ jdom
+ jdom
+ 1.1
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.1.10
+
+
+ com.github.org-hejianhui
+ spring-boot-starter-rocketmq
+ 1.0-RELEASE
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+ ${spring-boot-version}
+
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ ${spring-boot-version}
+
+
+ commons-io
+ commons-io
+ 2.6
+
+
+ io.quarkus
+ quarkus-development-mode
+ 0.22.0
+
+
+ com.alibaba
+ fastjson
+ 1.2.59
+
+
+
+ io.springfox
+ springfox-swagger2
+ ${swagger.version}
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${swagger.version}
+
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ 1.9.3
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/README.md
new file mode 100644
index 0000000..fd10a44
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-alipay
+
+【支付宝企业支付集成(五分钟集成)】技术点
+
+功能介绍
+
+1. 支付宝企业支付集成(五分钟集成)
+
+## 本项目教程
+
+[支付宝企业支付集成(五分钟集成)](https://hemin.blog.csdn.net/article/details/104605826)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/lib/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/lib/README.md
new file mode 100644
index 0000000..33d9f66
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/lib/README.md
@@ -0,0 +1,3 @@
+进入项目根目录下的lib目录,运行下面命令,把包安装到maven本地仓库:
+
+mvn install:install-file -Dfile=alipay-sdk-1.0.jar -DgroupId=alipay-sdk -DartifactId=alipay-sdk -Dversion=1.0 -Dpackaging=jar
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/lib/alipay-sdk-1.0.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/lib/alipay-sdk-1.0.jar
new file mode 100644
index 0000000..b03be9e
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/lib/alipay-sdk-1.0.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/pom.xml
new file mode 100644
index 0000000..0f62e19
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/pom.xml
@@ -0,0 +1,72 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-alipay
+ jar
+
+ spring-boot2-alipay
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ io.springfox
+ springfox-swagger2
+
+
+ io.springfox
+ springfox-swagger-ui
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+
+
+ alipay-sdk
+ alipay-sdk
+ 1.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..a877347
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,49 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+@EnableScheduling
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/ScheduleConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/ScheduleConfig.java
new file mode 100644
index 0000000..caa0fa6
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/ScheduleConfig.java
@@ -0,0 +1,21 @@
+package com.md.demo;
+
+import java.util.concurrent.Executors;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+/**
+ * 多线程实现并发定时
+ *
+ * @author Minbo
+ */
+@Configuration
+public class ScheduleConfig implements SchedulingConfigurer {
+
+ @Override
+ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+ taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/service/IAlipayService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/service/IAlipayService.java
new file mode 100644
index 0000000..836316f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/service/IAlipayService.java
@@ -0,0 +1,15 @@
+package com.md.demo.pay.service;
+
+/**
+ * 支付宝自动打款
+ *
+ * @author Minbo
+ */
+public interface IAlipayService {
+
+ /**
+ * 支付宝批量打款
+ */
+ public void alipayBatchPay();
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/service/impl/AlipayServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/service/impl/AlipayServiceImpl.java
new file mode 100644
index 0000000..f5600ae
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/service/impl/AlipayServiceImpl.java
@@ -0,0 +1,109 @@
+package com.md.demo.pay.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+
+import com.md.demo.pay.service.IAlipayService;
+import com.md.demo.pay.util.AliPayServiceUtils;
+import com.md.demo.pay.utils.vo.PayWithdrawHis;
+import com.md.demo.util.StrUtil;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 支付宝自动打款
+ *
+ * @author Minbo
+ */
+@Service
+@Slf4j
+public class AlipayServiceImpl implements IAlipayService {
+
+ /**
+ * 支付宝批量打款
+ */
+ @Override
+ public void alipayBatchPay() {
+
+ // TODO 这里从DB中获得订单数据
+ List list = new ArrayList();
+
+ for (PayWithdrawHis objInfo : list) {
+ log.info("---------------------------------------------");
+ log.info("--------------------start--------------------");
+
+ try {
+ String name = StrUtil.null2Str(objInfo.getName());
+ String amount = objInfo.getIncome();
+ String orderId = objInfo.getOrderId();
+ String account = StrUtil.null2Str(objInfo.getAccount());
+
+ log.info("打款订单:" + objInfo.toString());
+
+ // 1. 先查询此订单状态
+ int flag = AliPayServiceUtils.query(orderId);
+ if (flag == 0) {
+ log.info("之前已经打款成功,直接更新状态即可。");
+
+ // TODO 直接更新订单桩体
+// this.updateHttWithdrawHis(objInfo);
+
+ // 2. 不存在此订单数据,则打款
+ } else if (flag == 4) {
+ log.info("开始真正打款,然后更新状态。");
+ int result = AliPayServiceUtils.transfer(orderId, account, amount, name, objInfo);
+
+ if (result == 99) {
+ log.error("打款,后台企业支付宝账户支付余额不足,停止打款", new RuntimeException("余额不足,停止此次打款"));
+ break;
+ }
+ if (result == 88) {
+ log.error("打款,后台企业支付宝账户系统异常,停止打款。" + objInfo.toString(),
+ new RuntimeException("支付宝账户异常,停止此次打款"));
+ break;
+ }
+ if (result == 77) {
+ log.error("支付宝账户系统繁忙,休眠十秒。" + objInfo.toString());
+ Thread.sleep(10000);
+ }
+ if (result == 55) {
+ log.error("打款报错【支付宝】,请检查。" + objInfo.toString(), new RuntimeException("打款报错,跳过该用户打款"));
+ continue;
+ }
+
+ if (result == 0) {
+ // TODO 打款成功处理
+// this.updateHttWithdrawHis(objInfo);
+
+ } else if (result == 4) {
+ // TODO 打款失败处理
+// this.httWithdrawHisService.failProcess(objInfo);
+ }
+ }
+ } catch (Exception e) {
+ log.error("提现记录异常:orderId=" + objInfo.getOrderId() + ", msg=" + e.getMessage(), e);
+ }
+ log.info("--------------------end--------------------");
+ log.info("---------------------------------------------");
+ }
+ }
+
+// /**
+// * 更新提现记录-‘提现成功’状态
+// *
+// * @param httWithdrawHisVo
+// */
+// private void updateHttWithdrawHis(PayWithdrawHis httWithdrawHisVo) {
+// httWithdrawHisVo.setStatus("提现成功");
+// httWithdrawHisVo.setStatusType(2);
+// httWithdrawHisVo.setUpdateDate(DateUtil.getCurrentLongDateTime());
+// boolean status = this.httWithdrawHisService.updateHttWithdrawHis(httWithdrawHisVo);
+// if (status) {
+// log.info("状态更新成功 for 提现成功");
+// } else {
+// log.info("状态更新失败 for 提现成功");
+// }
+// }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/task/ScheduledTasks.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/task/ScheduledTasks.java
new file mode 100644
index 0000000..eac17c5
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/task/ScheduledTasks.java
@@ -0,0 +1,59 @@
+package com.md.demo.pay.task;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import com.md.demo.pay.service.IAlipayService;
+
+@Component
+public class ScheduledTasks {
+
+ protected static Logger logger = LoggerFactory.getLogger(ScheduledTasks.class);
+
+ @Autowired
+ private IAlipayService alipayService;
+
+ /**
+ * 每60秒执行一次,从DB中获得订单数据
+ */
+ @Scheduled(initialDelay = 5000, fixedDelay = 60000)
+ public void httTaskOfWechatPay() {
+ if (!isGoPayment()) {
+ return;
+ }
+
+ logger.info("------------------------------------------------");
+ logger.info("============支付宝打款任务,start===================");
+
+ // 调用打款服务
+// this.alipayService.alipayBatchPay();
+
+ logger.info("============支付宝打款任务,end===================");
+ logger.info("------------------------------------------------");
+ }
+
+ /**
+ * 是否允许自动打款-判断时间区间
+ *
+ * @return
+ */
+ public boolean isGoPayment() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(new Date());
+ int hour = calendar.get(Calendar.HOUR_OF_DAY);
+ logger.info("当前小时hour=" + hour);
+
+ if (hour >= 0 && hour <= 8) {
+ logger.info("0点到8点期间,不进行打款,停止打款任");
+ return false;
+ }
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/util/AliPayServiceUtils.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/util/AliPayServiceUtils.java
new file mode 100644
index 0000000..996e3c0
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/util/AliPayServiceUtils.java
@@ -0,0 +1,129 @@
+package com.md.demo.pay.util;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
+import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
+import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
+import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
+import com.md.demo.pay.utils.vo.PayWithdrawHis;
+import com.md.demo.util.StrUtil;
+
+import lombok.extern.slf4j.Slf4j;
+import net.sf.json.JSONObject;
+
+/**
+ * 支付服务工具类
+ *
+ * @author Minbo
+ *
+ */
+@Slf4j
+public class AliPayServiceUtils {
+
+ // TODO 填写支付宝接入信息
+ private static final String APP_ID = "xxxxxx";
+ private static final String APP_PRIVATE_KEY = "xxxxxx";
+ private static final String ALIPAY_PUBLIC_KEY = "xxxxxx";
+
+ private static AlipayClient alipayClient;
+
+ private static final String payer_show_name = "xxx企业账户";
+ private static final String remark = "提现转账测试";
+
+ static {
+ alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json",
+ "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");
+ }
+
+ /**
+ * 转账打款
+ */
+ public static int transfer(String out_biz_no, String payee_account, String amount, String payee_real_name,
+ PayWithdrawHis objInfo) {
+ AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
+ request.setBizContent(
+ "{" + " \"out_biz_no\":\"" + out_biz_no + "\"," + " \"payee_type\":\"ALIPAY_LOGONID\","
+ + " \"payee_account\":\"" + payee_account + "\"," + " \"amount\":\"" + amount + "\","
+ + " \"payer_show_name\":\"" + payer_show_name + "\"," + " \"payee_real_name\":\""
+ + payee_real_name + "\"," + " \"remark\":\"" + remark + "\"," + " }");
+ try {
+ AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
+ String json = response.getBody();
+ log.info("打款操作结果json=" + json);
+
+ JSONObject obj = JSONObject.fromObject(json);
+ JSONObject objResp = JSONObject.fromObject(obj.get("alipay_fund_trans_toaccount_transfer_response"));
+ if (StrUtil.null2Str(objResp.get("code")).equals("10000")) {
+ log.info("打款成功");
+ return 0;
+
+ } else {
+ if (StrUtil.null2Str(objResp.get("sub_code")).equals("PAYER_BALANCE_NOT_ENOUGH")) {
+ return 99;
+ }
+ if (StrUtil.null2Str(objResp.get("sub_code")).equals("aop.SYSTEM_ERROR")) {
+ return 88;
+ }
+ if (StrUtil.null2Str(objResp.get("sub_code")).equals("isp.unknow-error")
+ && StrUtil.null2Str(objResp.get("sub_msg")).equals("系统繁忙")) {
+ return 77;
+ }
+
+ if (objInfo != null) {
+ // 支付宝账号和姓名不匹配,请确认姓名是否正确
+ // 收款账号不存在
+ if (StrUtil.null2Str(objResp.get("sub_code")).equals("PAYEE_USER_INFO_ERROR")
+ || StrUtil.null2Str(objResp.get("sub_code")).equals("PAYEE_NOT_EXIST")) {
+ objInfo.setFailErrorMsg(StrUtil.null2Str(objResp.get("sub_code")) + ":"
+ + StrUtil.null2Str(objResp.get("sub_msg")));
+ objInfo.setOrderStatusName("提现失败,金币已返还-" + StrUtil.null2Str(objResp.get("sub_msg")));
+
+ log.error("打款失败。objResp=" + objResp.toString() + ",httWithdrawHisVo--->" + objInfo.toString());
+ return 4;
+ }
+ }
+ return 55;
+ }
+
+ } catch (AlipayApiException e) {
+ log.error("转账异常:" + e.getMessage(), e);
+ return 2;
+ }
+ }
+
+ /**
+ * 订单查询
+ */
+ public static int query(String out_biz_no) {
+ AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
+ request.setBizContent("{" + " \"out_biz_no\":\"" + out_biz_no + "\" " + "}");
+
+ try {
+ AlipayFundTransOrderQueryResponse response = alipayClient.execute(request);
+ String json = response.getBody();
+ log.info("查询打款结果json=" + json);
+
+ JSONObject obj = JSONObject.fromObject(json);
+ JSONObject objResp = JSONObject.fromObject(obj.get("alipay_fund_trans_order_query_response"));
+
+ if (StrUtil.null2Str(objResp.get("code")).equals("10000")
+ && StrUtil.null2Str(objResp.get("msg")).equals("Success")) {
+ log.error("订单已打款,不能重复打款。out_biz_no=" + out_biz_no + ",json=" + json);
+ return 0;
+ }
+ if (StrUtil.null2Str(objResp.get("code")).equals("40004")
+ && StrUtil.null2Str(objResp.get("sub_code")).equals("ORDER_NOT_EXIST")) {
+ log.info("订单不存在,可以打款");
+ return 4;
+
+ } else {
+ return 1;
+ }
+ } catch (AlipayApiException e) {
+ log.error("查询异常:" + e.getMessage(), e);
+ return 3;
+ }
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/utils/vo/PayWithdrawHis.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/utils/vo/PayWithdrawHis.java
new file mode 100644
index 0000000..59fd251
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/pay/utils/vo/PayWithdrawHis.java
@@ -0,0 +1,59 @@
+package com.md.demo.pay.utils.vo;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ *
+ * 提现记录
+ *
+ *
+ * @author minbo
+ */
+@Data
+@ApiModel(value = "PayWithdrawHis对象", description = "提现记录")
+public class PayWithdrawHis implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(value = "订单流水号")
+ private String orderId;
+
+ @ApiModelProperty(value = "打款账户号")
+ private String Account;
+
+ @ApiModelProperty(value = "账户姓名")
+ private String name;
+
+ @ApiModelProperty(value = "系统用户ID")
+ private String sysUserId;
+
+ @ApiModelProperty(value = "AppID")
+ private String appId;
+
+ @ApiModelProperty(value = "兑换金币值")
+ private String gold;
+
+ @ApiModelProperty(value = "提现金额")
+ private String income;
+
+ @ApiModelProperty(value = "提现申请时间")
+ private Date applyTime;
+
+ @ApiModelProperty(value = "订单状态类型值,1/2/3/4")
+ private Integer orderStatus;
+
+ @ApiModelProperty(value = "订单状态类型名1处理中,2提现成功,3审核中,4提现失败")
+ private String orderStatusName;
+
+ @ApiModelProperty(value = "提现完成时间")
+ private Date finishedTime;
+
+ @ApiModelProperty(value = "提现失败原因")
+ private String failErrorMsg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..6f76b9e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,26 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-alipay";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/DateUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/DateUtil.java
new file mode 100644
index 0000000..499bfe0
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/DateUtil.java
@@ -0,0 +1,628 @@
+package com.md.demo.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Random;
+
+import org.apache.commons.lang.time.DateUtils;
+
+/**
+ * 日期工具类
+ */
+public final class DateUtil {
+
+ public static final int DATE_NUM = 0;
+
+ public static final String LONG_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+ public static final String LONG_DATETIME_FORMAT_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
+
+ public static final String LONGDATETIMEFORMAT = "yyyyMMddHHmmss";
+
+ public static final String DATETIMEFORMAT = "yyyyMMdd";
+
+ private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm";
+
+ private static final String DATETIME_FORMAT_HOURS = "yyyy-MM-dd HH";
+
+ private static final String DATE_FORMAT = "yyyy-MM-dd";
+
+ private static final String TIME_FORMAT = "HH:mm";
+
+ /**
+ * 获取指定月的对应天数
+ */
+ public static final int[] DAYS = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ /**
+ * convert to millisecond
+ */
+ public static final long TIME_ONE_HOUR = 3600L * 1000L;
+
+ public static final long TIME_ONE_DAY = 24L * TIME_ONE_HOUR;
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentLongDateTime() {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addHours(new Date(), DATE_NUM));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentLongDateTime(int num) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addDays(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd".
+ */
+ public static String getCurrentDate() {
+ return new SimpleDateFormat(DATE_FORMAT).format(DateUtils.addHours(new Date(), DATE_NUM));
+ }
+
+ public static String getCurrentDate(int num) {
+ return new SimpleDateFormat(DATE_FORMAT).format(DateUtils.addDays(new Date(), num));
+ }
+
+ /**
+ * 返回当前系统时间(字符串格式:yyyy-MM-dd HH:mm:ss)
+ *
+ * @return String
+ */
+ public static String getDateTime() {
+ Date d = DateUtils.addHours(new Date(), DATE_NUM);
+ SimpleDateFormat sdfreplay = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ String replytime = sdfreplay.format(d);
+ return replytime;
+ }
+
+ /**
+ * 返回一个随机数,组成格式"yyyyMMddhhmmss"+10000以内的随机数
+ *
+ * @return
+ */
+ public static String buildRandomFileName() {
+ Calendar cal = Calendar.getInstance();
+ SimpleDateFormat sdfreplay = new SimpleDateFormat("yyyyMMddHHmmss");
+ String replytime = sdfreplay.format(cal.getTime());
+ return replytime + new Random().nextInt(1000);
+ }
+
+ /**
+ * Convert date to String like "yyyyMMddHHmmss".
+ */
+ public static String getCurrentLongDateTime2() {
+ return new SimpleDateFormat(LONGDATETIMEFORMAT).format(new Date());
+ }
+
+ /**
+ * Convert date to String like "yyyyMMdd".
+ */
+ public static String getCurrentDate2(int num) {
+ return new SimpleDateFormat(DATETIMEFORMAT).format(DateUtils.addDays(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm".
+ */
+ public static String getCurrentDateTime() {
+ return new SimpleDateFormat(DATETIME_FORMAT).format(DateUtils.addHours(new Date(), DATE_NUM));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH".
+ */
+ public static String getCurrentDateTimeHours(int num) {
+ return new SimpleDateFormat(DATETIME_FORMAT_HOURS).format(DateUtils.addHours(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH".
+ */
+ public static String getCurrentDateTimeMinutes(int num) {
+ return new SimpleDateFormat(DATETIME_FORMAT).format(DateUtils.addMinutes(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentDateTimeMinutesSecond(int num) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addMinutes(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentDateTimeSecond(int num) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addSeconds(new Date(), num));
+ }
+
+ /**
+ * Convert time to string like "HH:mm".
+ */
+ public static String formatTime(Date d) {
+ return new SimpleDateFormat(TIME_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm".
+ */
+ public static String formatDateTime(Date d) {
+ return new SimpleDateFormat(DATETIME_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd".
+ */
+ public static String formatDate(Date d) {
+ return new SimpleDateFormat(DATE_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String formatLongDate(Date d) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm:ss SSS".
+ */
+ public static String formatLongDateSSS(Date d) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT_SSS).format(d);
+ }
+
+ /**
+ * Parse date like "yyyy-MM-dd".
+ */
+ public static Date parseDate(String d) {
+ try {
+ return new SimpleDateFormat(DATE_FORMAT).parse(d);
+ } catch (ParseException e) {
+ }
+ return null;
+ }
+
+ /**
+ * Parse date and time like "yyyy-MM-dd HH:mm".
+ */
+ public static Date parseDateTime(String dt) {
+ try {
+ return new SimpleDateFormat(DATETIME_FORMAT).parse(dt);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ /**
+ * Parse date and time like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static Date parseLongDateTime(String dt, String format) {
+ try {
+ return new SimpleDateFormat(format).parse(dt);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ /**
+ * Parse date and time like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static Date parseLongDateTime(String dt) {
+ try {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dt);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm".
+ */
+ public static String formatLongDateTime(Date d, String format) {
+ return new SimpleDateFormat(format).format(d);
+ }
+
+ /*
+ * 判断date是否在开始日期和结束日期之间
+ */
+ public static boolean includes(Date fromDay, Date toDay, Date date) {
+ long fromTime = fromDay.getTime();
+ long toTime = toDay.getTime();
+ long dateTime = date.getTime();
+ return ((fromTime <= dateTime) && (dateTime < toTime));
+ }
+
+ /*
+ * 判断date是否在开始日期和结束日期之间
+ *
+ */
+ public static boolean includess(Date fromDay, Date toDay, Date date) {
+ long fromTime = fromDay.getTime();
+ long toTime = toDay.getTime();
+ long dateTime = date.getTime();
+ return ((fromTime <= dateTime) && (dateTime <= toTime));
+ }
+
+ /*
+ * 给定的日期,增加指定的天数 除去周六周日之外
+ */
+ public static String addDays(String dateStr, int days, Properties holidays) {
+ SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMAT);
+ Date current = null;
+ try {
+ current = sf.parse(dateStr);
+ int cuDay = 0;
+ for (int i = 0; i < days; i++) {
+ current.setDate(current.getDate() + 1);
+ cuDay = current.getDay();
+ /* 除去节假日 */
+ Iterator iter = holidays.keySet().iterator();
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ if (key.startsWith("holiday.")) {
+ String[] va = holidays.getProperty(key).split("&");
+ boolean re = includes(sf.parse(va[0]), sf.parse(va[1]), current);
+ if (re) {
+ if (cuDay != 0 && cuDay != 6) {
+ i--;
+ }
+ }
+ }
+ }
+ /* 除去周六周日 */
+ if (cuDay == 0 || cuDay == 6) {
+ i--;
+ }
+ }
+ } catch (ParseException e) {
+ current = DateUtils.addHours(new Date(), DATE_NUM);
+ }
+ return sf.format(current);
+ }
+
+ /*
+ * 给定日期和系统当前日期的天数差 除去周六周日之外
+ */
+ public static int getDayFromToday(String start, Properties holidays) {
+ int day = -1;
+ boolean negative = false;
+ try {
+ SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMAT);
+ Date startDate = sf.parse(start);
+ Date endDate = DateUtils.addHours(new Date(), DATE_NUM);/* 系统当前日期 */
+ int cuDay = 0;
+ Date temp = null;
+ if (endDate.before(startDate)) {
+ temp = startDate;
+ startDate = endDate;
+ endDate = temp;
+ negative = true;
+ }
+ while (endDate.compareTo(startDate) > 0) {
+ startDate.setDate(startDate.getDate() + 1);
+ cuDay = startDate.getDay();
+ /* 除去节假日 */
+ Iterator iter = holidays.keySet().iterator();
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ if (key.startsWith("holiday.")) {
+ String[] va = holidays.getProperty(key).split("&");
+ boolean re = includes(sf.parse(va[0]), sf.parse(va[1]), startDate);
+ if (re) {
+ if (cuDay != 0 && cuDay != 6) {
+ day++;
+ }
+ }
+ }
+ }
+ if (cuDay > 0 && cuDay < 6) {
+ day++;
+ }
+ }
+ } catch (ParseException e) {
+ }
+
+ return negative == true ? day : -day;
+ }
+
+ public static boolean isLeapYear(int year) {
+ if (year % 100 == 0) {
+ return year % 400 == 0;
+ }
+ return year % 4 == 0;
+ }
+
+ /**
+ * 将10-05-2013 转换为 2013-10-05
+ */
+ public static String changedate(String d) {
+ String ret = d;
+ try {
+ String tmp = d.substring(d.length() - 4, d.length());
+ ret = tmp + "-" + d;
+ ret = ret.substring(0, 10);
+ } catch (Exception e) {
+ return ret;
+ }
+ return ret;
+ }
+
+ /**
+ * 将01/10/2013 转换为 2013-10-01
+ */
+ public static String changedates(String d) {
+ String ret = d;
+ try {
+ String tmp = d.substring(3, 5);
+ String tmpday = d.substring(0, 2);
+ String tmpyew = d.substring(6, 10);
+ ret = tmpyew + "-" + tmp + "-" + tmpday;
+
+ } catch (Exception e) {
+ return ret;
+ }
+ return ret;
+ }
+
+ /**
+ * 获取周几的中文名称,比如周一
+ *
+ * @param key
+ * @return
+ */
+ public static String getWeekDesc(String key) {
+ String[][] keys = initWeeks();
+ for (int i = 0; i < keys.length; i++) {
+ String[] temp = keys[i];
+ for (int j = 0; j < temp.length; j++) {
+ if (key.equals(temp[0])) {
+ return temp[1];
+ }
+ }
+ }
+ return "不存在对应的解析描述";
+ }
+
+ private static String[][] initWeeks() {
+ String[][] KEY_VALUE = { { "1", "周一" }, { "2", "周二" }, { "3", "周三" }, { "4", "周四" }, { "5", "周五" },
+ { "6", "周六" }, { "7", "周日" } };
+ return KEY_VALUE;
+ }
+
+ public static long getDateDays(Date nowDate, Date oldDate) {
+ long nd = 1000 * 24 * 60 * 60;
+ long nh = 1000 * 60 * 60;
+ long nm = 1000 * 60;
+ // long ns = 1000;
+ // 获得两个时间的毫秒时间差异
+ long diff = nowDate.getTime() - oldDate.getTime();
+ // 计算差多少天
+ // long day = diff / nd;
+ // 计算差多少小时
+ long hour = diff % nd / nh;
+ // 计算差多少分钟
+ // long min = diff % nd % nh / nm;
+ // 计算差多少秒//输出结果
+ // long sec = diff % nd % nh % nm / ns;
+ // return day + "天" + hour + "小时" + min + "分钟";
+ return hour;
+ }
+
+ // public static void main(String[] args) {
+ // Date d1 = DateUtil.parseLongDateTime("2017-04-25 14:12:12");
+ // Date d2 = DateUtil.parseLongDateTime("2017-04-25 11:12:11");
+ // long a = getDateDays(d2, d1);
+ // System.out.println(a);
+ // }
+
+ /**
+ * 根据日期取得星期几
+ *
+ * @param date
+ * @return
+ */
+ public static int getWeek(Date date) {
+ String[] weeks = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
+ if (week_index < 0) {
+ week_index = 0;
+ }
+ if (week_index == 0) {
+ week_index = 7; // 周日
+ }
+ return week_index;
+ // SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
+ // String week = sdf.format(date);
+ // return week;
+ }
+
+ /**
+ * 得到指定日期在一个月中的哪一天
+ *
+ * @param date
+ * @return
+ */
+ public static int getDayOfMonth(Date date) {
+ Calendar ca = Calendar.getInstance();
+ ca.setTime(date);
+ int a = ca.get(Calendar.DAY_OF_MONTH);
+ return a;
+ }
+
+ /**
+ * 将时间转换为时间戳
+ */
+ public static String dateToStamp(String s) {
+ String res;
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date;
+ try {
+ date = simpleDateFormat.parse(s);
+ long ts = date.getTime();
+ res = String.valueOf(ts);
+ return res;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 将时间戳转换为时间
+ */
+ public static String stampToDate(long timeStamp) {
+ String result = null;
+ Date date = new Date(timeStamp * 1000);
+ SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ result = sd.format(date);
+ return result;
+ }
+
+ /**
+ * 两个时间相差距离多少天多少小时多少分多少秒
+ *
+ * @param str1 时间参数 1 格式:1990-01-01 12:00:00
+ * @param str2 时间参数 2 格式:2009-01-01 12:00:00
+ * @return long[] 返回值为:{天, 时, 分, 秒}
+ */
+ public static long[] getDistanceTimes(String str1, String str2) {
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date one;
+ Date two;
+ long day = 0;
+ long hour = 0;
+ long min = 0;
+ long sec = 0;
+ try {
+ one = df.parse(str1);
+ two = df.parse(str2);
+ long time1 = one.getTime();
+ long time2 = two.getTime();
+ long diff;
+ if (time1 < time2) {
+ diff = time2 - time1;
+ } else {
+ diff = time1 - time2;
+ }
+ day = diff / (24 * 60 * 60 * 1000);
+ hour = (diff / (60 * 60 * 1000) - day * 24);
+ min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
+ sec = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ long[] times = { day, hour, min, sec };
+ return times;
+ }
+
+ /**
+ * 将时间转换为时间戳
+ */
+ public static long dateToStamp2(String s) {
+ if (s.equals("0")) {
+ // 如果为空,则默认为当前时间
+ s = getCurrentLongDateTime();
+ }
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date;
+ try {
+ date = simpleDateFormat.parse(s);
+ long ts = date.getTime() / 1000;
+ return ts;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return new Date().getTime() / 1000;
+ }
+
+ /**
+ * 将时间戳转换为时间
+ */
+ public static String stampToDate2(long timeStamp) {
+ String result = null;
+ Date date = new Date(timeStamp * 1000);
+ SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ result = sd.format(date);
+ return result;
+ }
+
+ /**
+ * 加减日期
+ *
+ * @param date
+ * @param day
+ * @return
+ */
+ public static Date operDay(Date date, int day) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ Calendar rightNow = Calendar.getInstance();
+ rightNow.setTime(date);
+ rightNow.add(Calendar.DAY_OF_YEAR, day);
+ Date dt1 = rightNow.getTime();
+ return dt1;
+ }
+
+ /**
+ * 加减日期
+ *
+ * @param time 传入的String字符串
+ * @param day 加减多少天
+ * @param flag 加减类型标识,1=加减天数,2=加减小时
+ * @return
+ */
+ public static String operDay2(String time, int day, int flag) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH");
+ Date date = new Date();
+ try {
+ date = sdf.parse(time);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ Calendar rightNow = Calendar.getInstance();
+ rightNow.setTime(date);
+ if (flag == 1) {
+ rightNow.add(Calendar.DAY_OF_YEAR, day);
+ } else {
+ rightNow.add(Calendar.HOUR_OF_DAY, day);
+ }
+ Date dt1 = rightNow.getTime();
+ return sdf.format(dt1);
+ }
+
+ /**
+ * 将HH:mm:ss转变成秒数
+ *
+ * @param s
+ * @return
+ */
+ public static long toFormatSecond(String s) {
+ String[] time = s.split(":");
+ long hourToSecond = Integer.parseInt(time[0]) * 3600;
+ long minToSecond = Integer.parseInt(time[1]) * 60;
+ long second = Integer.parseInt(time[2]);
+ return hourToSecond + minToSecond + second;
+ }
+
+ public static long getStamp() {
+ return System.currentTimeMillis() / 1000;
+ }
+
+ public static void main(String[] args) {
+// /* System.out.println(stampToDate2(1517228653L)); */
+// System.out.println(DateUtil.getCurrentDateTimeMinutesSecond(-1440));
+// System.out.println(DateUtil.getCurrentDateTimeMinutesSecond(0));
+// System.out.println(DateUtil.getCurrentDateTimeSecond(-5));
+
+ System.out.println(getStamp());
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/StrUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/StrUtil.java
new file mode 100644
index 0000000..6ef2329
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/java/com/md/demo/util/StrUtil.java
@@ -0,0 +1,355 @@
+package com.md.demo.util;
+
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ * Title: StrUtil.java Description: 字符处理公共类
+
+ * 1.getFormData() 封装request请求参数为HashMap
+ * 2.getNoNullNewStr() 去NULL 用传入得参数代替
+ * 3.dateToString() 日期转化为字符串
+ * 4.datetimeToString() 日期时间转化为字符串
+ * 5.isEmpty() 判断字符串是否无效
+ * 6.strFormat() 字符串为空或去掉前后空格处理
+ * 7.isNumber() 判断是否数字
+ * 8.getOPERATEID() 生成受理号
+ * 9.encodeFileName() 将文件名进行转码,避免乱码
+ * 10.getFlowNo() 获取流水号(20位)
+ * 11.formatValue() 格式化值格式
+ *
+ */
+public class StrUtil {
+
+ /**
+ * 处理json解析不了的特殊字符
+ * @param paramValue
+ * @return
+ */
+ public static String transferString(String paramValue) {
+ if (!"".equals(paramValue) && paramValue != null) {
+ paramValue = paramValue.replaceAll("\"", "“");
+ //paramValue = paramValue.replaceAll("\"", "”");
+ paramValue = paramValue.replaceAll("\'", "‘");
+ paramValue = paramValue.replaceAll("\\\\", " ");
+ paramValue = paramValue.replaceAll("'", "‘");
+ paramValue = paramValue.replaceAll("\n", " ");
+ paramValue = paramValue.replaceAll("\r", " ");
+ //paramValue = paramValue.replaceAll("\'", "’");
+ }
+ return paramValue;
+ }
+ /*********
+ * 处理工单流转备注
+ * @param paramValue
+ * @return
+ * @author xiaojianfeng
+ * @updateDate:2015-11-04
+ */
+ public static String transFerStringMemo(String paramValue){
+ if (!"".equals(paramValue) && paramValue != null) {
+ paramValue = paramValue.replaceAll("\"", "“");
+ paramValue = paramValue.replaceAll("\'", "‘");
+ paramValue = paramValue.replaceAll("\\\\", " ");
+ paramValue = paramValue.replaceAll("'", "‘");
+ paramValue = paramValue.replaceAll("\r\n", "
");
+ }
+ return paramValue;
+ }
+
+ /**
+ * 去NULL 用传入得参数代替
+ * @param oldStr
+ * @param rel
+ * @return
+ */
+ public static String getNoNullNewStr(String oldStr, String rel) {
+ String newStr = (oldStr == null ? rel : oldStr.trim());
+ return newStr;
+ }
+
+ /**
+ * 日期转化为字符串
+ * @param date 日期
+ * @return 如:2015-01-08
+ * @throws Exception
+ */
+ public static String dateToString(Date date) throws Exception {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ return sdf.format(date);
+ }
+ /**
+ * 日期时间转化为字符串
+ * @param date 日期时间
+ * @return 如:2015-01-08 12:12:12
+ * @throws Exception
+ */
+ public static String datetimeToString(Date date) throws Exception {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
+ return sdf.format(date);
+ }
+
+ //add by zhangdulong 20150917 增加替换掉特殊字符
+ public static final String filterHF(Object out) {
+
+ if (out == null || out.toString().length() == 0)
+ return "";
+ String sout = out.toString();
+ StringBuffer sb = new StringBuffer();
+ char ch = ' ';
+ for (int i = 0; i < sout.length(); i++) {
+ ch = sout.charAt(i);
+ if (ch == '<') {
+ sb.append("<");
+ } else if (ch == '>') {
+ sb.append(">");
+ } else if (ch == '&') {
+ sb.append("&");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'"); // ´
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ public static final String filterHF(String out) {
+ if (out == null || out.length() == 0)
+ return out;
+ StringBuffer sb = new StringBuffer();
+ char ch = ' ';
+ for (int i = 0; i < out.length(); i++) {
+ ch = out.charAt(i);
+ if (ch == '<') {
+ sb.append("<");
+ } else if (ch == '>') {
+ sb.append(">");
+ } else if (ch == '&') {
+ sb.append("&");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'"); // ´
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+ public static final String filterSS(String out) {
+ if (out == null || out.length() == 0)
+ return out;
+ StringBuffer sb = new StringBuffer();
+ char ch = ' ';
+ for (int i = 0; i < out.length(); i++) {
+ ch = out.charAt(i);
+ if (ch == '&') {
+ sb.append("&");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'"); // ´
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+ /**
+ * 去掉字符串前后空格
+ * @param sValue
+ * @return
+ */
+ public static String getString(String sValue) {
+ return (sValue == null) ? "" : sValue.trim();
+ }
+
+ // 必须是|1|2|3|否则最后一个为&ERROR&
+ static public String getFieldData(String AString, int Index, char Dilimiter) {
+ int p1, p2;
+ int count;
+ p1 = 0;
+ p2 = 0;
+ count = 0;
+ if (AString == null)
+ AString = "";
+ for (int i = 0; i < AString.length(); i++) {
+ if (AString.charAt(i) == Dilimiter) {
+ p2 = p1;
+ p1 = i + 1;
+ count++;
+ }
+ if (count == Index) {
+ break;
+ }
+ }
+
+ if ((p1 > 0) && (count == Index))
+ return AString.substring(p2, p1 - 1).trim();
+ else
+ return "&ERROR&";
+ }
+
+ /**
+ * 判断字符串是否无效
+ * @param str
+ * @return
+ */
+ public static boolean isEmpty(String str) {
+ if (null == str || "".equals(str.trim()) || "null".equals(str.trim())
+ || "NULL".equals(str.trim())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ /**
+ * 字符串为空或去掉前后空格处理
+ * @param str
+ * @return
+ */
+ public static String strFormat(String str) {
+ if (null == str || "".equals(str.trim()) || "null".equals(str.trim())
+ || "NULL".equals(str.trim())) {
+ return "";
+ } else {
+ return str.trim();
+ }
+ }
+
+ /**
+ * 校验输入串是否为数字
+ * @param str
+ * @return
+ */
+ public static boolean isNumber(String str) {
+ boolean rtn = true;
+ String array[] = str.split("");// 将字符串转换为字符串数组,以""为分隔符来转换字符串。注:array[0]=""
+ int length = array.length;
+ for (int i = 1; i < length; i++) { // 从array[1]开始判断
+ int code = array[i].hashCode(); // 获得ASCII码
+ // 如果array[i]为数字
+ if (code >= 48 && code <= 57) { // 判断是否为数字
+ continue;
+ } else {
+ rtn = false;
+ break;
+ }
+ }
+
+ return rtn;
+ }
+
+ /**
+ * 生成受理号
+ *
+ * @param OPERATETYPE
+ * 工单编号
+ * @param flowno
+ * 流水号
+ * @return String
+ * */
+ public static String getOPERATEID(String OPERATETYPE, String flowno) {
+
+ String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
+ StringBuffer sb = new StringBuffer(date);
+ sb.append(OPERATETYPE).append(flowno);
+ return sb.toString();
+
+ }
+
+ /**
+ * 将文件名进行转码,避免乱码
+ * @param request
+ * @param fileName
+ * @author xiajia
+ * @return
+ */
+ public static String encodeFileName(HttpServletRequest request,
+ String fileName) {
+// String agent = request.getHeader("USER-AGENT");
+// try {
+// if (null != agent && -1 != agent.indexOf("MSIE")) {
+// return URLEncoder.encode(fileName, "UTF-8");
+// } else if (null != agent && -1 != agent.indexOf("Mozilla")) {
+// return "=?UTF-8?B?"
+// + new String(Base64.encodeBase64(fileName
+// .getBytes("UTF-8"))) + "?=";
+// } else {
+// return fileName;
+// }
+// } catch (UnsupportedEncodingException e) {
+// }
+ return "";
+ }
+
+ /**
+ * 1.将null对象返回空字符串-“""”
+ * 2.若非null对象返回toString()及trim字符串
+ *
+ * @param origin
+ * String
+ * @return String
+ */
+ public static String null2Str(Object origin) {
+ return (origin == null ? "" : origin.toString().trim()).replace("null", "");
+ }
+
+ /**
+ * 格式化值格式
+ * @param value 值
+ * @param valueFormat 值格式(保留2位小数,若显示88.00%,则传入0.00%;若显示88.88,则传入0.00。以此类推!)
+ * @author xuwei
+ * @return
+ */
+ public static String formatValue(String value,String valueFormat){
+ String digits = "";//默认0位,即取整数
+ NumberFormat numberFormat = null;
+ if(valueFormat.indexOf("%") > 0){
+ //带%值格式
+ digits = valueFormat.substring(0, valueFormat.indexOf("%"));//去掉%
+ numberFormat = NumberFormat.getPercentInstance();
+ }else{
+ //不带%值格式
+ digits = valueFormat;
+ numberFormat = NumberFormat.getNumberInstance();
+ }
+ if(digits.indexOf(".") > 0){
+ //含小数点,取小数点后面的位数
+ digits = digits.substring(digits.indexOf(".")+1, digits.length());
+ }else{
+ digits = "";
+ }
+
+ int decimals = digits.length();//小数位数
+ numberFormat.setMinimumFractionDigits(decimals);
+ numberFormat.setMaximumFractionDigits(decimals);
+ numberFormat.setGroupingUsed(false);//不千分位显示
+ return numberFormat.format(Double.parseDouble(value));
+ }
+
+ public static String parseSosMgTyp(String mgTyp){
+ if(mgTyp.indexOf("Sos")>0){
+ return "求助";
+ }else if(mgTyp.indexOf("Fire")>0){
+ return "火警";
+ }else if(mgTyp.indexOf("Aleak")>0){
+ return "漏水";
+ }else if(mgTyp.indexOf("Hijack")>0){
+ return "被劫持";
+ }else if(mgTyp.indexOf("War")>0){
+ return "预警";
+ }else if(mgTyp.indexOf("Alm")>0){
+ return "报警";
+ }
+ return "未知";
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-alipay/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/README.md
new file mode 100644
index 0000000..2439b7a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/README.md
@@ -0,0 +1,40 @@
+# spring-boot2-api-protect
+
+【接口防刷机制】技术点
+
+功能介绍
+
+1. 接口防刷机制用法
+
+策略逻辑:
+
+1. 可以在参数中增加一个动态随机字符参数,比如sId,每次请求时,对方都需要动态生成一个十位随机字符,防止sign值一直固化不变
+2. 同时,服务器可以校验请求是否重复,比如可以通过redis存储已请求过的rId,每请求一次就需要重新生成一个新的rId(可设置过期时间,以免一直存储历史的rId值),防止别人利用固定请求链接刷请求
+3. 可以使用公网ip,限制同一个ip访问次数(也可以在nginx层做限制,这个自行网上了解了)
+
+## 本项目教程
+
+[接口防刷机制](https://hemin.blog.csdn.net/article/details/99637749)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/pom.xml
new file mode 100644
index 0000000..208790a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-api-protect
+ jar
+
+ spring-boot2-api-protect
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..8dc85c3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,68 @@
+package com.md.demo.rest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+import com.md.demo.util.sign.NetworkUtil;
+import com.md.demo.util.sign.SignUtil;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-api-protect";
+ }
+
+ /**
+ * 利用秘钥生成签名(只有对方知,服务器知),校验请求源合法性,不同源可以设置不同的秘钥
+ */
+ private static final String API_SECRET_KEY = "996";;
+
+ /**
+ * http://localhost:9090/test?name=minbo&age=100&sign=495FC6F52324AB1460C95A27803E3A4A
+ *
+ * @param name
+ * @param age
+ * @param sign 大写
+ * @return
+ */
+ @GetMapping("/test")
+ public JsonResult test(String name, Integer age, String sign, HttpServletRequest request) {
+ // 1. 还可以在参数中增加一个动态随机字符参数,比如sId,每次请求时,对方都需要动态生成一个十位随机字符,防止sign值一直固化不变
+ // 2. 同时,服务器可以校验请求是否重复,比如可以通过redis存储已请求过的rId(可设置过期时间,以免一直存储历史的rId值),防止别人利用固定请求链接刷请求
+ // 3. 可以使用公网ip,限制同一个ip访问次数(也可以在nginx层做限制,这个自行网上了解了)
+
+// // 获取公网ip
+// String sIp = NetworkUtil.getIpAddress(request);
+// System.out.println("sIp=" + sIp);
+
+ Map params = new HashMap();
+ params.put("name", name);
+ params.put("age", age);
+ String serverSign = SignUtil.signByMD5(params, API_SECRET_KEY);
+ if (serverSign.equals(sign)) {
+ return new JsonResult(ResultCode.SUCCESS, "签名通过");
+ }
+ return new JsonResult(ResultCode.SUCCESS_FAIL, "非法请求");
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/MD5Util.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/MD5Util.java
new file mode 100644
index 0000000..949a553
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/MD5Util.java
@@ -0,0 +1,57 @@
+package com.md.demo.util.sign;
+
+import java.security.MessageDigest;
+import java.text.ParseException;
+
+public class MD5Util {
+
+ // 十六进制下数字到字符的映射数组
+ private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
+ "e", "f" };
+
+ /** 对字符串进行MD5加密 */
+ public static String encodeByMD5(String originString) {
+ if (originString != null && originString != "") {
+ try {
+ // 创建具有指定算法名称的信息摘要
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ // 使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
+ byte[] results = md.digest(originString.getBytes());
+ // 将得到的字节数组变成字符串返回
+ String resultString = byteArrayToHexString(results);
+ return resultString.toLowerCase();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 转换字节数组为十六进制字符串
+ *
+ * @param 字节数组
+ * @return 十六进制字符串
+ */
+ private static String byteArrayToHexString(byte[] b) {
+ StringBuffer resultSb = new StringBuffer();
+ for (int i = 0; i < b.length; i++) {
+ resultSb.append(byteToHexString(b[i]));
+ }
+ return resultSb.toString();
+ }
+
+ /** 将一个字节转化成十六进制形式的字符串 */
+ private static String byteToHexString(byte b) {
+ int n = b;
+ if (n < 0)
+ n = 256 + n;
+ int d1 = n / 16;
+ int d2 = n % 16;
+ return hexDigits[d1] + hexDigits[d2];
+ }
+
+ public static void main(String[] args) throws ParseException {
+ System.out.println(encodeByMD5("abc123"));
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/NetworkUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/NetworkUtil.java
new file mode 100644
index 0000000..9595b63
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/NetworkUtil.java
@@ -0,0 +1,239 @@
+package com.md.demo.util.sign;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class NetworkUtil {
+
+ /**
+ * 获取用户真实IP地址
+ *
+ * @param request
+ * @return
+ */
+ public static String getIpAddress(HttpServletRequest request) {
+ String ip = request.getHeader("x-forwarded-for");
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ // 不管转发多少次,取第一位
+ return ip.split(",")[0];
+ }
+
+ /**
+ * 获取来访者的浏览器版本
+ *
+ * @param request
+ * @return
+ */
+ public static String getRequestBrowserInfo(HttpServletRequest request) {
+ String browserVersion = null;
+ String header = request.getHeader("user-agent");
+ if (header == null || header.equals("")) {
+ return "";
+ }
+ if (header.indexOf("MSIE") > 0) {
+ browserVersion = "IE";
+ } else if (header.indexOf("Firefox") > 0) {
+ browserVersion = "Firefox";
+ } else if (header.indexOf("Chrome") > 0) {
+ browserVersion = "Chrome";
+ } else if (header.indexOf("Safari") > 0) {
+ browserVersion = "Safari";
+ } else if (header.indexOf("Camino") > 0) {
+ browserVersion = "Camino";
+ } else if (header.indexOf("Konqueror") > 0) {
+ browserVersion = "Konqueror";
+ }
+ return browserVersion;
+ }
+
+ /**
+ * 获取系统版本信息
+ *
+ * @param request
+ * @return
+ */
+ public static String getRequestSystemInfo(HttpServletRequest request) {
+ String systenInfo = null;
+ String header = request.getHeader("user-agent");
+ if (header == null || header.equals("")) {
+ return "";
+ }
+ // 得到用户的操作系统
+ if (header.indexOf("NT 6.0") > 0) {
+ systenInfo = "Windows Vista/Server 2008";
+ } else if (header.indexOf("NT 5.2") > 0) {
+ systenInfo = "Windows Server 2003";
+ } else if (header.indexOf("NT 5.1") > 0) {
+ systenInfo = "Windows XP";
+ } else if (header.indexOf("NT 6.0") > 0) {
+ systenInfo = "Windows Vista";
+ } else if (header.indexOf("NT 6.1") > 0) {
+ systenInfo = "Windows 7";
+ } else if (header.indexOf("NT 6.2") > 0) {
+ systenInfo = "Windows Slate";
+ } else if (header.indexOf("NT 6.3") > 0) {
+ systenInfo = "Windows 9";
+ } else if (header.indexOf("NT 5") > 0) {
+ systenInfo = "Windows 2000";
+ } else if (header.indexOf("NT 4") > 0) {
+ systenInfo = "Windows NT4";
+ } else if (header.indexOf("Me") > 0) {
+ systenInfo = "Windows Me";
+ } else if (header.indexOf("98") > 0) {
+ systenInfo = "Windows 98";
+ } else if (header.indexOf("95") > 0) {
+ systenInfo = "Windows 95";
+ } else if (header.indexOf("Mac") > 0) {
+ systenInfo = "Mac";
+ } else if (header.indexOf("Unix") > 0) {
+ systenInfo = "UNIX";
+ } else if (header.indexOf("Linux") > 0) {
+ systenInfo = "Linux";
+ } else if (header.indexOf("SunOS") > 0) {
+ systenInfo = "SunOS";
+ }
+ return systenInfo == null ? header : systenInfo;
+ }
+
+ /**
+ * 获取来访者的主机名称
+ *
+ * @param ip
+ * @return
+ */
+ public static String getHostName(String ip) {
+ InetAddress inet;
+ try {
+ inet = InetAddress.getByName(ip);
+ return inet.getHostName();
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 命令获取mac地址
+ *
+ * @param cmd
+ * @return
+ */
+ private static String callCmd(String[] cmd) {
+ String result = "";
+ String line = "";
+ try {
+ Process proc = Runtime.getRuntime().exec(cmd);
+ InputStreamReader is = new InputStreamReader(proc.getInputStream());
+ BufferedReader br = new BufferedReader(is);
+ while ((line = br.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * @param cmd 第一个命令
+ * @param another 第二个命令
+ * @return 第二个命令的执行结果
+ */
+ private static String callCmd(String[] cmd, String[] another) {
+ String result = "";
+ String line = "";
+ try {
+ Runtime rt = Runtime.getRuntime();
+ Process proc = rt.exec(cmd);
+ proc.waitFor(); // 已经执行完第一个命令,准备执行第二个命令
+ proc = rt.exec(another);
+ InputStreamReader is = new InputStreamReader(proc.getInputStream());
+ BufferedReader br = new BufferedReader(is);
+ while ((line = br.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * @param ip 目标ip,一般在局域网内
+ * @param sourceString 命令处理的结果字符串
+ * @param macSeparator mac分隔符号
+ * @return mac地址,用上面的分隔符号表示
+ */
+ private static String filterMacAddress(final String ip, final String sourceString, final String macSeparator) {
+ String result = "";
+ String regExp = "((([0-9,A-F,a-f]{1,2}" + macSeparator + "){1,5})[0-9,A-F,a-f]{1,2})";
+ Pattern pattern = Pattern.compile(regExp);
+ Matcher matcher = pattern.matcher(sourceString);
+ while (matcher.find()) {
+ result = matcher.group(1);
+ if (sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group(1))) {
+ break; // 如果有多个IP,只匹配本IP对应的Mac.
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @param ip 目标ip
+ * @return Mac Address
+ */
+ private static String getMacInWindows(final String ip) {
+ String result = "";
+ String[] cmd = { "cmd", "/c", "ping " + ip };
+ String[] another = { "cmd", "/c", "arp -a" };
+ String cmdResult = callCmd(cmd, another);
+ result = filterMacAddress(ip, cmdResult, "-");
+ return result;
+ }
+
+ /**
+ * @param ip 目标ip
+ * @return Mac Address
+ */
+ private static String getMacInLinux(final String ip) {
+ String result = "";
+ String[] cmd = { "/bin/sh", "-c", "ping " + ip + " -c 2 && arp -a" };
+ String cmdResult = callCmd(cmd);
+ result = filterMacAddress(ip, cmdResult, ":");
+ return result;
+ }
+
+ /**
+ * 获取MAC地址
+ *
+ * @return 返回MAC地址
+ */
+ public static String getMacAddress(String ip) {
+ String macAddress = "";
+ macAddress = getMacInWindows(ip).trim();
+ if (macAddress == null || "".equals(macAddress)) {
+ macAddress = getMacInLinux(ip).trim();
+ }
+ return macAddress;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/SignUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/SignUtil.java
new file mode 100644
index 0000000..2fd2640
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/java/com/md/demo/util/sign/SignUtil.java
@@ -0,0 +1,104 @@
+package com.md.demo.util.sign;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 签名工具类
+ */
+public class SignUtil {
+
+ protected static Logger logger = LoggerFactory.getLogger(SignUtil.class);
+
+ /**
+ * 算法实现 将参数集合按照参数名的ASCII排列 把排序后的结果按照【参数+参数值 +
+ * &】的方式拼接,再加上secretKey=secretKeyValue
+ * 拼装好的字符串按MD5(p1=v1&p2=v2&p3=v3&secretKey=secretKeyValue)进行md5加密后,转大写
+ *
+ * @param params 参数集合(必须)
+ * @param secretKey 秘钥(必须)
+ * @return
+ */
+ public static String signByMD5(Map params, String secretKey) {
+ // 将参数集合按照参数名首字母先后顺序排列
+ SortedMap sortParamMap = SignUtil.sortMap(params);
+ // 把排序后的结果按照参数+参数值的方式拼接
+ // 拼装好的字符串按secretKey进行md5加密后,转大写
+ return SignUtil.createSign(sortParamMap, secretKey);
+ }
+
+ /**
+ * 把排序后的结果按照【参数+参数值 + &】的方式拼接,再加上secretKey=secretKeyValue
+ * 拼装好的字符串按MD5(p1=v1&p2=v2&p3=v3&secretKey=secretKeyValue)进行md5加密后,转大写
+ *
+ * @param parameters
+ * @param secretKey
+ * @return
+ */
+ private static String createSign(Map parameters, String secretKey) {
+ StringBuffer sb = new StringBuffer();
+ Iterator> it = parameters.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry) it.next();
+ String key = (String) entry.getKey();
+ Object value = entry.getValue();
+ // 去掉带sign的项
+ if (null != value && !"".equals(value) && !"sign".equals(key) && !"secretKey".equals(key)) {
+ sb.append(key + "=" + value + "&");
+ }
+ }
+ sb.append("secretKey=" + secretKey);
+ // 注意sign转为大写
+ return MD5Util.encodeByMD5(sb.toString()).toUpperCase();
+ }
+
+ /**
+ * 按首字母排列
+ *
+ * @param map
+ * @return
+ */
+ public static SortedMap sortMap(Map map) {
+ List> infoIds = new ArrayList>(map.entrySet());
+ // 排序
+ Collections.sort(infoIds, new Comparator>() {
+ public int compare(Map.Entry o1, Map.Entry o2) {
+ // 按首字母比对
+ return (String.valueOf(o1.getKey().charAt(0))).compareTo(String.valueOf(o2.getKey().charAt(0)));
+ }
+ });
+ // 排序后
+ SortedMap sortmap = new TreeMap();
+ // 根据key进行排序ASCII顺序
+ System.out.println(infoIds.toString());
+ for (int i = 0; i < infoIds.size(); i++) {
+ String[] split = infoIds.get(i).toString().split("=");
+ if (split.length == 1) {
+ sortmap.put(split[0], null);
+ continue;
+ }
+ sortmap.put(split[0], split[1]);
+ }
+ return sortmap;
+ }
+
+ public static void main(String[] args) {
+ Map params = new HashMap();
+ params.put("name", "minbo");
+ params.put("age", 100);
+ String secretKey = "996";
+ String sign = SignUtil.signByMD5(params, secretKey);
+ System.out.println(sign);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-api-protect/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/README.md
new file mode 100644
index 0000000..ab17fe4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/README.md
@@ -0,0 +1,36 @@
+# sprint-boot2-autotest
+
+【自动化测试】技术点
+
+功能介绍
+
+1. 如何编写单元测试案例,具体用法有哪些
+2. 单元测试场景:四种业务场景,例如如何进行接口api测试,服务层代码测试,MockMvc用法等
+
+## 本项目教程
+
+[如何进行单元测试编写和场景案例分析](https://blog.csdn.net/hemin1003/article/details/90214986)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/pom.xml
new file mode 100644
index 0000000..b52e10b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/pom.xml
@@ -0,0 +1,91 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ sprint-boot2-autotest
+ jar
+
+ sprint-boot2-autotest
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ io.qameta.allure
+ allure-junit4
+ 2.12.0
+ test
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+ **/*Test.java
+
+
+
+ **/Test*.java
+
+ false
+
+ -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
+
+
+
+ listener
+ io.qameta.allure.junit4.AllureJunit4
+
+
+
+
+
+ org.aspectj
+ aspectjweaver
+ ${aspectj.version}
+
+
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..3ebd755
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,19 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..6c26588
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,20 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello,greetings from sprint-boot2-autotest";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/service/DemoService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/service/DemoService.java
new file mode 100644
index 0000000..8bfef31
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/service/DemoService.java
@@ -0,0 +1,6 @@
+package com.md.demo.service;
+
+public interface DemoService {
+
+ public String sayHello();
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java
new file mode 100644
index 0000000..c98c89e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java
@@ -0,0 +1,15 @@
+package com.md.demo.service.impl;
+
+import org.springframework.stereotype.Service;
+
+import com.md.demo.service.DemoService;
+
+@Service
+public class DemoServiceImpl implements DemoService {
+
+ @Override
+ public String sayHello() {
+ return "hello from service layer";
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/resources/application.yml
new file mode 100644
index 0000000..2ea1b3e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+# tomcat
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/resources/logback.xml
new file mode 100644
index 0000000..0adec0a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationJavaTest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationJavaTest.java
new file mode 100644
index 0000000..fd69682
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationJavaTest.java
@@ -0,0 +1,46 @@
+package com.md.demo;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import junit.framework.TestCase;
+
+/**
+ * 普通Java测试,比如配置参数加载,静态方法返回值等
+ *
+ * @author Minbo
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = { ApplicationJavaTest.class }) // 指定启动类
+public class ApplicationJavaTest {
+
+ protected static Logger logger = LoggerFactory.getLogger(ApplicationJavaTest.class);
+
+ @Test
+ public void testOne() {
+ logger.info("test hello 1");
+ }
+
+ @Test
+ public void testTwo() {
+ logger.info("test hello 2");
+ TestCase.assertEquals(1, 1);
+ }
+
+ @Before
+ public void testBefore() {
+ logger.info("before");
+ }
+
+ @After
+ public void testAfter() {
+ logger.info("after");
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationMockTest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationMockTest.java
new file mode 100644
index 0000000..099aac9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationMockTest.java
@@ -0,0 +1,72 @@
+package com.md.demo;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+/**
+ * 使用MockMvc测试接口
+ *
+ * @author Minbo
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class) // 指定启动类
+@AutoConfigureMockMvc // 测试接口用
+@WebAppConfiguration
+public class ApplicationMockTest {
+
+ protected static Logger logger = LoggerFactory.getLogger(ApplicationMockTest.class);
+
+ @Autowired
+ private MockMvc mockMvc;
+ @Autowired
+ private WebApplicationContext context;
+
+ @Before
+ public void setupMockMvc() throws Exception {
+ mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
+ }
+
+ @Before
+ public void testBefore() {
+ logger.info("测试前,打印...");
+ }
+
+ @After
+ public void testAfter() {
+ logger.info("测试后,打印...");
+ }
+
+ @Test
+ public void apiTest() throws Exception {
+ String url = "/hello";
+ String expectResult = "Hello,greetings from sprint-boot2-autotest";
+
+ MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get(url))
+ // 期望:200成功状态码
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ // 期望:返回结果数据
+ .andExpect(MockMvcResultMatchers.content().string(expectResult)).andReturn();
+
+ int status = mvcResult.getResponse().getStatus();
+ logger.info("返回状态码status=" + status);
+
+ String content = mvcResult.getResponse().getContentAsString();
+ logger.info("返回结果数据content=" + content);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationWebApiTest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationWebApiTest.java
new file mode 100644
index 0000000..ea86068
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationWebApiTest.java
@@ -0,0 +1,67 @@
+package com.md.demo;
+
+import java.net.URL;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import junit.framework.TestCase;
+
+/**
+ * 普通Web接口测试
+ *
+ * @author Minbo
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) // 指定启动类和随机端口
+public class ApplicationWebApiTest {
+
+ protected static Logger logger = LoggerFactory.getLogger(ApplicationWebApiTest.class);
+
+ /**
+ * @LocalServerPort 提供了 @Value("${local.server.port}") 的代替
+ */
+ @LocalServerPort
+ private int port;
+
+ private URL base;
+
+ @Autowired
+ private TestRestTemplate restTemplate;
+
+ @Before
+ public void setUp() throws Exception {
+ String url = String.format("http://localhost:%d/", port);
+ logger.info("随机自动分配端口后的整体请求头--->>> " + url);
+ this.base = new URL(url);
+ }
+
+ /**
+ * 向"/hello"地址发送请求,并打印返回结果
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testUrlApi() throws Exception {
+ String url = this.base.toString() + "/hello";
+ logger.info("待测试接口地址:url=" + url);
+ ResponseEntity response = this.restTemplate.getForEntity(url, String.class, "");
+ String result = response.getBody();
+ logger.info("返回结果:result=" + result);
+ boolean expected = false;
+ if (result != null && result.contains("sprint-boot2-autotest")) {
+ expected = true;
+ }
+ TestCase.assertEquals(true, expected);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationWebServiceTest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationWebServiceTest.java
new file mode 100644
index 0000000..584c881
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/ApplicationWebServiceTest.java
@@ -0,0 +1,45 @@
+package com.md.demo;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.md.demo.service.DemoService;
+
+import junit.framework.TestCase;
+
+/**
+ * 普通业务服务层测试
+ *
+ * @author Minbo
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class) // 指定启动类
+public class ApplicationWebServiceTest {
+
+ protected static Logger logger = LoggerFactory.getLogger(ApplicationWebServiceTest.class);
+
+ @Autowired
+ private DemoService demoService;
+
+ /**
+ * 测试方法
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testService() throws Exception {
+ // 检查入口配置是否正确
+ String result = this.demoService.sayHello();
+ logger.info("实际返回结果result=" + result);
+
+ TestCase.assertNotNull(result);
+ String expected = "hello from service layer";
+ TestCase.assertEquals(expected, result);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/README.md
new file mode 100644
index 0000000..95044a7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/java/com/md/demo/README.md
@@ -0,0 +1,23 @@
+@SpringBootTest注解底层实际上还是使用了Junit框架
+
+Junit基本注解介绍
+
+@BeforeClass 在所有测试方法前执行一次,一般在其中写上整体初始化的代码
+
+@AfterClass 在所有测试方法后执行一次,一般在其中写上销毁和释放资源的代码
+
+@Before 在每个测试方法前执行,一般用来初始化方法(比如我们在测试别的方法时,类中与其他测试方法共享的值已经被改变,为了保证测试结果的有效性,我们会在@Before注解的方法中重置数据)
+
+@After 在每个测试方法后执行,在方法执行完成后要做的事情
+
+@Test(timeout = 1000) 测试方法执行超过1000毫秒后算超时,测试将失败
+
+@Test(expected = Exception.class) 测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败
+
+@Ignore(“not ready yet”) 执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类
+
+@Test 编写一般测试用例
+
+@RunWith 在JUnit中有很多个Runner,他们负责调用你的测试代码,每一个Runner都有各自的特殊功能,你要根据需要选择不同的Runner来运行你的测试代码。
+
+如果只是简单的做普通Java测试,不涉及Spring Web项目,你可以省略@RunWith注解,这样系统会自动使用默认Runner来运行你的代码。
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/resources/application.yml
new file mode 100644
index 0000000..2ea1b3e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-autotest/src/test/resources/application.yml
@@ -0,0 +1,3 @@
+# tomcat
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/README.md
new file mode 100644
index 0000000..83704e9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-crawler
+
+【爬虫框架集成】技术点
+
+功能介绍
+
+1. 爬虫框架集成
+
+## 本项目教程
+
+[爬虫框架集成](https://hemin.blog.csdn.net/article/details/104615208)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/pom.xml
new file mode 100644
index 0000000..71a2487
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-crawler
+ jar
+
+ spring-boot2-crawler
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+ us.codecraft
+ webmagic-extension
+ 0.6.0
+
+
+ org.nlpcn
+ nlp-lang
+ 1.7
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..a877347
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,49 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+@EnableScheduling
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/ScheduleConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/ScheduleConfig.java
new file mode 100644
index 0000000..caa0fa6
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/ScheduleConfig.java
@@ -0,0 +1,21 @@
+package com.md.demo;
+
+import java.util.concurrent.Executors;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+/**
+ * 多线程实现并发定时
+ *
+ * @author Minbo
+ */
+@Configuration
+public class ScheduleConfig implements SchedulingConfigurer {
+
+ @Override
+ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+ taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/crawler/test/MyPageProcessor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/crawler/test/MyPageProcessor.java
new file mode 100644
index 0000000..8cb0a91
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/crawler/test/MyPageProcessor.java
@@ -0,0 +1,75 @@
+package com.md.demo.crawler.test;
+
+import java.util.List;
+
+import org.nlpcn.commons.lang.finger.SimHashService;
+
+import lombok.extern.slf4j.Slf4j;
+import us.codecraft.webmagic.Page;
+import us.codecraft.webmagic.Site;
+import us.codecraft.webmagic.Spider;
+import us.codecraft.webmagic.processor.PageProcessor;
+import us.codecraft.webmagic.selector.JsonPathSelector;
+
+/**
+ * 官方地址:http://webmagic.io/
+ *
+ * WebMagic是一个简单灵活的Java爬虫框架。基于WebMagic,你可以快速开发出一个高效、易维护的爬虫。
+ *
+ * @author Minbo
+ *
+ */
+@Slf4j
+public class MyPageProcessor implements PageProcessor {
+
+ private Site site = Site.me();
+
+ @Override
+ public void process(Page page) {
+ // 这里使用了jsonPath,因为今日头条返回的是json数据格式。如果是html内容,则使用xpath
+
+ // 第一层解析
+ String json = page.getRawText();
+ List data = new JsonPathSelector("$.data").selectList(json);
+ // 第二层解析
+ for (int i = 0; i < data.size(); i++) {
+ String result = data.get(i);
+ // 文章ID
+ String item_id = new JsonPathSelector("$.item_id").select(result);
+ // 文章标题
+ String title = new JsonPathSelector("$.title").select(result);
+ // 是否有图
+ String has_image = new JsonPathSelector("$.has_image").select(result);
+ // 文章来源
+ String source = new JsonPathSelector("$.source").select(result);
+ // 文章时间
+ String datetime = new JsonPathSelector("$.datetime").select(result);
+ // 一般是根据文章详细内容生成内容指纹id,实现文章去重,这里只是举例说明拿了文章标题
+ // 更多阅读我的博客文章:https://blog.csdn.net/hemin1003/article/details/82819489(【应用算法】信息流-推荐系统的去重策略)
+ String fPrintId = String.valueOf(new SimHashService().fingerprint(title));
+
+ log.info("");
+ log.info("---------->>> 提取文章主信息:");
+ log.info("文章ID item_id=" + item_id);
+ log.info("文章标题 title=" + title);
+ log.info("是否有图 has_image=" + has_image);
+ log.info("文章来源 source=" + source);
+ log.info("文章时间 datetime=" + datetime);
+ log.info("内容指纹id fPrintId=" + fPrintId);
+
+ // webmagic官方还有很多案例,更多内容自行参考学习了,例如配置代理,自带url去重、网页去重等功能
+ // 官方文档地址:http://webmagic.io/docs/zh/
+ }
+ }
+
+ public Site getSite() {
+ return MySite.getSit(site);
+ }
+
+ public static void main(String[] args) {
+ // 今日头条/热点数据url
+ Spider.create(new MyPageProcessor()).addUrl(
+ "https://m.toutiao.com/list/?tag=news_hot&ac=wap&count=20&format=json_raw&as=A1551E75BC4CF9C&cp=5E5C3CEFB9DCAE1&max_behot_time=1583123351&_signature=CXZIuwAAVy.txcPhjSEcTwl2SK&i=1583123351")
+ .thread(1).run();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/crawler/test/MySite.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/crawler/test/MySite.java
new file mode 100644
index 0000000..036afa8
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/crawler/test/MySite.java
@@ -0,0 +1,35 @@
+package com.md.demo.crawler.test;
+
+import us.codecraft.webmagic.Site;
+
+/**
+ * 模拟请求头设置
+ *
+ * @author Minbo
+ *
+ */
+public class MySite {
+
+ // 设置请求头
+ public static Site getSit(Site site) {
+ site.addHeader("Accept", "*/*");
+ site.addHeader("Accept-Encoding", "gzip, deflate, br");
+ site.addHeader("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6,cy;q=0.5");
+ site.addHeader("Connection", "keep-alive");
+ site.addHeader("Cookie",
+ "uuid=\"w:6eeae48e765542f8816b14bd1a8803f2\"; tt_webid=6799537520192783879; csrftoken=3eb88bcad1818058de0e3c0ca8a3f6d1; W2atIF=1; _ga=GA1.2.2115719807.1583140719; _gid=GA1.2.359266539.1583140719; __tasessionId=tr7vk2kgh1583140721519");
+ site.addHeader("Host", "m.toutiao.com");
+ site.addHeader("Referer", "https://m.toutiao.com/?w2atif=1&channel=news_hot");
+ site.addHeader("Sec-Fetch-Dest", "empty");
+ site.addHeader("Sec-Fetch-Mode", "cors");
+ site.addHeader("Sec-Fetch-Site", "same-origin");
+ site.addHeader("Upgrade-Insecure-Requests", "1");
+ site.addHeader("User-Agent",
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1");
+
+ site.setTimeOut(60000);
+ site.setCharset("UTF-8");
+ site.setRetryTimes(2);
+ return site;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/nlp/test/TestNlp.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/nlp/test/TestNlp.java
new file mode 100644
index 0000000..9f833f3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/nlp/test/TestNlp.java
@@ -0,0 +1,43 @@
+package com.md.demo.nlp.test;
+
+import org.nlpcn.commons.lang.finger.FingerprintService;
+import org.nlpcn.commons.lang.finger.SimHashService;
+
+/**
+ * 指纹去重库Github地址:https://github.com/hemin1003/nlp-lang
+ *
+ * 更多阅读:https://blog.csdn.net/hemin1003/article/details/82819489(【应用算法】信息流-推荐系统的去重策略)
+ *
+ * @author Minbo
+ */
+public class TestNlp {
+
+ /**
+ * 任何一段信息文字,都可以对应一个不太长的随机数,作为区别它和其它信息的指纹(Fingerprint)。
+ * 只要算法设计的好,任何两段信息的指纹都很难重复,就如同人类的指纹一样。信息指纹在加密、信息压缩和处理中有着广泛的应用。
+ * 这里的做法是文章抽取特征词,压缩为md5指纹。利用这些指纹进行hash去重。广泛应用在搜索结果、推荐结果去重。
+ */
+ public static void main(String[] args) {
+
+ String content = "卓尔防线继续伤筋动骨 队长梅方出场再补漏说起来卓尔队长梅方本赛季就是个“补漏”的命!在中卫与右边后卫间不停地轮换。如果不出意外,今天与广州恒大一战梅方又要换位置,这也是汉军队长连续三场比赛中的第三次换位。而从梅方的身上也可以看出,本赛季汉军防线如此“折腾”,丢球多也不奇怪了。梅方自2009赛季中乙出道便一直司职中后卫,还曾入选过布拉泽维奇国奥队,也是司职的中卫。上赛季,梅方与忻峰搭档双中卫帮助武汉卓尔队中超成功,但谁知进入本赛季后从第一场比赛开始梅方便不断因为种种“意外”而居无定所。联赛首战江苏舜天时,也是由于登贝莱受伤,朱挺位置前移,梅方临危受命客串右边后卫。第二轮主场与北京国安之战梅方仅仅打了一场中卫,又因为柯钊受罚停赛4轮而不得不再次到边路“补漏”。随着马丁诺维奇被弃用,梅方一度成为中卫首选,在与上海东亚队比赛中,邱添一停赛,梅方与忻峰再度携手,紧接着与申鑫队比赛中移至边路,本轮忻峰又停赛,梅方和邱添一成为中卫线上最后的选择。至于左右边后卫位置,卓尔队方面人选较多,罗毅、周恒、刘尚坤等人均可出战。记者马万勇原标题:卓尔防线继续伤筋动骨队长梅方出场再补漏稿源:中新网作者:";
+ String content2 = "在中卫与右边后卫间不停地轮换。卓尔防线继续伤筋动骨 队长梅方出场再补漏说起来卓尔队长梅方本赛季就是个“补漏”的命!还曾入选过布拉泽维奇国奥队,也是司职的中卫。上赛季,梅方与忻峰搭档双中卫帮助武汉卓尔队中超成功,但谁知进入本赛季后从第一场比赛开始梅方便不断因为种种“意外”而居无定所。";
+
+ // 方式1
+// String f1 = new FingerprintService().fingerprint(content);
+// String f2 = new FingerprintService().fingerprint(content2);
+// System.out.println(f1);
+// System.out.println(f2);
+// System.out.println(f1.equals(f2));
+
+ // 方式2
+ SimHashService service = new SimHashService();
+ String f3 = String.valueOf(service.fingerprint(content));
+ String f4 = String.valueOf(service.fingerprint(content2));
+ System.out.println(f3);
+ System.out.println(f4);
+ System.out.println(f3.equals(f4));
+
+// System.out.println(service.hmDistance(content, content2));
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..f006e50
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,26 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-crawler";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/task/ScheduledTasks.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/task/ScheduledTasks.java
new file mode 100644
index 0000000..303ef28
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/task/ScheduledTasks.java
@@ -0,0 +1,39 @@
+package com.md.demo.task;
+
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import com.md.demo.crawler.test.MyPageProcessor;
+
+import lombok.extern.slf4j.Slf4j;
+import us.codecraft.webmagic.Spider;
+
+@Component
+@Slf4j
+public class ScheduledTasks {
+
+ /**
+ * 每30秒执行一次
+ */
+ @Scheduled(initialDelay = 5000, fixedDelay = 30000)
+ public void httTaskOfWechatPay() {
+ log.info("------------------------------------------------");
+ log.info("============爬虫数据任务,start===================");
+
+ // TODO 在这里,你可以把爬虫做成执行计划任务,或者动态执行计划(通过db配置,或quartz框架,或XXL-job任务调度计划框架)
+
+ log.info("开始爬虫数据...");
+ log.info("处理处理...可以入库db,或存入es中");
+
+ // 爬今日头条/热点数据url
+ Spider.create(new MyPageProcessor()).addUrl(
+ "https://m.toutiao.com/list/?tag=news_hot&ac=wap&count=20&format=json_raw&as=A1551E75BC4CF9C&cp=5E5C3CEFB9DCAE1&max_behot_time=1583123351&_signature=CXZIuwAAVy.txcPhjSEcTwl2SK&i=1583123351")
+ .thread(1).run();
+
+ log.info("爬虫结束...done");
+
+ log.info("============爬虫数据任务,end===================");
+ log.info("------------------------------------------------");
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/DateUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/DateUtil.java
new file mode 100644
index 0000000..28793dd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/DateUtil.java
@@ -0,0 +1,632 @@
+package com.md.demo.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Random;
+
+import org.apache.commons.lang.time.DateUtils;
+
+/**
+ * 日期工具类
+ */
+/**
+ * @author CJS
+ *
+ */
+public final class DateUtil {
+
+ public static final int DATE_NUM = 0;
+
+ public static final String LONG_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+ public static final String LONG_DATETIME_FORMAT_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
+
+ public static final String LONGDATETIMEFORMAT = "yyyyMMddHHmmss";
+
+ public static final String DATETIMEFORMAT = "yyyyMMdd";
+
+ private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm";
+
+ private static final String DATETIME_FORMAT_HOURS = "yyyy-MM-dd HH";
+
+ private static final String DATE_FORMAT = "yyyy-MM-dd";
+
+ private static final String TIME_FORMAT = "HH:mm";
+
+ /**
+ * 获取指定月的对应天数
+ */
+ public static final int[] DAYS = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ /**
+ * convert to millisecond
+ */
+ public static final long TIME_ONE_HOUR = 3600L * 1000L;
+
+ public static final long TIME_ONE_DAY = 24L * TIME_ONE_HOUR;
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentLongDateTime() {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addHours(new Date(), DATE_NUM));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentLongDateTime(int num) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addDays(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd".
+ */
+ public static String getCurrentDate() {
+ return new SimpleDateFormat(DATE_FORMAT).format(DateUtils.addHours(new Date(), DATE_NUM));
+ }
+
+ public static String getCurrentDate(int num) {
+ return new SimpleDateFormat(DATE_FORMAT).format(DateUtils.addDays(new Date(), num));
+ }
+
+ /**
+ * 返回当前系统时间(字符串格式:yyyy-MM-dd HH:mm:ss)
+ *
+ * @return String
+ */
+ public static String getDateTime() {
+ Date d = DateUtils.addHours(new Date(), DATE_NUM);
+ SimpleDateFormat sdfreplay = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ String replytime = sdfreplay.format(d);
+ return replytime;
+ }
+
+ /**
+ * 返回一个随机数,组成格式"yyyyMMddhhmmss"+10000以内的随机数
+ *
+ * @return
+ */
+ public static String buildRandomFileName() {
+ Calendar cal = Calendar.getInstance();
+ SimpleDateFormat sdfreplay = new SimpleDateFormat("yyyyMMddHHmmss");
+ String replytime = sdfreplay.format(cal.getTime());
+ return replytime + new Random().nextInt(1000);
+ }
+
+ /**
+ * Convert date to String like "yyyyMMddHHmmss".
+ */
+ public static String getCurrentLongDateTime2() {
+ return new SimpleDateFormat(LONGDATETIMEFORMAT).format(new Date());
+ }
+
+ /**
+ * Convert date to String like "yyyyMMdd".
+ */
+ public static String getCurrentDate2(int num) {
+ return new SimpleDateFormat(DATETIMEFORMAT).format(DateUtils.addDays(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm".
+ */
+ public static String getCurrentDateTime() {
+ return new SimpleDateFormat(DATETIME_FORMAT).format(DateUtils.addHours(new Date(), DATE_NUM));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH".
+ */
+ public static String getCurrentDateTimeHours(int num) {
+ return new SimpleDateFormat(DATETIME_FORMAT_HOURS).format(DateUtils.addHours(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH".
+ */
+ public static String getCurrentDateTimeMinutes(int num) {
+ return new SimpleDateFormat(DATETIME_FORMAT).format(DateUtils.addMinutes(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentDateTimeMinutesSecond(int num) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addMinutes(new Date(), num));
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String getCurrentDateTimeSecond(int num) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(DateUtils.addSeconds(new Date(), num));
+ }
+
+ /**
+ * Convert time to string like "HH:mm".
+ */
+ public static String formatTime(Date d) {
+ return new SimpleDateFormat(TIME_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm".
+ */
+ public static String formatDateTime(Date d) {
+ return new SimpleDateFormat(DATETIME_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date to String like "yyyy-MM-dd".
+ */
+ public static String formatDate(Date d) {
+ return new SimpleDateFormat(DATE_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static String formatLongDate(Date d) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT).format(d);
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm:ss SSS".
+ */
+ public static String formatLongDateSSS(Date d) {
+ return new SimpleDateFormat(LONG_DATETIME_FORMAT_SSS).format(d);
+ }
+
+ /**
+ * Parse date like "yyyy-MM-dd".
+ */
+ public static Date parseDate(String d) {
+ try {
+ return new SimpleDateFormat(DATE_FORMAT).parse(d);
+ } catch (ParseException e) {
+ }
+ return null;
+ }
+
+ /**
+ * Parse date and time like "yyyy-MM-dd HH:mm".
+ */
+ public static Date parseDateTime(String dt) {
+ try {
+ return new SimpleDateFormat(DATETIME_FORMAT).parse(dt);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ /**
+ * Parse date and time like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static Date parseLongDateTime(String dt, String format) {
+ try {
+ return new SimpleDateFormat(format).parse(dt);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ /**
+ * Parse date and time like "yyyy-MM-dd HH:mm:ss".
+ */
+ public static Date parseLongDateTime(String dt) {
+ try {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dt);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ /**
+ * Convert date and time to string like "yyyy-MM-dd HH:mm".
+ */
+ public static String formatLongDateTime(Date d, String format) {
+ return new SimpleDateFormat(format).format(d);
+ }
+
+ /*
+ * 判断date是否在开始日期和结束日期之间
+ */
+ public static boolean includes(Date fromDay, Date toDay, Date date) {
+ long fromTime = fromDay.getTime();
+ long toTime = toDay.getTime();
+ long dateTime = date.getTime();
+ return ((fromTime <= dateTime) && (dateTime < toTime));
+ }
+
+ /*
+ * 判断date是否在开始日期和结束日期之间
+ *
+ */
+ public static boolean includess(Date fromDay, Date toDay, Date date) {
+ long fromTime = fromDay.getTime();
+ long toTime = toDay.getTime();
+ long dateTime = date.getTime();
+ return ((fromTime <= dateTime) && (dateTime <= toTime));
+ }
+
+ /*
+ * 给定的日期,增加指定的天数 除去周六周日之外
+ */
+ public static String addDays(String dateStr, int days, Properties holidays) {
+ SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMAT);
+ Date current = null;
+ try {
+ current = sf.parse(dateStr);
+ int cuDay = 0;
+ for (int i = 0; i < days; i++) {
+ current.setDate(current.getDate() + 1);
+ cuDay = current.getDay();
+ /* 除去节假日 */
+ Iterator iter = holidays.keySet().iterator();
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ if (key.startsWith("holiday.")) {
+ String[] va = holidays.getProperty(key).split("&");
+ boolean re = includes(sf.parse(va[0]), sf.parse(va[1]), current);
+ if (re) {
+ if (cuDay != 0 && cuDay != 6) {
+ i--;
+ }
+ }
+ }
+ }
+ /* 除去周六周日 */
+ if (cuDay == 0 || cuDay == 6) {
+ i--;
+ }
+ }
+ } catch (ParseException e) {
+ current = DateUtils.addHours(new Date(), DATE_NUM);
+ }
+ return sf.format(current);
+ }
+
+ /*
+ * 给定日期和系统当前日期的天数差 除去周六周日之外
+ */
+ public static int getDayFromToday(String start, Properties holidays) {
+ int day = -1;
+ boolean negative = false;
+ try {
+ SimpleDateFormat sf = new SimpleDateFormat(DATE_FORMAT);
+ Date startDate = sf.parse(start);
+ Date endDate = DateUtils.addHours(new Date(), DATE_NUM);/* 系统当前日期 */
+ int cuDay = 0;
+ Date temp = null;
+ if (endDate.before(startDate)) {
+ temp = startDate;
+ startDate = endDate;
+ endDate = temp;
+ negative = true;
+ }
+ while (endDate.compareTo(startDate) > 0) {
+ startDate.setDate(startDate.getDate() + 1);
+ cuDay = startDate.getDay();
+ /* 除去节假日 */
+ Iterator iter = holidays.keySet().iterator();
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ if (key.startsWith("holiday.")) {
+ String[] va = holidays.getProperty(key).split("&");
+ boolean re = includes(sf.parse(va[0]), sf.parse(va[1]), startDate);
+ if (re) {
+ if (cuDay != 0 && cuDay != 6) {
+ day++;
+ }
+ }
+ }
+ }
+ if (cuDay > 0 && cuDay < 6) {
+ day++;
+ }
+ }
+ } catch (ParseException e) {
+ }
+
+ return negative == true ? day : -day;
+ }
+
+ public static boolean isLeapYear(int year) {
+ if (year % 100 == 0) {
+ return year % 400 == 0;
+ }
+ return year % 4 == 0;
+ }
+
+ /**
+ * 将10-05-2013 转换为 2013-10-05
+ */
+ public static String changedate(String d) {
+ String ret = d;
+ try {
+ String tmp = d.substring(d.length() - 4, d.length());
+ ret = tmp + "-" + d;
+ ret = ret.substring(0, 10);
+ } catch (Exception e) {
+ return ret;
+ }
+ return ret;
+ }
+
+ /**
+ * 将01/10/2013 转换为 2013-10-01
+ */
+ public static String changedates(String d) {
+ String ret = d;
+ try {
+ String tmp = d.substring(3, 5);
+ String tmpday = d.substring(0, 2);
+ String tmpyew = d.substring(6, 10);
+ ret = tmpyew + "-" + tmp + "-" + tmpday;
+
+ } catch (Exception e) {
+ return ret;
+ }
+ return ret;
+ }
+
+ /**
+ * 获取周几的中文名称,比如周一
+ *
+ * @param key
+ * @return
+ */
+ public static String getWeekDesc(String key) {
+ String[][] keys = initWeeks();
+ for (int i = 0; i < keys.length; i++) {
+ String[] temp = keys[i];
+ for (int j = 0; j < temp.length; j++) {
+ if (key.equals(temp[0])) {
+ return temp[1];
+ }
+ }
+ }
+ return "不存在对应的解析描述";
+ }
+
+ private static String[][] initWeeks() {
+ String[][] KEY_VALUE = { { "1", "周一" }, { "2", "周二" }, { "3", "周三" }, { "4", "周四" }, { "5", "周五" },
+ { "6", "周六" }, { "7", "周日" } };
+ return KEY_VALUE;
+ }
+
+ public static long getDateDays(Date nowDate, Date oldDate) {
+ long nd = 1000 * 24 * 60 * 60;
+ long nh = 1000 * 60 * 60;
+ long nm = 1000 * 60;
+ // long ns = 1000;
+ // 获得两个时间的毫秒时间差异
+ long diff = nowDate.getTime() - oldDate.getTime();
+ // 计算差多少天
+ // long day = diff / nd;
+ // 计算差多少小时
+ long hour = diff % nd / nh;
+ // 计算差多少分钟
+ // long min = diff % nd % nh / nm;
+ // 计算差多少秒//输出结果
+ // long sec = diff % nd % nh % nm / ns;
+ // return day + "天" + hour + "小时" + min + "分钟";
+ return hour;
+ }
+
+ // public static void main(String[] args) {
+ // Date d1 = DateUtil.parseLongDateTime("2017-04-25 14:12:12");
+ // Date d2 = DateUtil.parseLongDateTime("2017-04-25 11:12:11");
+ // long a = getDateDays(d2, d1);
+ // System.out.println(a);
+ // }
+
+ /**
+ * 根据日期取得星期几
+ *
+ * @param date
+ * @return
+ */
+ public static int getWeek(Date date) {
+ String[] weeks = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
+ if (week_index < 0) {
+ week_index = 0;
+ }
+ if (week_index == 0) {
+ week_index = 7; // 周日
+ }
+ return week_index;
+ // SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
+ // String week = sdf.format(date);
+ // return week;
+ }
+
+ /**
+ * 得到指定日期在一个月中的哪一天
+ *
+ * @param date
+ * @return
+ */
+ public static int getDayOfMonth(Date date) {
+ Calendar ca = Calendar.getInstance();
+ ca.setTime(date);
+ int a = ca.get(Calendar.DAY_OF_MONTH);
+ return a;
+ }
+
+ /**
+ * 将时间转换为时间戳
+ */
+ public static String dateToStamp(String s) {
+ String res;
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date;
+ try {
+ date = simpleDateFormat.parse(s);
+ long ts = date.getTime();
+ res = String.valueOf(ts);
+ return res;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 将时间戳转换为时间
+ */
+ public static String stampToDate(long timeStamp) {
+ String result = null;
+ Date date = new Date(timeStamp * 1000);
+ SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ result = sd.format(date);
+ return result;
+ }
+
+ /**
+ * 两个时间相差距离多少天多少小时多少分多少秒
+ *
+ * @param str1 时间参数 1 格式:1990-01-01 12:00:00
+ * @param str2 时间参数 2 格式:2009-01-01 12:00:00
+ * @return long[] 返回值为:{天, 时, 分, 秒}
+ */
+ public static long[] getDistanceTimes(String str1, String str2) {
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date one;
+ Date two;
+ long day = 0;
+ long hour = 0;
+ long min = 0;
+ long sec = 0;
+ try {
+ one = df.parse(str1);
+ two = df.parse(str2);
+ long time1 = one.getTime();
+ long time2 = two.getTime();
+ long diff;
+ if (time1 < time2) {
+ diff = time2 - time1;
+ } else {
+ diff = time1 - time2;
+ }
+ day = diff / (24 * 60 * 60 * 1000);
+ hour = (diff / (60 * 60 * 1000) - day * 24);
+ min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
+ sec = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ long[] times = { day, hour, min, sec };
+ return times;
+ }
+
+ /**
+ * 将时间转换为时间戳
+ */
+ public static long dateToStamp2(String s) {
+ if (s.equals("0")) {
+ // 如果为空,则默认为当前时间
+ s = getCurrentLongDateTime();
+ }
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date;
+ try {
+ date = simpleDateFormat.parse(s);
+ long ts = date.getTime() / 1000;
+ return ts;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return new Date().getTime() / 1000;
+ }
+
+ /**
+ * 将时间戳转换为时间
+ */
+ public static String stampToDate2(long timeStamp) {
+ String result = null;
+ Date date = new Date(timeStamp * 1000);
+ SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ result = sd.format(date);
+ return result;
+ }
+
+ /**
+ * 加减日期
+ *
+ * @param date
+ * @param day
+ * @return
+ */
+ public static Date operDay(Date date, int day) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ Calendar rightNow = Calendar.getInstance();
+ rightNow.setTime(date);
+ rightNow.add(Calendar.DAY_OF_YEAR, day);
+ Date dt1 = rightNow.getTime();
+ return dt1;
+ }
+
+ /**
+ * 加减日期
+ *
+ * @param time 传入的String字符串
+ * @param day 加减多少天
+ * @param flag 加减类型标识,1=加减天数,2=加减小时
+ * @return
+ */
+ public static String operDay2(String time, int day, int flag) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH");
+ Date date = new Date();
+ try {
+ date = sdf.parse(time);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ Calendar rightNow = Calendar.getInstance();
+ rightNow.setTime(date);
+ if (flag == 1) {
+ rightNow.add(Calendar.DAY_OF_YEAR, day);
+ } else {
+ rightNow.add(Calendar.HOUR_OF_DAY, day);
+ }
+ Date dt1 = rightNow.getTime();
+ return sdf.format(dt1);
+ }
+
+ /**
+ * 将HH:mm:ss转变成秒数
+ *
+ * @param s
+ * @return
+ */
+ public static long toFormatSecond(String s) {
+ String[] time = s.split(":");
+ long hourToSecond = Integer.parseInt(time[0]) * 3600;
+ long minToSecond = Integer.parseInt(time[1]) * 60;
+ long second = Integer.parseInt(time[2]);
+ return hourToSecond + minToSecond + second;
+ }
+
+ public static long getStamp() {
+ return System.currentTimeMillis() / 1000;
+ }
+
+ public static void main(String[] args) {
+// /* System.out.println(stampToDate2(1517228653L)); */
+// System.out.println(DateUtil.getCurrentDateTimeMinutesSecond(-1440));
+// System.out.println(DateUtil.getCurrentDateTimeMinutesSecond(0));
+// System.out.println(DateUtil.getCurrentDateTimeSecond(-5));
+
+ System.out.println(getStamp());
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/StrUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/StrUtil.java
new file mode 100644
index 0000000..6ef2329
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/java/com/md/demo/util/StrUtil.java
@@ -0,0 +1,355 @@
+package com.md.demo.util;
+
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ * Title: StrUtil.java Description: 字符处理公共类
+
+ * 1.getFormData() 封装request请求参数为HashMap
+ * 2.getNoNullNewStr() 去NULL 用传入得参数代替
+ * 3.dateToString() 日期转化为字符串
+ * 4.datetimeToString() 日期时间转化为字符串
+ * 5.isEmpty() 判断字符串是否无效
+ * 6.strFormat() 字符串为空或去掉前后空格处理
+ * 7.isNumber() 判断是否数字
+ * 8.getOPERATEID() 生成受理号
+ * 9.encodeFileName() 将文件名进行转码,避免乱码
+ * 10.getFlowNo() 获取流水号(20位)
+ * 11.formatValue() 格式化值格式
+ *
+ */
+public class StrUtil {
+
+ /**
+ * 处理json解析不了的特殊字符
+ * @param paramValue
+ * @return
+ */
+ public static String transferString(String paramValue) {
+ if (!"".equals(paramValue) && paramValue != null) {
+ paramValue = paramValue.replaceAll("\"", "“");
+ //paramValue = paramValue.replaceAll("\"", "”");
+ paramValue = paramValue.replaceAll("\'", "‘");
+ paramValue = paramValue.replaceAll("\\\\", " ");
+ paramValue = paramValue.replaceAll("'", "‘");
+ paramValue = paramValue.replaceAll("\n", " ");
+ paramValue = paramValue.replaceAll("\r", " ");
+ //paramValue = paramValue.replaceAll("\'", "’");
+ }
+ return paramValue;
+ }
+ /*********
+ * 处理工单流转备注
+ * @param paramValue
+ * @return
+ * @author xiaojianfeng
+ * @updateDate:2015-11-04
+ */
+ public static String transFerStringMemo(String paramValue){
+ if (!"".equals(paramValue) && paramValue != null) {
+ paramValue = paramValue.replaceAll("\"", "“");
+ paramValue = paramValue.replaceAll("\'", "‘");
+ paramValue = paramValue.replaceAll("\\\\", " ");
+ paramValue = paramValue.replaceAll("'", "‘");
+ paramValue = paramValue.replaceAll("\r\n", "
");
+ }
+ return paramValue;
+ }
+
+ /**
+ * 去NULL 用传入得参数代替
+ * @param oldStr
+ * @param rel
+ * @return
+ */
+ public static String getNoNullNewStr(String oldStr, String rel) {
+ String newStr = (oldStr == null ? rel : oldStr.trim());
+ return newStr;
+ }
+
+ /**
+ * 日期转化为字符串
+ * @param date 日期
+ * @return 如:2015-01-08
+ * @throws Exception
+ */
+ public static String dateToString(Date date) throws Exception {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ return sdf.format(date);
+ }
+ /**
+ * 日期时间转化为字符串
+ * @param date 日期时间
+ * @return 如:2015-01-08 12:12:12
+ * @throws Exception
+ */
+ public static String datetimeToString(Date date) throws Exception {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
+ return sdf.format(date);
+ }
+
+ //add by zhangdulong 20150917 增加替换掉特殊字符
+ public static final String filterHF(Object out) {
+
+ if (out == null || out.toString().length() == 0)
+ return "";
+ String sout = out.toString();
+ StringBuffer sb = new StringBuffer();
+ char ch = ' ';
+ for (int i = 0; i < sout.length(); i++) {
+ ch = sout.charAt(i);
+ if (ch == '<') {
+ sb.append("<");
+ } else if (ch == '>') {
+ sb.append(">");
+ } else if (ch == '&') {
+ sb.append("&");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'"); // ´
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ public static final String filterHF(String out) {
+ if (out == null || out.length() == 0)
+ return out;
+ StringBuffer sb = new StringBuffer();
+ char ch = ' ';
+ for (int i = 0; i < out.length(); i++) {
+ ch = out.charAt(i);
+ if (ch == '<') {
+ sb.append("<");
+ } else if (ch == '>') {
+ sb.append(">");
+ } else if (ch == '&') {
+ sb.append("&");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'"); // ´
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+ public static final String filterSS(String out) {
+ if (out == null || out.length() == 0)
+ return out;
+ StringBuffer sb = new StringBuffer();
+ char ch = ' ';
+ for (int i = 0; i < out.length(); i++) {
+ ch = out.charAt(i);
+ if (ch == '&') {
+ sb.append("&");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'"); // ´
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+ /**
+ * 去掉字符串前后空格
+ * @param sValue
+ * @return
+ */
+ public static String getString(String sValue) {
+ return (sValue == null) ? "" : sValue.trim();
+ }
+
+ // 必须是|1|2|3|否则最后一个为&ERROR&
+ static public String getFieldData(String AString, int Index, char Dilimiter) {
+ int p1, p2;
+ int count;
+ p1 = 0;
+ p2 = 0;
+ count = 0;
+ if (AString == null)
+ AString = "";
+ for (int i = 0; i < AString.length(); i++) {
+ if (AString.charAt(i) == Dilimiter) {
+ p2 = p1;
+ p1 = i + 1;
+ count++;
+ }
+ if (count == Index) {
+ break;
+ }
+ }
+
+ if ((p1 > 0) && (count == Index))
+ return AString.substring(p2, p1 - 1).trim();
+ else
+ return "&ERROR&";
+ }
+
+ /**
+ * 判断字符串是否无效
+ * @param str
+ * @return
+ */
+ public static boolean isEmpty(String str) {
+ if (null == str || "".equals(str.trim()) || "null".equals(str.trim())
+ || "NULL".equals(str.trim())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ /**
+ * 字符串为空或去掉前后空格处理
+ * @param str
+ * @return
+ */
+ public static String strFormat(String str) {
+ if (null == str || "".equals(str.trim()) || "null".equals(str.trim())
+ || "NULL".equals(str.trim())) {
+ return "";
+ } else {
+ return str.trim();
+ }
+ }
+
+ /**
+ * 校验输入串是否为数字
+ * @param str
+ * @return
+ */
+ public static boolean isNumber(String str) {
+ boolean rtn = true;
+ String array[] = str.split("");// 将字符串转换为字符串数组,以""为分隔符来转换字符串。注:array[0]=""
+ int length = array.length;
+ for (int i = 1; i < length; i++) { // 从array[1]开始判断
+ int code = array[i].hashCode(); // 获得ASCII码
+ // 如果array[i]为数字
+ if (code >= 48 && code <= 57) { // 判断是否为数字
+ continue;
+ } else {
+ rtn = false;
+ break;
+ }
+ }
+
+ return rtn;
+ }
+
+ /**
+ * 生成受理号
+ *
+ * @param OPERATETYPE
+ * 工单编号
+ * @param flowno
+ * 流水号
+ * @return String
+ * */
+ public static String getOPERATEID(String OPERATETYPE, String flowno) {
+
+ String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
+ StringBuffer sb = new StringBuffer(date);
+ sb.append(OPERATETYPE).append(flowno);
+ return sb.toString();
+
+ }
+
+ /**
+ * 将文件名进行转码,避免乱码
+ * @param request
+ * @param fileName
+ * @author xiajia
+ * @return
+ */
+ public static String encodeFileName(HttpServletRequest request,
+ String fileName) {
+// String agent = request.getHeader("USER-AGENT");
+// try {
+// if (null != agent && -1 != agent.indexOf("MSIE")) {
+// return URLEncoder.encode(fileName, "UTF-8");
+// } else if (null != agent && -1 != agent.indexOf("Mozilla")) {
+// return "=?UTF-8?B?"
+// + new String(Base64.encodeBase64(fileName
+// .getBytes("UTF-8"))) + "?=";
+// } else {
+// return fileName;
+// }
+// } catch (UnsupportedEncodingException e) {
+// }
+ return "";
+ }
+
+ /**
+ * 1.将null对象返回空字符串-“""”
+ * 2.若非null对象返回toString()及trim字符串
+ *
+ * @param origin
+ * String
+ * @return String
+ */
+ public static String null2Str(Object origin) {
+ return (origin == null ? "" : origin.toString().trim()).replace("null", "");
+ }
+
+ /**
+ * 格式化值格式
+ * @param value 值
+ * @param valueFormat 值格式(保留2位小数,若显示88.00%,则传入0.00%;若显示88.88,则传入0.00。以此类推!)
+ * @author xuwei
+ * @return
+ */
+ public static String formatValue(String value,String valueFormat){
+ String digits = "";//默认0位,即取整数
+ NumberFormat numberFormat = null;
+ if(valueFormat.indexOf("%") > 0){
+ //带%值格式
+ digits = valueFormat.substring(0, valueFormat.indexOf("%"));//去掉%
+ numberFormat = NumberFormat.getPercentInstance();
+ }else{
+ //不带%值格式
+ digits = valueFormat;
+ numberFormat = NumberFormat.getNumberInstance();
+ }
+ if(digits.indexOf(".") > 0){
+ //含小数点,取小数点后面的位数
+ digits = digits.substring(digits.indexOf(".")+1, digits.length());
+ }else{
+ digits = "";
+ }
+
+ int decimals = digits.length();//小数位数
+ numberFormat.setMinimumFractionDigits(decimals);
+ numberFormat.setMaximumFractionDigits(decimals);
+ numberFormat.setGroupingUsed(false);//不千分位显示
+ return numberFormat.format(Double.parseDouble(value));
+ }
+
+ public static String parseSosMgTyp(String mgTyp){
+ if(mgTyp.indexOf("Sos")>0){
+ return "求助";
+ }else if(mgTyp.indexOf("Fire")>0){
+ return "火警";
+ }else if(mgTyp.indexOf("Aleak")>0){
+ return "漏水";
+ }else if(mgTyp.indexOf("Hijack")>0){
+ return "被劫持";
+ }else if(mgTyp.indexOf("War")>0){
+ return "预警";
+ }else if(mgTyp.indexOf("Alm")>0){
+ return "报警";
+ }
+ return "未知";
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-crawler/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.classpath b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.classpath
new file mode 100644
index 0000000..5e8a55f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.classpath
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.project b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.project
new file mode 100644
index 0000000..9c97a1e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.project
@@ -0,0 +1,23 @@
+
+
+ md-leaf-core
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.core.resources.prefs b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..e9441bb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding/=UTF-8
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.jdt.core.prefs b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..71df522
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.m2e.core.prefs b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/README.md
new file mode 100644
index 0000000..f4cbe48
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/README.md
@@ -0,0 +1,19 @@
+# 基础组件
+
+分布式ID组件(Snowflake算法)
+
+# 全局唯一ID/分布式ID解决方案
+
+全局唯一,绝对不会出现重复的ID,且ID整体趋势递增。
+
+高可用,服务完全基于分布式架构,即使MySQL宕机,也能容忍一段时间的数据库不可用。
+
+高并发低延时,在CentOS 4C8G的虚拟机上,远程调用QPS可达5W+,TP99在1ms内。
+
+接入简单,直接通过公司RPC服务或者HTTP调用即可接入。
+
+[分布式ID解决方案-教程说明地址](https://blog.csdn.net/hemin1003/article/details/89133535)
+
+# 附加
+
+此组件是我剥离后的组件,只保留Snowflake算法部分,其他服务需要用到,可直接引入此组件,简单快捷
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/pom.xml
new file mode 100644
index 0000000..616739d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/pom.xml
@@ -0,0 +1,55 @@
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-distributed-id-core-leafid
+ jar
+
+ spring-boot2-distributed-id-core-leafid
+ MD Core LeafId 分布式Id组件
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.perf4j
+ perf4j
+ 0.9.16
+
+
+ org.slf4j
+ slf4j-api
+
+
+ commons-io
+ commons-io
+ 2.4
+
+
+
+ org.apache.curator
+ curator-recipes
+ 2.6.0
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ provided
+
+
+ org.apache.logging.log4j
+ log4j-core
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/CheckVO.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/CheckVO.java
new file mode 100644
index 0000000..48ffaad
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/CheckVO.java
@@ -0,0 +1,27 @@
+package com.md.core.leafid;
+
+public class CheckVO {
+ private long timestamp;
+ private int workID;
+
+ public CheckVO(long timestamp, int workID) {
+ this.timestamp = timestamp;
+ this.workID = workID;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public int getWorkID() {
+ return workID;
+ }
+
+ public void setWorkID(int workID) {
+ this.workID = workID;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/MdIdsGen.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/MdIdsGen.java
new file mode 100644
index 0000000..1f28111
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/MdIdsGen.java
@@ -0,0 +1,63 @@
+package com.md.core.leafid;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.md.core.leafid.id.IDGen;
+import com.md.core.leafid.snowflake.SnowflakeIDGenImpl;
+
+/**
+ * 分布式id生成器
+ *
+ * @author Minbo
+ *
+ */
+public class MdIdsGen {
+
+ protected static Logger logger = LoggerFactory.getLogger(MdIdsGen.class);
+
+ private static Result result = null;
+ private static IDGen idGen = null;
+ private static String sIp;
+ private static String sPort;
+
+ // 美团开源的分布式id生成器
+ // https://github.com/hemin1003/Leaf
+ /**
+ * 与注册中心建立连接, 初始化id值
+ *
+ * @param zkAddress
+ * @param ip
+ * @param port
+ */
+ public static void init(String zkAddress, String ip, String port) {
+ try {
+ sIp = ip;
+ sPort = port;
+
+ logger.info("----------------");
+ logger.info("初始化:分布式id生成器");
+ logger.info("参数值:zkAddress=" + zkAddress + ",sIp=" + sIp + ",sPort=" + sPort);
+
+ idGen = new SnowflakeIDGenImpl(zkAddress, Integer.valueOf(port));
+ Long idLong = getId();
+ if (idLong == null || idLong < 0) {
+ logger.error("分布式id生成器初始化【异常】:id值为空或小于0,【id=" + idLong + "】", new RuntimeException("valueError"));
+ // 初始失败,直接停止应用
+ System.exit(0);
+ }
+ logger.info("分布式id生成器,初始化【成功】。测试id值=" + idLong);
+ logger.info("----------------done");
+
+ } catch (Exception e) {
+ logger.error("分布式id生成器,初始化【异常】:" + e.getMessage(), new RuntimeException("initError"));
+ // 初始失败,直接停止应用
+ System.exit(0);
+ }
+ }
+
+ public static Long getId() {
+ result = idGen.get(sIp + ":" + sPort);
+ return result.getId();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/PropertyFactory.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/PropertyFactory.java
new file mode 100644
index 0000000..fc9b7c3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/PropertyFactory.java
@@ -0,0 +1,22 @@
+package com.md.core.leafid;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Properties;
+
+public class PropertyFactory {
+ private static final Logger logger = LoggerFactory.getLogger(PropertyFactory.class);
+ private static final Properties prop = new Properties();
+ static {
+ try {
+ prop.load(PropertyFactory.class.getClassLoader().getResourceAsStream("leaf.properties"));
+ } catch (IOException e) {
+ logger.warn("Load Properties Ex", e);
+ }
+ }
+ public static Properties getProperties() {
+ return prop;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Result.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Result.java
new file mode 100644
index 0000000..c9dc2de
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Result.java
@@ -0,0 +1,39 @@
+package com.md.core.leafid;
+
+public class Result {
+ private long id;
+ private Status status;
+
+ public Result() {
+
+ }
+ public Result(long id, Status status) {
+ this.id = id;
+ this.status = status;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("Result{");
+ sb.append("id=").append(id);
+ sb.append(", status=").append(status);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Status.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Status.java
new file mode 100644
index 0000000..45bf587
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Status.java
@@ -0,0 +1,6 @@
+package com.md.core.leafid;
+
+public enum Status {
+ SUCCESS,
+ EXCEPTION
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Utils.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Utils.java
new file mode 100644
index 0000000..55c7487
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/Utils.java
@@ -0,0 +1,21 @@
+package com.md.core.leafid;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+
+public class Utils {
+ private static final Logger logger = LoggerFactory.getLogger(Utils.class);
+ public static String getIp() {
+ String ip;
+ try {
+ InetAddress addr = InetAddress.getLocalHost();
+ ip = addr.getHostAddress();
+ } catch(Exception ex) {
+ ip = "";
+ logger.warn("Utils get IP warn", ex);
+ }
+ return ip;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/ZeroIDGen.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/ZeroIDGen.java
new file mode 100644
index 0000000..53dca25
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/ZeroIDGen.java
@@ -0,0 +1,16 @@
+package com.md.core.leafid;
+
+import com.md.core.leafid.id.IDGen;
+
+public class ZeroIDGen implements IDGen {
+
+ @Override
+ public Result get(String key) {
+ return new Result(0, Status.SUCCESS);
+ }
+
+ @Override
+ public boolean init() {
+ return true;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/id/IDGen.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/id/IDGen.java
new file mode 100644
index 0000000..9916fe7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/id/IDGen.java
@@ -0,0 +1,8 @@
+package com.md.core.leafid.id;
+
+import com.md.core.leafid.Result;
+
+public interface IDGen {
+ Result get(String key);
+ boolean init();
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/SnowflakeIDGenImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/SnowflakeIDGenImpl.java
new file mode 100644
index 0000000..07a0053
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/SnowflakeIDGenImpl.java
@@ -0,0 +1,109 @@
+package com.md.core.leafid.snowflake;
+
+import java.util.Random;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.md.core.leafid.Result;
+import com.md.core.leafid.Status;
+import com.md.core.leafid.Utils;
+import com.md.core.leafid.id.IDGen;
+
+public class SnowflakeIDGenImpl implements IDGen {
+
+ @Override
+ public boolean init() {
+ return true;
+ }
+
+ static private final Logger LOGGER = LoggerFactory.getLogger(SnowflakeIDGenImpl.class);
+
+ private final long twepoch = 1288834974657L;
+ private final long workerIdBits = 10L;
+ private final long maxWorkerId = -1L ^ (-1L << workerIdBits);// 最大能够分配的workerid =1023
+ private final long sequenceBits = 12L;
+ private final long workerIdShift = sequenceBits;
+ private final long timestampLeftShift = sequenceBits + workerIdBits;
+ private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+ private long workerId;
+ private long sequence = 0L;
+ private long lastTimestamp = -1L;
+ public boolean initFlag = false;
+ private static final Random RANDOM = new Random();
+ private int port;
+
+ public SnowflakeIDGenImpl(String zkAddress, int port) {
+ this.port = port;
+ SnowflakeZookeeperHolder holder = new SnowflakeZookeeperHolder(Utils.getIp(), String.valueOf(port), zkAddress);
+ initFlag = holder.init();
+ if (initFlag) {
+ workerId = holder.getWorkerID();
+ LOGGER.info("START SUCCESS USE ZK WORKERID-{}", workerId);
+ } else {
+ Preconditions.checkArgument(initFlag, "Snowflake Id Gen is not init ok");
+ }
+ Preconditions.checkArgument(workerId >= 0 && workerId <= maxWorkerId, "workerID must gte 0 and lte 1023");
+ }
+
+ public synchronized Result get(String key) {
+ long timestamp = timeGen();
+ if (timestamp < lastTimestamp) {
+ long offset = lastTimestamp - timestamp;
+ if (offset <= 5) {
+ try {
+ wait(offset << 1);
+ timestamp = timeGen();
+ if (timestamp < lastTimestamp) {
+ return new Result(-1, Status.EXCEPTION);
+ }
+ } catch (InterruptedException e) {
+ LOGGER.error("wait interrupted");
+ return new Result(-2, Status.EXCEPTION);
+ }
+ } else {
+ return new Result(-3, Status.EXCEPTION);
+ }
+ }
+ if (lastTimestamp == timestamp) {
+ sequence = (sequence + 1) & sequenceMask;
+ if (sequence == 0) {
+ // seq 为0的时候表示是下一毫秒时间开始对seq做随机
+ sequence = RANDOM.nextInt(100);
+ timestamp = tilNextMillis(lastTimestamp);
+ }
+ } else {
+ // 如果是新的ms开始
+ sequence = RANDOM.nextInt(100);
+ }
+ lastTimestamp = timestamp;
+ long id = ((timestamp - twepoch) << timestampLeftShift) | (workerId << workerIdShift) | sequence;
+ return new Result(id, Status.SUCCESS);
+
+ }
+
+ protected long tilNextMillis(long lastTimestamp) {
+ long timestamp = timeGen();
+ while (timestamp <= lastTimestamp) {
+ timestamp = timeGen();
+ }
+ return timestamp;
+ }
+
+ protected long timeGen() {
+ return System.currentTimeMillis();
+ }
+
+ public long getWorkerId() {
+ return workerId;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/SnowflakeZookeeperHolder.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/SnowflakeZookeeperHolder.java
new file mode 100644
index 0000000..a6d2460
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/SnowflakeZookeeperHolder.java
@@ -0,0 +1,307 @@
+package com.md.core.leafid.snowflake;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.retry.RetryUntilElapsed;
+import org.apache.zookeeper.data.Stat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+import com.md.core.leafid.*;
+import com.md.core.leafid.snowflake.exception.CheckLastTimeException;
+
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.zookeeper.CreateMode;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 与注册中心建立连接,初始化绑定服务的全局id值
+ *
+ * @author Minbo
+ *
+ */
+public class SnowflakeZookeeperHolder {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SnowflakeZookeeperHolder.class);
+ private String zk_AddressNode = null;// 保存自身的key ip:port-000000001
+ private String listenAddress = null;// 保存自身的key ip:port
+ private int workerID;
+ private static final String PREFIX_ZK_PATH = "/snowflake/"
+ + PropertyFactory.getProperties().getProperty("leaf.name");
+ private static final String PROP_PATH = System.getProperty("java.io.tmpdir") + File.separator
+ + PropertyFactory.getProperties().getProperty("leaf.name") + "/leafconf/{port}/workerID.properties";
+ private static final String PATH_FOREVER = PREFIX_ZK_PATH + "/forever";// 保存所有数据持久的节点
+ private String ip;
+ private String port;
+ private String connectionString;
+ private long lastUpdateTime;
+
+ public SnowflakeZookeeperHolder(String ip, String port, String connectionString) {
+ this.ip = ip;
+ this.port = port;
+ this.listenAddress = ip + ":" + port;
+ this.connectionString = connectionString;
+ }
+
+ public boolean init() {
+ try {
+ CuratorFramework curator = createWithOptions(connectionString, new RetryUntilElapsed(1000, 4), 10000,
+ 10000);
+ curator.start();
+ Stat stat = curator.checkExists().forPath(PATH_FOREVER);
+ if (stat == null) {
+ // 不存在根节点,机器第一次启动,创建/snowflake/ip:port-000000000,并上传数据
+ zk_AddressNode = createNode(curator);
+ // worker id 默认是0
+ updateLocalWorkerID(workerID);
+ // 定时上报本机时间给forever节点
+ ScheduledUploadData(curator, zk_AddressNode);
+ return true;
+ } else {
+ Map nodeMap = Maps.newHashMap();// ip:port->00001
+ Map realNode = Maps.newHashMap();// ip:port->(ipport-000001)
+ // 存在根节点,先检查是否有属于自己的根节点
+ List keys = curator.getChildren().forPath(PATH_FOREVER);
+ for (String key : keys) {
+ String[] nodeKey = key.split("-");
+ realNode.put(nodeKey[0], key);
+ nodeMap.put(nodeKey[0], Integer.parseInt(nodeKey[1]));
+ }
+ Integer workerid = nodeMap.get(listenAddress);
+ if (workerid != null) {
+ // 有自己的节点,zk_AddressNode=ip:port
+ zk_AddressNode = PATH_FOREVER + "/" + realNode.get(listenAddress);
+ workerID = workerid;// 启动worder时使用会使用
+ if (!checkInitTimeStamp(curator, zk_AddressNode))
+ throw new CheckLastTimeException(
+ "init timestamp check error,forever node timestamp gt this node time");
+ // 准备创建临时节点
+ doService(curator);
+ updateLocalWorkerID(workerID);
+ LOGGER.info(
+ "[Old NODE]find forever node have this endpoint ip-{} port-{} workid-{} childnode and start SUCCESS",
+ ip, port, workerID);
+ } else {
+ // 表示新启动的节点,创建持久节点 ,不用check时间
+ String newNode = createNode(curator);
+ zk_AddressNode = newNode;
+ String[] nodeKey = newNode.split("-");
+ workerID = Integer.parseInt(nodeKey[1]);
+ doService(curator);
+ updateLocalWorkerID(workerID);
+ LOGGER.info(
+ "[New NODE]can not find node on forever node that endpoint ip-{} port-{} workid-{},create own node on forever node and start SUCCESS ",
+ ip, port, workerID);
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error("Start node ERROR {}", e);
+ try {
+ Properties properties = new Properties();
+ properties.load(new FileInputStream(new File(PROP_PATH.replace("{port}", port + ""))));
+ workerID = Integer.valueOf(properties.getProperty("workerID"));
+ LOGGER.warn("START FAILED ,use local node file properties workerID-{}", workerID);
+ } catch (Exception e1) {
+ LOGGER.error("Read file error ", e1);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void doService(CuratorFramework curator) {
+ ScheduledUploadData(curator, zk_AddressNode);// /snowflake_forever/ip:port-000000001
+ }
+
+ private void ScheduledUploadData(final CuratorFramework curator, final String zk_AddressNode) {
+ Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread thread = new Thread(r, "schedule-upload-time");
+ thread.setDaemon(true);
+ return thread;
+ }
+ }).scheduleWithFixedDelay(new Runnable() {
+ @Override
+ public void run() {
+ updateNewData(curator, zk_AddressNode);
+ }
+ }, 1L, 3L, TimeUnit.SECONDS);// 每3s上报数据
+
+ }
+
+ private boolean checkInitTimeStamp(CuratorFramework curator, String zk_AddressNode) throws Exception {
+ byte[] bytes = curator.getData().forPath(zk_AddressNode);
+ Endpoint endPoint = deBuildData(new String(bytes));
+ // 该节点的时间不能小于最后一次上报的时间
+ return !(endPoint.getTimestamp() > System.currentTimeMillis());
+ }
+
+ /**
+ * 创建持久顺序节点 ,并把节点数据放入 value
+ *
+ * @param curator
+ * @return
+ * @throws Exception
+ */
+ private String createNode(CuratorFramework curator) throws Exception {
+ try {
+ return curator.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL)
+ .forPath(PATH_FOREVER + "/" + listenAddress + "-", buildData().getBytes());
+ } catch (Exception e) {
+ LOGGER.error("create node error msg {} ", e.getMessage());
+ throw e;
+ }
+ }
+
+ private void updateNewData(CuratorFramework curator, String path) {
+ try {
+ if (System.currentTimeMillis() < lastUpdateTime) {
+ return;
+ }
+ curator.setData().forPath(path, buildData().getBytes());
+ lastUpdateTime = System.currentTimeMillis();
+ } catch (Exception e) {
+ LOGGER.info("update init data error path is {} error is {}", path, e);
+ }
+ }
+
+ /**
+ * 构建需要上传的数据
+ *
+ * @return
+ */
+ private String buildData() throws JsonProcessingException {
+ Endpoint endpoint = new Endpoint(ip, port, System.currentTimeMillis());
+ ObjectMapper mapper = new ObjectMapper();
+ String json = mapper.writeValueAsString(endpoint);
+ return json;
+ }
+
+ private Endpoint deBuildData(String json) throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ Endpoint endpoint = mapper.readValue(json, Endpoint.class);
+ return endpoint;
+ }
+
+ /**
+ * 在节点文件系统上缓存一个workid值,zk失效,机器重启时保证能够正常启动
+ *
+ * @param workerID
+ */
+ private void updateLocalWorkerID(int workerID) {
+ File LeafconfFile = new File(PROP_PATH.replace("{port}", port));
+ boolean exists = LeafconfFile.exists();
+ LOGGER.info("file exists status is {}", exists);
+ if (exists) {
+ try {
+ FileUtils.writeStringToFile(LeafconfFile, "workerID=" + workerID, false);
+ LOGGER.info("update file cache workerID is {}", workerID);
+ } catch (IOException e) {
+ LOGGER.error("update file cache error ", e);
+ }
+ } else {
+ // 不存在文件,父目录页肯定不存在
+ try {
+ boolean mkdirs = LeafconfFile.getParentFile().mkdirs();
+ LOGGER.info("init local file cache create parent dis status is {}, worker id is {}", mkdirs, workerID);
+ if (mkdirs) {
+ if (LeafconfFile.createNewFile()) {
+ FileUtils.writeStringToFile(LeafconfFile, "workerID=" + workerID, false);
+ LOGGER.info("local file cache workerID is {}", workerID);
+ }
+ } else {
+ LOGGER.warn("create parent dir error===");
+ }
+ } catch (IOException e) {
+ LOGGER.warn("craete workerID conf file error", e);
+ }
+ }
+ }
+
+ private CuratorFramework createWithOptions(String connectionString, RetryPolicy retryPolicy,
+ int connectionTimeoutMs, int sessionTimeoutMs) {
+ return CuratorFrameworkFactory.builder().connectString(connectionString).retryPolicy(retryPolicy)
+ .connectionTimeoutMs(connectionTimeoutMs).sessionTimeoutMs(sessionTimeoutMs).build();
+ }
+
+ /**
+ * 上报数据结构
+ */
+ static class Endpoint {
+ private String ip;
+ private String port;
+ private long timestamp;
+
+ public Endpoint() {
+ }
+
+ public Endpoint(String ip, String port, long timestamp) {
+ this.ip = ip;
+ this.port = port;
+ this.timestamp = timestamp;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+ }
+
+ public String getZk_AddressNode() {
+ return zk_AddressNode;
+ }
+
+ public void setZk_AddressNode(String zk_AddressNode) {
+ this.zk_AddressNode = zk_AddressNode;
+ }
+
+ public String getListenAddress() {
+ return listenAddress;
+ }
+
+ public void setListenAddress(String listenAddress) {
+ this.listenAddress = listenAddress;
+ }
+
+ public int getWorkerID() {
+ return workerID;
+ }
+
+ public void setWorkerID(int workerID) {
+ this.workerID = workerID;
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/CheckLastTimeException.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/CheckLastTimeException.java
new file mode 100644
index 0000000..2a25dfd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/CheckLastTimeException.java
@@ -0,0 +1,9 @@
+package com.md.core.leafid.snowflake.exception;
+
+public class CheckLastTimeException extends RuntimeException {
+ private static final long serialVersionUID = -8190739312919956031L;
+
+ public CheckLastTimeException(String msg){
+ super(msg);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/CheckOtherNodeException.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/CheckOtherNodeException.java
new file mode 100644
index 0000000..33f67a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/CheckOtherNodeException.java
@@ -0,0 +1,9 @@
+package com.md.core.leafid.snowflake.exception;
+
+public class CheckOtherNodeException extends RuntimeException {
+ private static final long serialVersionUID = -3875889640476871473L;
+
+ public CheckOtherNodeException(String message) {
+ super(message);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/ClockGoBackException.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/ClockGoBackException.java
new file mode 100644
index 0000000..6ef6731
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id-core-leafid/src/main/java/com/md/core/leafid/snowflake/exception/ClockGoBackException.java
@@ -0,0 +1,9 @@
+package com.md.core.leafid.snowflake.exception;
+
+public class ClockGoBackException extends RuntimeException {
+ private static final long serialVersionUID = -2021330616975162738L;
+
+ public ClockGoBackException(String message) {
+ super(message);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/README.md
new file mode 100644
index 0000000..f90e6e7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-distributed-id
+
+【全局唯一ID/分布式ID解决方案】技术点
+
+功能介绍
+
+1. 分布式ID解决方案
+
+## 本项目教程
+
+[全局唯一ID/分布式ID解决方案](https://hemin.blog.csdn.net/article/details/96483588)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/pom.xml
new file mode 100644
index 0000000..63e0ffd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-distributed-id
+ jar
+
+ spring-boot2-distributed-id
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ com.md
+ spring-boot2-distributed-id-core-leafid
+ 0.0.1-SNAPSHOT
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..396b0a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,51 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import com.md.demo.begin.MyApplicationPreparedEvent;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication application = new SpringApplication(Application.class);
+ application.addListeners(new MyApplicationPreparedEvent());
+ application.run(args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/begin/MyApplicationPreparedEvent.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/begin/MyApplicationPreparedEvent.java
new file mode 100644
index 0000000..38fba9d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/begin/MyApplicationPreparedEvent.java
@@ -0,0 +1,42 @@
+package com.md.demo.begin;
+
+import java.net.InetAddress;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.context.event.ApplicationPreparedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+import com.md.core.leafid.MdIdsGen;
+
+/**
+ * 监听器:项目初始化时调用类
+ *
+ * ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
+ *
+ * @author Minbo
+ */
+public class MyApplicationPreparedEvent implements ApplicationListener {
+
+ private Logger logger = LoggerFactory.getLogger(MyApplicationPreparedEvent.class);
+
+ @Override
+ public void onApplicationEvent(ApplicationPreparedEvent event) {
+ try {
+ ConfigurableEnvironment environment = event.getApplicationContext().getEnvironment();
+ logger.info("项目启动前,执行操作:");
+
+ // 1. 初始化分布式id生成器(利用本机IP和端口生成)
+ logger.info("1. 初始化分布式id生成器(利用本机IP和端口生成):");
+ String ip = InetAddress.getLocalHost().getHostAddress();
+ String port = environment.getProperty("server.port");
+ String zkAddress = environment.getProperty("leaf.zk.list");
+ MdIdsGen.init(zkAddress, ip, port);
+
+ } catch (Exception e) {
+ logger.error("初始化分布式id生成器,异常:" + e.getMessage(), e);
+ System.exit(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..39cf3a2
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,40 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.core.leafid.MdIdsGen;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-distributed-id";
+ }
+
+ /**
+ * http://localhost:9090/getNewId
+ *
+ * @return
+ */
+ @GetMapping("/getNewId")
+ public JsonResult getNewId() {
+ Long id = MdIdsGen.getId();
+ return new JsonResult(ResultCode.SUCCESS, id);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/application.yml
new file mode 100644
index 0000000..657b951
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+server:
+ port: 9090
+leaf:
+ zk:
+ list: localhost:3181
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/leaf.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/leaf.properties
new file mode 100644
index 0000000..6763bdc
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/leaf.properties
@@ -0,0 +1 @@
+leaf.name=default
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/logback.xml
new file mode 100644
index 0000000..8561ff9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-id/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/README.md
new file mode 100644
index 0000000..9bcc6df
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-distributed-lock
+
+【分布式锁用法】技术点
+
+功能介绍
+
+1. 分布式锁用法(基于Redis实现)
+
+## 本项目教程
+
+[分布式锁用法](https://hemin.blog.csdn.net/article/details/99637778)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/pom.xml
new file mode 100644
index 0000000..e541cdb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-distributed-lock
+ jar
+
+ spring-boot2-distributed-lock
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+ org.springframework.boot
+ spring-boot-starter-integration
+
+
+ org.springframework.integration
+ spring-integration-redis
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/RedisLockConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/RedisLockConfiguration.java
new file mode 100644
index 0000000..615ffed
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/RedisLockConfiguration.java
@@ -0,0 +1,16 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.integration.redis.util.RedisLockRegistry;
+
+@Configuration
+public class RedisLockConfiguration {
+
+ @Bean
+ public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
+ return new RedisLockRegistry(redisConnectionFactory, "spring-boot");
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..6576a16
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,56 @@
+package com.md.demo.rest;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.integration.redis.util.RedisLockRegistry;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ @Autowired
+ private RedisLockRegistry redisLockRegistry;
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-distributed-lock";
+ }
+
+ /**
+ * http://localhost:9090/test
+ *
+ * @return
+ */
+ @GetMapping("test")
+ public String test() throws InterruptedException {
+ Lock lock = this.redisLockRegistry.obtain("lock");
+ boolean b1 = lock.tryLock(3, TimeUnit.SECONDS);
+ logger.info("b1 is : {}", b1);
+
+ TimeUnit.SECONDS.sleep(5);
+
+ boolean b2 = lock.tryLock(3, TimeUnit.SECONDS);
+ logger.info("b2 is : {}", b2);
+
+ lock.unlock();
+ lock.unlock();
+
+ return "success";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/resources/application.yml
new file mode 100644
index 0000000..fe2d30a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/resources/application.yml
@@ -0,0 +1,9 @@
+server:
+ port: 9090
+spring:
+ redis:
+ host: localhost
+ port: 7379
+ password: a123456
+ timeout: 10000
+ max-wait: -1
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-distributed-lock/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/README.md
new file mode 100644
index 0000000..a29fd3a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-docker
+
+【Docker集成+容器化部署详解】技术点
+
+功能介绍
+
+1. 使用Maven插件构建Docker镜像
+
+## 本项目文档教程
+
+[Docker集成+容器化部署详解-上篇](https://hemin.blog.csdn.net/article/details/96483517)
+
+## 该系列教程
+
+[SpringBoot系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/pom.xml
new file mode 100644
index 0000000..39938ba
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/pom.xml
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-docker
+ jar
+
+ spring-boot2-docker
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ com.spotify
+ docker-maven-plugin
+ 0.4.12
+
+
+ spring-boot2-docker
+ java
+ ["java", "-jar", "/${project.build.finalName}.jar"]
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.jar
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..2b65917
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,25 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-docker";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/resources/application.yml
new file mode 100644
index 0000000..f55234a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/resources/logback.xml
new file mode 100644
index 0000000..d2f95c4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-docker/src/main/resources/logback.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/README.md
new file mode 100644
index 0000000..b377226
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-dockerfile
+
+【Docker集成+容器化部署详解-下篇】技术点
+
+功能介绍
+
+1. 使用Dockerfile构建Docker镜像
+
+## 本项目文档教程
+
+[ Docker集成+容器化部署详解/下篇-使用Dockerfile进行构建](https://hemin.blog.csdn.net/article/details/99676483)
+
+## 该系列教程
+
+[SpringBoot系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/pom.xml
new file mode 100644
index 0000000..eda8d64
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-dockerfile
+ jar
+
+ spring-boot2-dockerfile
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ spring-boot2-dockerfile
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+ com.spotify
+ docker-maven-plugin
+ 0.4.12
+
+
+ build-image
+ package
+
+ build
+
+
+
+
+ spring-boot2-dockerfile
+ ${project.basedir}/src/main/docker
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.jar
+
+
+
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/docker/Dockerfile b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/docker/Dockerfile
new file mode 100644
index 0000000..19114ef
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/docker/Dockerfile
@@ -0,0 +1,6 @@
+FROM java:8
+VOLUME /tmp/spring-boot2-dockerfile
+ADD spring-boot2-dockerfile.jar spring-boot2-dockerfile.jar
+RUN bash -c 'touch /spring-boot2-dockerfile.jar'
+RUN echo "Asia/Shanghai" > /etc/timezone
+ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/spring-boot2-dockerfile.jar"]
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..f430e92
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,25 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-dockerfile";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/resources/application.yml
new file mode 100644
index 0000000..f55234a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/resources/logback.xml
new file mode 100644
index 0000000..d2f95c4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dockerfile/src/main/resources/logback.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/README.md
new file mode 100644
index 0000000..74bdc1a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/README.md
@@ -0,0 +1,39 @@
+# spring-boot2-dubbo-consumer【服务消费者】
+
+【Dubbo服务提供者、服务消费者整合/Zookeeper集成】技术点
+
+功能介绍
+
+1. Dubbo服务提供者、服务消费者整合/Zookeeper集成
+
+## 本项目文档教程
+
+[Dubbo服务提供者、服务消费者整合/Zookeeper集成](https://hemin.blog.csdn.net/article/details/96483573)
+
+[Zookeeper安装教程](https://blog.csdn.net/hemin1003/article/details/64437977)
+
+[Dubbo Admin安装教程](https://blog.csdn.net/hemin1003/article/details/64438617)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/pom.xml
new file mode 100644
index 0000000..2afadd7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/pom.xml
@@ -0,0 +1,84 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-dubbo-consumer
+ jar
+
+ spring-boot2-dubbo-consumer
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+ com.alibaba
+ fastjson
+ 1.1.41
+
+
+ com.alibaba
+ dubbo
+
+
+ spring
+ org.springframework
+
+
+
+
+ org.apache.zookeeper
+ zookeeper
+
+
+ slf4j-log4j12
+ org.slf4j
+
+
+
+
+ com.github.sgroschupf
+ zkclient
+
+
+ com.md
+ spring-boot2-dubbo-provider
+ 0.0.1-SNAPSHOT
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..7db4454
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,50 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+//使用 consumers.xml 配置;
+@ImportResource(value = { "classpath:consumers.xml" })
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..a684256
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,25 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-dubbo-consumer";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/rest/TestController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/rest/TestController.java
new file mode 100644
index 0000000..3e6e2a6
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/rest/TestController.java
@@ -0,0 +1,33 @@
+package com.md.demo.rest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.md.demo.service.DemoService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+
+/**
+ * 测试用的 Controller 类;
+ */
+@Controller
+public class TestController {
+
+ @Autowired
+ private DemoService demoService;
+
+ /**
+ * 测试 JSON 接口;
+ *
+ * @param name 名字
+ * @return
+ */
+ @ResponseBody
+ @RequestMapping("/test")
+ public JsonResult testJson(String name) {
+ String result = this.demoService.sayHello(name);
+ return new JsonResult(ResultCode.SUCCESS, result);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/application.yml
new file mode 100644
index 0000000..39286dd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9091
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/consumers.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/consumers.xml
new file mode 100644
index 0000000..1236913
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/consumers.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/logback.xml
new file mode 100644
index 0000000..8561ff9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-consumer/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/README.md
new file mode 100644
index 0000000..27b9193
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/README.md
@@ -0,0 +1,39 @@
+# spring-boot2-dubbo-provider【服务提供者】
+
+【Dubbo服务提供者、服务消费者整合/Zookeeper集成】技术点
+
+功能介绍
+
+1. Dubbo服务提供者、服务消费者整合/Zookeeper集成
+
+## 本项目文档教程
+
+[Dubbo服务提供者、服务消费者整合/Zookeeper集成](https://hemin.blog.csdn.net/article/details/96483573)
+
+[Zookeeper安装教程](https://blog.csdn.net/hemin1003/article/details/64437977)
+
+[Dubbo Admin安装教程](https://blog.csdn.net/hemin1003/article/details/64438617)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/pom.xml
new file mode 100644
index 0000000..9628bc8
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-dubbo-provider
+ jar
+
+ spring-boot2-dubbo-provider
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ com.alibaba
+ dubbo
+
+
+ spring
+ org.springframework
+
+
+
+
+
+ org.apache.zookeeper
+ zookeeper
+
+
+ slf4j-log4j12
+ org.slf4j
+
+
+
+
+
+ com.github.sgroschupf
+ zkclient
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..d2e7677
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,50 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+//使用 providers.xml 配置
+@ImportResource(value = { "classpath:providers.xml" })
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..a684256
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,25 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-dubbo-consumer";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/service/DemoService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/service/DemoService.java
new file mode 100644
index 0000000..4dafc90
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/service/DemoService.java
@@ -0,0 +1,5 @@
+package com.md.demo.service;
+
+public interface DemoService {
+ String sayHello(String name);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/service/DemoServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/service/DemoServiceImpl.java
new file mode 100644
index 0000000..be3e623
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/service/DemoServiceImpl.java
@@ -0,0 +1,9 @@
+package com.md.demo.service;
+
+public class DemoServiceImpl implements DemoService{
+
+ public String sayHello(String name) {
+ return "Welcome to Minbo's Dubbo demo, Hello " + name;
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/logback.xml
new file mode 100644
index 0000000..8561ff9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/providers.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/providers.xml
new file mode 100644
index 0000000..3d011b0
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-dubbo-provider/src/main/resources/providers.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/README.md
new file mode 100644
index 0000000..9e266b6
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-exception
+
+【全局异常处理】技术点
+
+功能介绍
+
+1. 全局异常处理方式(自定义error请求返回结果)
+
+## 本项目教程
+
+[全局异常处理](https://hemin.blog.csdn.net/article/details/99637714)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/pom.xml
new file mode 100644
index 0000000..199e0bc
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-exception
+ jar
+
+ spring-boot2-exception
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/GlobalExceptionHandler.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/GlobalExceptionHandler.java
new file mode 100644
index 0000000..f0eec77
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/GlobalExceptionHandler.java
@@ -0,0 +1,24 @@
+package com.md.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * 统一异常处理
+ *
+ * @author Minbo
+ *
+ */
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ protected static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ @ExceptionHandler(Exception.class)
+ public String handleException(Exception e) {
+ logger.error("系统异常【全局异常】:" + e.getMessage(), e);
+ return "error";
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..0c30adf
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,44 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-exception";
+ }
+
+ /**
+ * http://localhost:9090/exception
+ *
+ * @return
+ */
+ @GetMapping("/exception")
+ public String exception() {
+ int a = 10 / 0;
+ return "exception," + a;
+ }
+
+ @GetMapping("/error")
+ public JsonResult error() {
+ return new JsonResult(ResultCode.SUCCESS_FAIL, "error错误");
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-exception/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/README.md
new file mode 100644
index 0000000..1f913be
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/README.md
@@ -0,0 +1,37 @@
+# spring-boot2-interceptor
+
+【拦截器】技术点
+
+功能介绍
+
+1. 拦截器用法介绍
+2. 如何把服务层对象注入到拦截器中,调用相关方法
+3. 开启跨域访问功能
+
+## 本项目教程
+
+[拦截器用法和场景案例分析](https://blog.csdn.net/hemin1003/article/details/90242803)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/pom.xml
new file mode 100644
index 0000000..5252206
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-interceptor
+ jar
+
+ spring-boot2-interceptor
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..de8ba26
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,79 @@
+package com.md.demo;
+
+import java.io.PrintWriter;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import com.md.demo.service.DemoService;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ @Autowired
+ private DemoService demoService;
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String uri = request.getRequestURI();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ // hello不做拦截
+ if (uri.equals("/hello")) {
+ return true;
+ }
+
+ //实现注入,调用服务层方法代码
+ logger.info("【实现注入】调用服务层方法代码:demoService.sayHello()=" + this.demoService.sayHello());
+
+ // 其他拦截请求(请求必须都带上用户id)
+ String userId = request.getParameter("userId");
+ if (userId != null) {
+ return true;
+
+ } else {
+ this.output(response, "{\n"
+ + "\"code\": \"4001\",\n"
+ + "\"message\": \"参数错误\"\n"
+ + "}");
+ return false;
+ }
+ }
+
+ /**
+ * 输出结果
+ */
+ private void output(HttpServletResponse response, String result) throws Exception {
+ response.setHeader("content-type", "text/html;charset=UTF-8");
+ response.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.println(result);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..ddda4ab
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,25 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-interceptor";
+ }
+
+ @GetMapping("/getUserInfo")
+ public String getUserInfo(String userId) {
+ return "getUserInfo from userId=" + userId;
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/service/DemoService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/service/DemoService.java
new file mode 100644
index 0000000..8bfef31
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/service/DemoService.java
@@ -0,0 +1,6 @@
+package com.md.demo.service;
+
+public interface DemoService {
+
+ public String sayHello();
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java
new file mode 100644
index 0000000..c98c89e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java
@@ -0,0 +1,15 @@
+package com.md.demo.service.impl;
+
+import org.springframework.stereotype.Service;
+
+import com.md.demo.service.DemoService;
+
+@Service
+public class DemoServiceImpl implements DemoService {
+
+ @Override
+ public String sayHello() {
+ return "hello from service layer";
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/resources/application.yml
new file mode 100644
index 0000000..2ea1b3e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+# tomcat
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/resources/logback.xml
new file mode 100644
index 0000000..0adec0a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-interceptor/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/README.md
new file mode 100644
index 0000000..c5112b6
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-log-level
+
+【动态修改日志输出级别用法】技术点
+
+功能介绍
+
+1. 动态修改日志输出级别用法
+
+## 本项目教程
+
+[动态修改日志输出级别用法](https://hemin.blog.csdn.net/article/details/103241044)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/pom.xml
new file mode 100644
index 0000000..74c7459
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-log-level
+ jar
+
+ spring-boot2-log-level
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+ io.springfox
+ springfox-swagger2
+
+
+
+ io.springfox
+ springfox-swagger-ui
+
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+
+
+ org.projectlombok
+ lombok
+
+
+ com.alibaba
+ fastjson
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..fecde15
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,50 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+@EnableSwaggerBootstrapUI
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..61886ad
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,51 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String uri = request.getRequestURI();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+
+ // 不做拦截
+ if (uri.contains("webjars") || uri.contains("/swagger")
+ || uri.contains("/csrf") || uri.equals("/") || uri.equals("/error")) {
+ return true;
+ }
+
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/SwaggerConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/SwaggerConfig.java
new file mode 100644
index 0000000..1a3e5f0
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/SwaggerConfig.java
@@ -0,0 +1,46 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+ /**
+ * 创建一个Docket对象 调用select()方法, 生成ApiSelectorBuilder对象实例,该对象负责定义外漏的API入口
+ * 通过使用RequestHandlerSelectors和PathSelectors来提供Predicate,在此我们使用any()方法,将所有API都通过Swagger进行文档管理
+ *
+ * @return
+ */
+ @Bean
+ public Docket createRestApi() {
+ return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
+ // 如果不想将所有的接口都通过swagger管理的话,可以将RequestHandlerSelectors.any()修改为RequestHandlerSelectors.basePackage()
+ // .apis(RequestHandlerSelectors.any())
+ .apis(RequestHandlerSelectors.basePackage("com.md")).paths(PathSelectors.any()).build();
+ }
+
+ @SuppressWarnings("deprecation")
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ // 标题
+ .title("SpringBoot2 中使用Swagger2 构建RESTful APIs")
+ // 简介
+ .description("This a demo for Swagger2")
+ // 服务条款
+ .termsOfServiceUrl("https://blog.csdn.net/hemin1003")
+ // 作者个人信息
+ .contact("Minbo.He")
+ // 版本
+ .version("1.0").build();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..47eb000
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,45 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 解决 swagger-ui.html 404报错
+ registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
+ registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+
+ // 解决 doc.html 404 报错
+ registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
+
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/rest/InitController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/rest/InitController.java
new file mode 100644
index 0000000..5dc9c47
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/rest/InitController.java
@@ -0,0 +1,43 @@
+package com.md.demo.rest;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author Minbo
+ */
+@RestController
+@Slf4j
+public class InitController {
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @ApiOperation(value = "/hello 欢迎入口", httpMethod = "GET")
+ @RequestMapping(value = "/hello")
+ public String hello() {
+ log.info("hello");
+ return "Hello greetings from spring-boot2-log-level";
+ }
+
+ /**
+ * Swagger注解用法:
+ *
+ * @Api:修饰整个类,描述Controller的作用
+ * @ApiOperation:描述一个类的一个方法,或者说一个接口
+ * @ApiParam:单个参数描述
+ * @ApiModel:用对象来接收参数
+ * @ApiProperty:用对象接收参数时,描述对象的一个字段
+ * @ApiResponse:HTTP响应其中1个描述
+ * @ApiResponses:HTTP响应整体描述
+ * @ApiIgnore:使用该注解忽略这个API
+ * @ApiError :发生错误返回的信息
+ * @ApiImplicitParam:一个请求参数
+ * @ApiImplicitParams:多个请求参数
+ */
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/rest/LogController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/rest/LogController.java
new file mode 100644
index 0000000..044a59d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/rest/LogController.java
@@ -0,0 +1,72 @@
+package com.md.demo.rest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.util.HttpRequestUtil;
+import com.md.demo.util.JsonResult;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author Minbo
+ */
+@RestController
+@RequestMapping("/log")
+@Api(tags = { "接口-演示" })
+@Slf4j
+public class LogController {
+
+ @Autowired
+ private Environment environment;
+
+ /**
+ * http://localhost:9090/testLog
+ *
+ * @return
+ */
+ @GetMapping("/testLog")
+ public String testLog() {
+ log.debug("this is debug log");
+ log.info("this is info log");
+ return "Hello greetings from spring-boot2-log-level";
+ }
+
+ /**
+ * http://localhost:9090/getLogger
+ *
+ * @return
+ */
+ @ApiOperation(value = "获得当前项目:日志输出级别", httpMethod = "GET")
+ @GetMapping("/getLogger")
+ public JsonResult getLogger() {
+ String port = this.environment.getProperty("local.server.port");
+ String url = "http://localhost:" + port + "/actuator/loggers/com.md";
+ String result = HttpRequestUtil.sendGet(url);
+ log.info("当前项目:日志输出级别,url={},result={}", url, result);
+ return JsonResult.ok(result);
+ }
+
+ /**
+ * http://localhost:9090/setLogger
+ *
+ * @return
+ */
+ @ApiOperation(value = "设置当前项目:日志输出级别(INFO/DEBUG)", httpMethod = "POST")
+ @PostMapping("/setLogger")
+ public JsonResult setLogger(@RequestHeader String logLevel) {
+ String port = this.environment.getProperty("local.server.port");
+ String url = "http://localhost:" + port + "/actuator/loggers/com.md";
+ String param = "{\"configuredLevel\":\"" + logLevel + "\"}";
+ String result = HttpRequestUtil.sendJsonPost(url, param);
+ log.info("设置当前项目:日志输出级别,url={},param={},result={}", url, param, result);
+ return JsonResult.ok();
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/CodeEnums.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/CodeEnums.java
new file mode 100644
index 0000000..5dabf14
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/CodeEnums.java
@@ -0,0 +1,115 @@
+package com.md.demo.util;
+
+public enum CodeEnums {
+
+
+ SUCCESS(Integer.valueOf(200), "操作成功"),
+ ERROR(Integer.valueOf(-1), "操作失败"),
+ CONTAINS_ERROR(Integer.valueOf(201),"操作完成,但包含错误"),
+
+ //--------------系统参数----------------
+ SYSTEM_ERR(Integer.valueOf(100000), "系统错误"),
+ PARA_ERR(Integer.valueOf(100001), "请求参数错误"),
+ STATUS_FORBIDDEN(Integer.valueOf(100002), "禁止访问"),
+ SERVICE_DOWN(Integer.valueOf(100003), "微服务不可用"),
+ SERVICE_BUSY(Integer.valueOf(1000031), "服务器繁忙,请稍后再试"),
+ SIGN_ERR(Integer.valueOf(100004), "url sign 签名不一致"),
+ TIMESTAMP_ERR(Integer.valueOf(100005), "timestamp与服务器时间相差较大"),
+ NONCE_REPEAT(Integer.valueOf(100006), "重复提交"),
+ INVALID_TOKEN(Integer.valueOf(100007), "无效的token"),
+ //EXPIRED_TOKEN(Integer.valueOf(100008), "token已经过期"),
+ JSONMAPPINGEXCEPTION(Integer.valueOf(100009), "JSON映射异常"),
+ SYS_PARAMETER_NULL(Integer.valueOf(100010), "请联系管理员配置正确相关参数"),
+ SYS_BIZ_ERR(Integer.valueOf(100011), "业务逻辑异常"),
+ PARAM_VALIDATE_REFUSE(Integer.valueOf(100012), "校验不通过"),
+ REPEAT(Integer.valueOf(100013), "网络开小差,请稍后重试"),
+ //---------end--系统参数----------------
+
+
+ //--------------登录----------------
+ USER_NOT_LOGIN(Integer.valueOf(110000), "用户未登录"),
+ USER_EXIST(Integer.valueOf(110001), "用户已经存在"),
+ USER_NOT_EXIST(Integer.valueOf(110002), "用户不存在"),
+ USER_IS_LOCK(Integer.valueOf(110003), "用户被冻结"),
+ USER_PWD_FAIL(Integer.valueOf(110004), "用户名或密码错误"),
+ //---------end--登录----------------
+
+ INFO_NOT_ALL(Integer.valueOf(110005), "信息不全"),
+
+
+ UP_HAS_USER(Integer.valueOf(200000), "当前手机号码已注册!!!"),
+ UP_NOT_USER(Integer.valueOf(200002), "当前手机号码未注册"),
+ UP_ERR(Integer.valueOf(200001), "接口异常"),
+ UP_INVITEPOSTER_NULL(Integer.valueOf(200004), "生产推广海报出现异常,请联系推荐人!"),
+
+ //--------------公共业务参数----------------
+
+ HSRJ_TOKEN_NOT_VALID(Integer.valueOf(401), "TOKEN无效"),
+ REDO(Integer.valueOf(10025), "重复操作"),
+ EXIST_NAME(Integer.valueOf(10002), "名称已经存在"),
+ MULTIPLE_RECORD(Integer.valueOf(10053), "存在多条记录"),
+ RECORD_NOT_EXIST(Integer.valueOf(10013), "暂无数据"),
+ RECORD_EXIST(Integer.valueOf(10014), "记录已经存在"),
+ USER_ROLE_LIMIT(Integer.valueOf(10008), "用户没有操作的权限"),
+ EMAIL_USED(Integer.valueOf(10009), "邮箱已经被使用"),
+ USER_VERSION_NULL(Integer.valueOf(1330004), "请联系管理员配置不存在的版本信息"),
+
+
+ //--------------业务参数----------------
+ USER_SPREAD_NOT_EXIST(Integer.valueOf(10021), "邀请码无效"),
+ VALIDATE_CODE_NOT(Integer.valueOf(10104), "验证码不正确"),
+ SMS_TIME_OUT(Integer.valueOf(10030), "短信验证超时或不存在"),
+
+
+ STORE_APROVING(Integer.valueOf(11101), "店铺审核中,请稍等"),
+ STORE_NOT(Integer.valueOf(11102), "暂无店铺"),
+
+
+ USER_CANT_CHANGE_PASSWORD(Integer.valueOf(10012), "原始密码不正确"),
+
+ NONE_OPERATE_RECORDS(Integer.valueOf(10015), "没有需要操作的记录"),
+ INVALID_USER(Integer.valueOf(10016), "无效的用户"),
+ USER_ACCOUNT_EMPTY(Integer.valueOf(10020), "用户账户信息为空"),
+ USER_RECIPIENT_EMPTY(Integer.valueOf(10022), "用户收款信息为空"),
+ USER_BALANCE_NOT_ENOUGH(Integer.valueOf(10023), "用户余额不足"),
+
+
+ USER_DEFAULT_STORE_NOT_EXIST(Integer.valueOf(10024), "用户店铺不存在"),
+ NOT_VALID_AUDIT_STATUS(Integer.valueOf(10026), "无效的审核状态"),
+ AUDIT_STATUS_CHANGED(Integer.valueOf(10028), "审核失败,状态已改变"),
+
+ ACTIVITY_UNAVAILABLE(Integer.valueOf(10088), "活动过期或名额已经抢光"),
+
+ MORE_THEN_QULITY_UPPER_LIMIT(Integer.valueOf(100100), "超出限购数量"),
+ //---------end--业务参数----------------
+
+ //--------------第三方参数----------------
+ ERR_FRAMEWORK(Integer.valueOf(30001), "系统异常"),
+ OK_FRAMEWORK(Integer.valueOf(0), "操作成功"),
+ SERVICE_DOWN_FRAMEWORK(Integer.valueOf(30000), "微服务不可用"),
+ //---------end--第三方参数----------------
+ ;
+ private Integer code;
+ private String msg;
+
+ private CodeEnums(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public Integer getCode() {
+ return this.code;
+ }
+
+ public void setCode(Integer code) {
+ this.code = code;
+ }
+
+ public String getMsg() {
+ return this.msg;
+ }
+
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/HttpRequestUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/HttpRequestUtil.java
new file mode 100644
index 0000000..1e18f36
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/HttpRequestUtil.java
@@ -0,0 +1,630 @@
+package com.md.demo.util;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Map;
+import java.util.zip.GZIPInputStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HttpRequestUtil {
+
+ protected static Logger logger = LoggerFactory.getLogger(HttpRequestUtil.class);
+
+ /**
+ * 用于接口检测 向指定URL发送GET方法的请求
+ *
+ * @param url 发送请求的URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @return URL 所代表远程资源的响应结果
+ */
+ public static String sendGet(String url) {
+ String result = "";
+ BufferedReader in = null;
+ try {
+ String urlNameString = url;
+ URL realUrl = new URL(urlNameString);
+ // 打开和URL之间的连接
+ URLConnection connection = realUrl.openConnection();
+ connection.setConnectTimeout(5000);
+ connection.setReadTimeout(5000);
+ // 设置通用的请求属性
+ connection.setRequestProperty("accept", "*/*");
+ connection.setRequestProperty("connection", "Keep-Alive");
+ connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 建立实际的连接
+ connection.connect();
+// 获取所有响应头字段
+// Map> map = connection.getHeaderFields();
+// // 遍历所有的响应头字段
+// for (String key : map.keySet()) {
+// System.out.println(key + "--->" + map.get(key));
+// }
+ // 定义 BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送GET请求出现异常:" + e.getMessage() + ", url=" + url);
+ result = "";
+ }
+ // 使用finally块来关闭输入流
+ finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (Exception e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ result = "";
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 向指定URL发送GET方法的请求
+ *
+ * @param url 发送请求的URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @return URL 所代表远程资源的响应结果
+ */
+ public static String sendGet(String url, String param) {
+ String result = "";
+ BufferedReader in = null;
+ try {
+ String urlNameString = url + "?" + param;
+ URL realUrl = new URL(urlNameString);
+
+// SocketAddress address = new InetSocketAddress("1.194.74.2", 29082);
+// Proxy proxy = new Proxy(Type.HTTP, address);
+ // 打开和URL之间的连接
+// URLConnection connection = realUrl.openConnection(proxy);
+
+// // 打开和URL之间的连接
+ URLConnection connection = realUrl.openConnection();
+ connection.setConnectTimeout(5000);
+ connection.setReadTimeout(5000);
+ // 设置通用的请求属性
+ connection.setRequestProperty("accept", "*/*");
+ connection.setRequestProperty("connection", "Keep-Alive");
+ connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 建立实际的连接
+ connection.connect();
+// 获取所有响应头字段
+// Map> map = connection.getHeaderFields();
+// // 遍历所有的响应头字段
+// for (String key : map.keySet()) {
+// System.out.println(key + "--->" + map.get(key));
+// }
+ // 定义 BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送GET请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" + param);
+ result = "";
+ }
+ // 使用finally块来关闭输入流
+ finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (Exception e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ result = "";
+ }
+ }
+ return result;
+ }
+
+ public static String sendGet2(String url, String param) {
+ StringBuffer stringBuffer = new StringBuffer();
+ try {
+ String urlStr = url + "?" + param;
+ URL realUrl = new URL(urlStr);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(5000);
+ conn.setReadTimeout(5000);
+ // 设置通用的请求属性
+ conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
+ conn.setRequestProperty("Accept-Encoding", "gzip");
+ conn.connect();
+ GZIPInputStream gZIPInputStream = null;
+ String encoding = conn.getContentEncoding();
+ if ("gzip".equals(encoding)) {
+ gZIPInputStream = new GZIPInputStream(conn.getInputStream());
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gZIPInputStream, "utf-8"));
+ String line = null;
+ while ((line = bufferedReader.readLine()) != null) {
+ // 转化为UTF-8的编码格式
+ line = new String(line.getBytes("UTF-8"));
+ stringBuffer.append(line);
+ }
+ bufferedReader.close();
+ return stringBuffer.toString();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 向指定 URL 发送POST方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendPost(String url, String param) {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ String result = "";
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(5000);
+ conn.setReadTimeout(5000);
+ // 设置通用的请求属性
+ conn.setRequestProperty("accept", "*/*");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流
+ out = new PrintWriter(conn.getOutputStream());
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 定义BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送POST请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" + param);
+ }
+ // 使用finally块来关闭输出流、输入流
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 向指定 URL 发送POST方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendPost(String url, String param, int timeout) {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ String result = "";
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(timeout);
+ conn.setReadTimeout(timeout);
+ // 设置通用的请求属性
+ conn.setRequestProperty("accept", "*/*");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流
+ out = new PrintWriter(conn.getOutputStream());
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 定义BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送POST请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" + param);
+ }
+ // 使用finally块来关闭输出流、输入流
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e2) {
+ logger.error("关闭流异常:" + e2.getMessage());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 向指定 URL 发送POST方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数,请求参数应该是 json 的形式。
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendJsonPost(String url, String param) {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ String result = "";
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(5000);
+ conn.setReadTimeout(5000);
+ // 设置通用的请求属性
+// conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
+// conn.setRequestProperty("accept", "application/json;charset=utf-8");
+ conn.setRequestProperty("Content-Type", "application/json");
+ conn.setRequestProperty("accept", "application/json");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流
+ out = new PrintWriter(conn.getOutputStream());
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 定义BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送POST请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" + param);
+ }
+ // 使用finally块来关闭输出流、输入流
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 向指定 URL 发送POST方法的请求,多一个Accept-Encoding类型
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数,请求参数应该是 json 的形式。
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendJsonPost2(String url, String param) {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ String result = "";
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(5000);
+ conn.setReadTimeout(5000);
+ // 设置通用的请求属性
+ conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
+ conn.setRequestProperty("Accept-Encoding", "gzip");
+// conn.setRequestProperty("accept", "application/json");
+// conn.setRequestProperty("connection", "Keep-Alive");
+// conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流
+ out = new PrintWriter(conn.getOutputStream());
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 定义BufferedReader输入流来读取URL的响应
+ // in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ // 定义一个内存输出流
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ GZIPInputStream gis = new GZIPInputStream(conn.getInputStream());
+ int len1 = -1;
+ byte[] b1 = new byte[1024];
+ while ((len1 = gis.read(b1)) != -1) {
+ byteArrayOutputStream.write(b1, 0, len1);
+ }
+ byteArrayOutputStream.close();
+ return byteArrayOutputStream.toString();
+ } catch (Exception e) {
+ // logger.error("发送POST请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" +
+ // param);
+ }
+ // 使用finally块来关闭输出流、输入流
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gzip模式下的自定义表头发送post请求
+ *
+ * @param url
+ * @param param
+ * @param header
+ * @return
+ */
+ public static String sendJsonPost3(String url, String param, Map header) {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ String result = "";
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(5000);
+ conn.setReadTimeout(5000);
+ // 设置通用的请求属性
+ if (!header.isEmpty()) {
+ for (Map.Entry m : header.entrySet()) {
+ conn.setRequestProperty(m.getKey(), m.getValue());
+ }
+ }
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流
+ out = new PrintWriter(conn.getOutputStream());
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 定义BufferedReader输入流来读取URL的响应
+ // in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ // 定义一个内存输出流
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ GZIPInputStream gis = new GZIPInputStream(conn.getInputStream());
+ int len1 = -1;
+ byte[] b1 = new byte[1024];
+ while ((len1 = gis.read(b1)) != -1) {
+ byteArrayOutputStream.write(b1, 0, len1);
+ }
+ byteArrayOutputStream.close();
+ return byteArrayOutputStream.toString();
+ } catch (Exception e) {
+ // logger.error("发送POST请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" +
+ // param);
+ }
+ // 使用finally块来关闭输出流、输入流
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ }
+ }
+ return result;
+ }
+
+ public static String sendJsonPost(String url, String param, Map header) {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ String result = "";
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(5000);
+ conn.setReadTimeout(5000);
+ // 设置通用的请求属性
+// conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
+// conn.setRequestProperty("accept", "application/json;charset=utf-8");
+ if (!header.isEmpty()) {
+ for (Map.Entry m : header.entrySet()) {
+ conn.setRequestProperty(m.getKey(), m.getValue());
+ }
+ }
+ conn.setRequestProperty("Content-Type", "application/json");
+ conn.setRequestProperty("accept", "application/json");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流
+ out = new PrintWriter(conn.getOutputStream());
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 定义BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送POST请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" + param);
+ }
+ // 使用finally块来关闭输出流、输入流
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 正常POST请求下的全自定义HEAD头方法
+ *
+ * @param url
+ * @param param
+ * @param header
+ * @return
+ */
+ public static String sendJsonPostByCustomHead(String url, String param, Map header) {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ String result = "";
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ conn.setConnectTimeout(5000);
+ conn.setReadTimeout(5000);
+ // 设置通用的请求属性
+// conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
+// conn.setRequestProperty("accept", "application/json;charset=utf-8");
+ if (!header.isEmpty()) {
+ for (Map.Entry m : header.entrySet()) {
+ conn.setRequestProperty(m.getKey(), m.getValue());
+ }
+ }
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流
+ out = new PrintWriter(conn.getOutputStream());
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 定义BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送POST请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" + param);
+ }
+ // 使用finally块来关闭输出流、输入流
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 向指定URL发送GET方法的请求
+ *
+ * @param url 发送请求的URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @return URL 所代表远程资源的响应结果
+ */
+ public static String sendGet(String url, String param, int timeout) {
+ String result = "";
+ BufferedReader in = null;
+ try {
+ String urlNameString = url + "?" + param;
+ URL realUrl = new URL(urlNameString);
+ // 打开和URL之间的连接
+ URLConnection connection = realUrl.openConnection();
+ connection.setConnectTimeout(timeout);
+ connection.setReadTimeout(timeout);
+ // 设置通用的请求属性
+ connection.setRequestProperty("accept", "*/*");
+ connection.setRequestProperty("connection", "Keep-Alive");
+ connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ // 建立实际的连接
+ connection.connect();
+// 获取所有响应头字段
+// Map> map = connection.getHeaderFields();
+// // 遍历所有的响应头字段
+// for (String key : map.keySet()) {
+// System.out.println(key + "--->" + map.get(key));
+// }
+ // 定义 BufferedReader输入流来读取URL的响应
+ in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
+ String line;
+ while ((line = in.readLine()) != null) {
+ result += line;
+ }
+ } catch (Exception e) {
+ logger.error("发送GET请求出现异常:" + e.getMessage() + ", url=" + url + ", param=" + param);
+ result = "";
+ }
+ // 使用finally块来关闭输入流
+ finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (Exception e2) {
+ logger.error("关闭流异常:" + e2.getMessage(), e2);
+ result = "";
+ }
+ }
+ return result;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f3ec5c9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,102 @@
+package com.md.demo.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@NoArgsConstructor
+@ApiModel(description = "通用参数")
+public class JsonResult implements Serializable {
+
+ @ApiModelProperty(value = "响应业务状态", required = true, position = 1)
+ private Integer status;
+
+ @ApiModelProperty(value = "响应消息", required = true, position = 2)
+ private String msg;
+
+ @ApiModelProperty(value = "响应中的数据", required = true, position = 3)
+ private T data;
+
+ public static JsonResult build(Integer status, String msg, Object data) {
+ return new JsonResult(status, msg, data);
+ }
+
+ public static JsonResult fromJSONObject(JSONObject jsonObject) {
+ if (jsonObject != null) {
+ if (jsonObject.containsKey("code")) {
+ Integer status = jsonObject.getInteger("code");
+ if (status == 0)
+ status = CodeEnums.SUCCESS.getCode();
+ if (status == 1)
+ status = CodeEnums.ERROR.getCode();
+ String msg = jsonObject.getString("msg");
+ Object data = jsonObject.get("data");
+ return new JsonResult(status, msg, data);
+ } else {
+ return new JsonResult(CodeEnums.ERROR.getCode(), "不正确的数据格式", null);
+ }
+
+ } else {
+ return new JsonResult(CodeEnums.SERVICE_DOWN.getCode(), CodeEnums.SERVICE_DOWN.getMsg(), null);
+ }
+
+ }
+
+ public static JsonResult ok(Object data) {
+ return new JsonResult(data);
+ }
+
+ public static JsonResult ok() {
+ return new JsonResult(null);
+ }
+
+ public static JsonResult build(Integer status, String msg) {
+ return new JsonResult(status, msg, null);
+ }
+
+ public static JsonResult build(CodeEnums codeEnums) {
+ return new JsonResult(codeEnums.getCode(), codeEnums.getMsg(), null);
+ }
+
+ public JsonResult(Integer status, String msg, T data) {
+ this.status = status;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ public JsonResult(T data) {
+ this.status = CodeEnums.SUCCESS.getCode();
+ this.msg = "OK";
+ this.data = data;
+ }
+
+ @JSONField(serialize = false)
+ @JsonIgnore
+ @ApiModelProperty(hidden = true)
+ public boolean isSuccess() {
+ return this.status.intValue() == CodeEnums.SUCCESS.getCode().intValue();
+ }
+
+ @JSONField(serialize = false)
+ @JsonIgnore
+ @ApiModelProperty(hidden = true)
+ public T getDataSuc() {
+ if (isSuccess()) {
+ return this.data;
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "JsonResult{" + "status=" + status + ", msg='" + msg + '\'' + ", data=" + data + '}';
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/resources/application.yml
new file mode 100644
index 0000000..13e14db
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/resources/application.yml
@@ -0,0 +1,8 @@
+server:
+ port: 9090
+# log
+management:
+ endpoints:
+ web:
+ exposure:
+ include: loggers
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-log-level/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/README.md
new file mode 100644
index 0000000..ce16493
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-logback-async
+
+【日志异步化处理用法】技术点
+
+功能介绍
+
+1. 日志异步化处理
+
+## 本项目教程
+
+[日志异步化处理用法](https://hemin.blog.csdn.net/article/details/99637609)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/pom.xml
new file mode 100644
index 0000000..8945720
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-logback-async
+ jar
+
+ spring-boot2-logback-async
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..62e1684
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,26 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-logback";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/resources/logback.xml
new file mode 100644
index 0000000..c4c42eb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-async/src/main/resources/logback.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] - %m%n
+
+ UTF-8
+
+
+
+
+
+ 0
+
+ 1024
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/README.md
new file mode 100644
index 0000000..b7d2584
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/README.md
@@ -0,0 +1,38 @@
+# spring-boot2-logback-elk
+
+【ELK日志集成】技术点
+
+功能介绍
+
+1. ELK日志集成说明
+
+## 本项目教程
+
+[ELK日志集成](https://hemin.blog.csdn.net/article/details/99637553)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 附加
+
+[从零开始搭建一个ELK实时日志收集系统](https://blog.csdn.net/hemin1003/article/details/73295303)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/pom.xml
new file mode 100644
index 0000000..f01e197
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-logback-elk
+ jar
+
+ spring-boot2-logback-elk
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..62e1684
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,26 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-logback";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/resources/logback.xml
new file mode 100644
index 0000000..92f96d4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback-elk/src/main/resources/logback.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+ 192.168.1.1:4567
+
+
+ {"appname":"test-spring-boot2-logback-elk"}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/README.md
new file mode 100644
index 0000000..6bd9a7c
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-logback
+
+【Logback日志框架集成】技术点
+
+功能介绍
+
+1. Logback日志文件讲解说明
+
+## 本项目教程
+
+[Logback日志框架集成](https://hemin.blog.csdn.net/article/details/99637532)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/pom.xml
new file mode 100644
index 0000000..b6a7dbd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-logback
+ jar
+
+ spring-boot2-logback
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..62e1684
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,26 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-logback";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/resources/application.yml
new file mode 100644
index 0000000..afef73d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-logback/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/README.md
new file mode 100644
index 0000000..0984241
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/README.md
@@ -0,0 +1,38 @@
+# spring-boot2-mongodb
+
+【MongoDB集成】技术点
+
+功能介绍
+
+1. MongoDB集成用法
+
+## 本项目教程
+
+[MongoDB集成用法](https://hemin.blog.csdn.net/article/details/99637830)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## mongodb安装教程
+
+[MongoDB 教程](https://www.runoob.com/mongodb/mongodb-tutorial.html)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/pom.xml
new file mode 100644
index 0000000..a175b64
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-mongodb
+ jar
+
+ spring-boot2-mongodb
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/dao/DemoDao.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/dao/DemoDao.java
new file mode 100644
index 0000000..e081f3d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/dao/DemoDao.java
@@ -0,0 +1,14 @@
+package com.md.demo.dao;
+
+import com.md.demo.vo.DemoEntity;
+
+public interface DemoDao {
+
+ void saveDemo(DemoEntity demoEntity);
+
+ void removeDemo(DemoEntity demoEntity);
+
+ void updateDemo(DemoEntity demoEntity);
+
+ DemoEntity findDemoById(Long id);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/dao/impl/DemoDaoImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/dao/impl/DemoDaoImpl.java
new file mode 100644
index 0000000..510b170
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/dao/impl/DemoDaoImpl.java
@@ -0,0 +1,50 @@
+package com.md.demo.dao.impl;
+
+import javax.annotation.Resource;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.stereotype.Component;
+
+import com.md.demo.dao.DemoDao;
+import com.md.demo.vo.DemoEntity;
+
+@Component
+public class DemoDaoImpl implements DemoDao {
+
+ @Resource
+ private MongoTemplate mongoTemplate;
+
+ @Override
+ public void saveDemo(DemoEntity demoEntity) {
+ mongoTemplate.save(demoEntity);
+ }
+
+ @Override
+ public void removeDemo(DemoEntity demoEntity) {
+ mongoTemplate.remove(demoEntity);
+ }
+
+ @Override
+ public void updateDemo(DemoEntity demoEntity) {
+ Query query = new Query(Criteria.where("id").is(demoEntity.getId()));
+
+ Update update = new Update();
+ update.set("title", demoEntity.getTitle());
+ update.set("description", demoEntity.getDescription());
+ update.set("by", demoEntity.getBy());
+ update.set("url", demoEntity.getUrl());
+
+ mongoTemplate.updateFirst(query, update, DemoEntity.class);
+ }
+
+ @Override
+ public DemoEntity findDemoById(Long id) {
+ Query query = new Query(Criteria.where("id").is(id));
+ DemoEntity demoEntity = mongoTemplate.findOne(query, DemoEntity.class);
+ return demoEntity;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..2a22080
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,100 @@
+package com.md.demo.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.service.DemoService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+import com.md.demo.vo.DemoEntity;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-mongodb";
+ }
+
+ @Autowired
+ private DemoService demoService;
+
+ /**
+ * 新增
+ */
+ @GetMapping("/saveDemoTest")
+ public JsonResult saveDemoTest() {
+
+ DemoEntity demoEntity = new DemoEntity();
+ demoEntity.setId(1L);
+ demoEntity.setTitle("使用mongodb");
+ demoEntity.setDescription("这是描述");
+ demoEntity.setBy("minbo");
+ demoEntity.setUrl("https://blog.csdn.net/hemin1003");
+
+ this.demoService.addDemo(demoEntity);
+
+ demoEntity = new DemoEntity();
+ demoEntity.setId(2L);
+ demoEntity.setTitle("使用mongodb2");
+ demoEntity.setDescription("这是描述2");
+ demoEntity.setBy("minbo2");
+ demoEntity.setUrl("https://blog.csdn.net/hemin1003");
+
+ this.demoService.addDemo(demoEntity);
+
+ return new JsonResult(ResultCode.SUCCESS);
+ }
+
+ /**
+ * 删除
+ */
+ @GetMapping("/removeDemoTest")
+ public JsonResult removeDemoTest(Long id) {
+ this.demoService.removeDemo(id);
+
+ return new JsonResult(ResultCode.SUCCESS);
+ }
+
+ /**
+ * 修改
+ */
+ @GetMapping("/updateDemoTest")
+ public JsonResult updateDemoTest() {
+
+ DemoEntity demoEntity = new DemoEntity();
+ demoEntity.setId(1L);
+ demoEntity.setTitle("使用mongodb3");
+ demoEntity.setDescription("这是描述3");
+ demoEntity.setBy("minbo3");
+ demoEntity.setUrl("https://blog.csdn.net/hemin1003");
+
+ this.demoService.modifyDemo(demoEntity);
+
+ return new JsonResult(ResultCode.SUCCESS, demoEntity);
+ }
+
+ /**
+ * 查找
+ */
+ @GetMapping("/findDemoByIdTest")
+ public JsonResult findDemoByIdTest(Long id) {
+ DemoEntity demoEntity = this.demoService.findDemoById(id);
+ System.out.println(demoEntity.toString());
+ return new JsonResult(ResultCode.SUCCESS, demoEntity);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/service/DemoService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/service/DemoService.java
new file mode 100644
index 0000000..94eb689
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/service/DemoService.java
@@ -0,0 +1,14 @@
+package com.md.demo.service;
+
+import com.md.demo.vo.DemoEntity;
+
+public interface DemoService {
+
+ void addDemo(DemoEntity demoEntity);
+
+ void removeDemo(Long id);
+
+ void modifyDemo(DemoEntity demoEntity);
+
+ DemoEntity findDemoById(Long id);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java
new file mode 100644
index 0000000..698a636
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java
@@ -0,0 +1,38 @@
+package com.md.demo.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.md.demo.dao.DemoDao;
+import com.md.demo.service.DemoService;
+import com.md.demo.vo.DemoEntity;
+
+@Service
+public class DemoServiceImpl implements DemoService {
+
+ @Autowired
+ private DemoDao demoDao;
+
+ @Override
+ public void addDemo(DemoEntity demoEntity) {
+ this.demoDao.saveDemo(demoEntity);
+ }
+
+ @Override
+ public void removeDemo(Long id) {
+ DemoEntity demoEntity = new DemoEntity();
+ demoEntity.setId(id);
+ this.demoDao.removeDemo(demoEntity);
+ }
+
+ @Override
+ public void modifyDemo(DemoEntity demoEntity) {
+ this.demoDao.updateDemo(demoEntity);
+ }
+
+ @Override
+ public DemoEntity findDemoById(Long id) {
+ return this.demoDao.findDemoById(id);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/vo/DemoEntity.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/vo/DemoEntity.java
new file mode 100644
index 0000000..1a41f56
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/java/com/md/demo/vo/DemoEntity.java
@@ -0,0 +1,79 @@
+package com.md.demo.vo;
+
+import java.io.Serializable;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+@Document(collection = "demo_collection")
+public class DemoEntity implements Serializable {
+
+ private static final long serialVersionUID = -2793367984250634455L;
+
+ private String _id;
+
+ @Id
+ private Long id;
+
+ private String title;
+
+ private String description;
+
+ private String by;
+
+ private String url;
+
+ public String get_id() {
+ return _id;
+ }
+
+ public void set_id(String _id) {
+ this._id = _id;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getBy() {
+ return by;
+ }
+
+ public void setBy(String by) {
+ this.by = by;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ @Override
+ public String toString() {
+ return "DemoEntity [id=" + id + ", title=" + title + ", description=" + description + ", by=" + by + ", url="
+ + url + "]";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/resources/application.yml
new file mode 100644
index 0000000..af2b000
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/resources/application.yml
@@ -0,0 +1,8 @@
+spring:
+ application:
+ name: spring-boot-mongodb
+ data:
+ mongodb:
+ uri: mongodb://127.0.0.1/demo
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mongodb/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/README.md
new file mode 100644
index 0000000..b051aca
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-multi-resources
+
+【多环境配置文件用法】技术点
+
+功能介绍
+
+1. 多环境配置文件用法
+
+## 本项目文档教程
+
+[多环境配置文件用法](https://hemin.blog.csdn.net/article/details/96483484)
+
+## 该系列教程
+
+[SpringBoot系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/db1-init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/db1-init.sql
new file mode 100644
index 0000000..d076fd1
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/db1-init.sql
@@ -0,0 +1,14 @@
+drop table city;
+
+CREATE TABLE `city` (
+ `id` int(11) NOT NULL primary key,
+ `name` varchar(32) DEFAULT NULL,
+ `state` varchar(32) DEFAULT NULL,
+ `country` varchar(32) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `city` (`id`, `name`, `state`, `country`)
+VALUES
+ (1, '广州11', 'GZ11', 'CH11'),
+ (2, '北京12', 'BJ12', 'CH12'),
+ (3, '深圳13', 'SZ13', 'CH13');
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/db2-init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/db2-init.sql
new file mode 100644
index 0000000..be2786c
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/db2-init.sql
@@ -0,0 +1,14 @@
+drop table city;
+
+CREATE TABLE `city` (
+ `id` int(11) NOT NULL primary key,
+ `name` varchar(32) DEFAULT NULL,
+ `state` varchar(32) DEFAULT NULL,
+ `country` varchar(32) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `city` (`id`, `name`, `state`, `country`)
+VALUES
+ (4, '广州14', 'GZ14', 'CH14'),
+ (5, '北京15', 'BJ15', 'CH15'),
+ (6, '深圳16', 'SZ16', 'CH16');
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/pom.xml
new file mode 100644
index 0000000..36bf65e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-multi-resources
+ jar
+
+ spring-boot2-multi-resources
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/bo/City.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/bo/City.java
new file mode 100644
index 0000000..294902e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/bo/City.java
@@ -0,0 +1,53 @@
+package com.md.demo.bo;
+
+import java.io.Serializable;
+
+public class City implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private Long id;
+
+ private String name;
+
+ private String state;
+
+ private String country;
+
+ public Long getId() {
+ return this.id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getState() {
+ return this.state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCountry() {
+ return this.country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ @Override
+ public String toString() {
+ return getId() + "," + getName() + "," + getState() + "," + getCountry();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/dao/CityDao.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/dao/CityDao.java
new file mode 100644
index 0000000..65f92b4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/dao/CityDao.java
@@ -0,0 +1,13 @@
+package com.md.demo.dao;
+
+import java.util.List;
+
+import com.md.demo.vo.CityVo;
+
+public interface CityDao {
+
+ public List listCities();
+
+ public CityVo getCityById(Long id);
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
new file mode 100644
index 0000000..a1bfecf
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
@@ -0,0 +1,28 @@
+package com.md.demo.dao.impl;
+
+import java.util.List;
+
+import org.mybatis.spring.SqlSessionTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.vo.CityVo;
+
+@Component
+public class CityDaoImpl implements CityDao {
+
+ @Autowired
+ public SqlSessionTemplate sqlSessionTemplate;
+
+ @Override
+ public List listCities() {
+ return this.sqlSessionTemplate.selectList("listCities");
+ }
+
+ @Override
+ public CityVo getCityById(Long id) {
+ return this.sqlSessionTemplate.selectOne("getCityById", id);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..06134aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,58 @@
+package com.md.demo.rest;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.service.CityService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+import com.md.demo.vo.CityVo;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ @Autowired
+ private CityService cityService;
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-multi-resources";
+ }
+
+ /**
+ * http://localhost:9090/listCities
+ *
+ * @return
+ */
+ @GetMapping("/listCities")
+ public JsonResult listCities() {
+ List list = this.cityService.listCities();
+ return new JsonResult(ResultCode.SUCCESS, list);
+ }
+
+ /**
+ * http://localhost:9090/getCityById?id=1
+ *
+ * @return
+ */
+ @GetMapping("/getCityById")
+ public JsonResult listCities(Long id) {
+ CityVo obj = this.cityService.getCityById(id);
+ return new JsonResult(ResultCode.SUCCESS, obj);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/service/CityService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/service/CityService.java
new file mode 100644
index 0000000..391199f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/service/CityService.java
@@ -0,0 +1,11 @@
+package com.md.demo.service;
+
+import java.util.List;
+import com.md.demo.vo.CityVo;
+
+public interface CityService {
+
+ public List listCities();
+
+ public CityVo getCityById(Long id);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/service/impl/CityServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
new file mode 100644
index 0000000..f3cf11b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
@@ -0,0 +1,34 @@
+package com.md.demo.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.service.CityService;
+import com.md.demo.vo.CityVo;
+
+@Service
+public class CityServiceImpl implements CityService {
+
+ @Autowired
+ private CityDao cityDao;
+
+ /**
+ * 获得城市列表
+ */
+ @Override
+ public List listCities() {
+ return this.cityDao.listCities();
+ }
+
+ /**
+ * 根据id,获得某个城市
+ */
+ @Override
+ public CityVo getCityById(Long id) {
+ return this.cityDao.getCityById(id);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/vo/CityVo.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/vo/CityVo.java
new file mode 100644
index 0000000..56fc798
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/java/com/md/demo/vo/CityVo.java
@@ -0,0 +1,9 @@
+package com.md.demo.vo;
+
+import com.md.demo.bo.City;
+
+public class CityVo extends City {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application-dev.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..3282422
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application-dev.yml
@@ -0,0 +1,7 @@
+# 多数据源用法,同spring-boot2-mysql-multi-datasource项目一样
+spring:
+ datasource:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://192.168.0.1:3306/db1?useUnicode=true&autoReconnect=true&allowMultiQueries=true&useSSL=false
+ username: root
+ password: 123456
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application-prod.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..f059d9c
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application-prod.yml
@@ -0,0 +1,7 @@
+# 多数据源用法,同spring-boot2-mysql-multi-datasource项目一样
+spring:
+ datasource:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://192.168.0.1:3306/db2?useUnicode=true&autoReconnect=true&allowMultiQueries=true&useSSL=false
+ username: root
+ password: 123456
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application.yml
new file mode 100644
index 0000000..54c0c54
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/application.yml
@@ -0,0 +1,18 @@
+# 不同的环境使用不同的配置,通过指定启动参数使用不同的profile和配置文件,比如:
+# 开发环境:java -jar xxx.jar --spring.profiles.active=dev
+# 生产环境:java -jar xxx.jar --spring.profiles.active=prod
+spring:
+ profiles:
+ active: dev
+
+# tomcat
+server:
+ port: 9090
+
+# mybatis
+mybatis:
+ config-location: classpath:mybatis-config.xml
+
+# logging
+logging:
+ config: classpath:logback-${spring.profiles.active}.xml
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/logback-dev.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/logback-dev.xml
new file mode 100644
index 0000000..d2f95c4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/logback-dev.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/logback-prod.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/logback-prod.xml
new file mode 100644
index 0000000..93050c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/logback-prod.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/mybatis-config.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/mybatis-config.xml
new file mode 100644
index 0000000..dbc7d97
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/mybatis-config.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/mybatis/mapper/CityMapper.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/mybatis/mapper/CityMapper.xml
new file mode 100644
index 0000000..135cecd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-multi-resources/src/main/resources/mybatis/mapper/CityMapper.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/README.md
new file mode 100644
index 0000000..78a08d0
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-mybatis-plus-multi-datasource
+
+【MybatisPlus框架动态数据源用法】技术点
+
+功能介绍
+
+1. MybatisPlus框架动态数据源用法:支持多个DB,切换数据源
+
+## 本项目文档教程
+
+[MybatisPlus框架动态数据源用法(支持多个DB,动态切换数据源)](https://hemin.blog.csdn.net/article/details/105145250)
+
+## 该系列教程
+
+[SpringBoot从入门到精通教程](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/db1-init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/db1-init.sql
new file mode 100644
index 0000000..7d79d2a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/db1-init.sql
@@ -0,0 +1,14 @@
+-- for db1
+
+drop table users;
+
+CREATE TABLE `users` (
+ `username` varchar(50) NOT NULL COMMENT '用户名',
+ `password` varchar(500) NOT NULL COMMENT '密码',
+ `enabled` tinyint(1) NOT NULL COMMENT '是否启用',
+ PRIMARY KEY (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+INSERT INTO `users` (`username`, `password`, `enabled`)
+VALUES
+ ('master', '123456', 1);
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/db2-init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/db2-init.sql
new file mode 100644
index 0000000..bf7c799
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/db2-init.sql
@@ -0,0 +1,14 @@
+-- for db2
+
+drop table users;
+
+CREATE TABLE `users` (
+ `username` varchar(50) NOT NULL COMMENT '用户名',
+ `password` varchar(500) NOT NULL COMMENT '密码',
+ `enabled` tinyint(1) NOT NULL COMMENT '是否启用',
+ PRIMARY KEY (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+INSERT INTO `users` (`username`, `password`, `enabled`)
+VALUES
+ ('slave', '654321', 1);
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/pom.xml
new file mode 100644
index 0000000..28a63a8
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/pom.xml
@@ -0,0 +1,105 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-mybatis-plus-multi-datasource
+ jar
+
+ spring-boot2-mybatis-plus-multi-datasource
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+ 2.9.2
+ 3.2.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ mysql
+ mysql-connector-java
+
+
+ org.projectlombok
+ lombok
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ junit
+ junit
+
+
+
+ io.springfox
+ springfox-swagger2
+
+
+
+ io.springfox
+ springfox-swagger-ui
+
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+
+
+
+ com.baomidou
+ mybatis-plus-generator
+ ${mybatisplus.version}
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatisplus.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-freemarker
+
+
+
+ com.baomidou
+ dynamic-datasource-spring-boot-starter
+ 2.5.4
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..d3c116e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,52 @@
+package com.md.demo;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+@EnableSwaggerBootstrapUI
+@MapperScan("com.md.demo.dao")
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/SwaggerConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/SwaggerConfig.java
new file mode 100644
index 0000000..5f32de3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/SwaggerConfig.java
@@ -0,0 +1,49 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+ /**
+ * 创建一个Docket对象 调用select()方法, 生成ApiSelectorBuilder对象实例,该对象负责定义外漏的API入口
+ * 通过使用RequestHandlerSelectors和PathSelectors来提供Predicate,在此我们使用any()方法,将所有API都通过Swagger进行文档管理
+ *
+ * @return
+ */
+ @Bean
+ public Docket createRestApi() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .apiInfo(apiInfo()).select()
+ //如果不想将所有的接口都通过swagger管理的话,可以将RequestHandlerSelectors.any()修改为RequestHandlerSelectors.basePackage()
+ //.apis(RequestHandlerSelectors.any())
+ .apis(RequestHandlerSelectors.basePackage("com.md"))
+ .paths(PathSelectors.any())
+ .build();
+ }
+
+ @SuppressWarnings("deprecation")
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ // 标题
+ .title("SpringBoot2 中使用Swagger2 构建RESTful APIs")
+ // 简介
+ .description("This a demo for Swagger2")
+ // 服务条款
+ .termsOfServiceUrl("https://blog.csdn.net/hemin1003")
+ // 作者个人信息
+ .contact("Minbo.He")
+ // 版本
+ .version("1.0").build();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..47e232c
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,45 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 解决 swagger-ui.html 404报错
+ registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
+ registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+
+ // 解决 doc.html 404 报错
+ registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
+
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/auto/CodeGenerator.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/auto/CodeGenerator.java
new file mode 100644
index 0000000..d51cccf
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/auto/CodeGenerator.java
@@ -0,0 +1,137 @@
+package com.md.demo.auto;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.InjectionConfig;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.FileOutConfig;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.PackageConfig;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.TemplateConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+
+/**
+ * 代码生成器
+ *
+ * @author Minbo.He
+ *
+ */
+public class CodeGenerator {
+
+ /**
+ * RUN THIS
+ */
+ public static void main(String[] args) {
+ String basePackage = "com.md";
+ String moduleName = "demo";
+
+ AutoGenerator mpg = new AutoGenerator();
+
+ // 全局配置
+ GlobalConfig gc = new GlobalConfig();
+ String projectPath = System.getProperty("user.dir");
+ gc.setOutputDir(projectPath + "/src/main/java");
+ gc.setAuthor(scanner("开发人员"));
+ gc.setOpen(false);
+ gc.setSwagger2(true);
+ // 默认不覆盖,如果文件存在,将不会再生成,配置true就是覆盖
+ gc.setFileOverride(false);
+ mpg.setGlobalConfig(gc);
+
+ // 数据源配置
+ DataSourceConfig dsc = new DataSourceConfig();
+ dsc.setUrl("jdbc:mysql://localhost:3306/testdb?useUnicode=true&useSSL=false&characterEncoding=utf8");
+ dsc.setDriverName("com.mysql.jdbc.Driver");
+ dsc.setUsername("root");
+ dsc.setPassword("123456");
+
+ mpg.setDataSource(dsc);
+
+ // 包配置
+ PackageConfig pc = new PackageConfig();
+ //pc.setModuleName(scanner("模块名"));
+ pc.setModuleName(moduleName);
+ pc.setParent(basePackage).setMapper("dao").setEntity("entity.vo");
+ mpg.setPackageInfo(pc);
+
+ // 自定义配置
+ InjectionConfig cfg = new InjectionConfig() {
+ @Override
+ public void initMap() {
+ // to do nothing
+ }
+ };
+
+ // 如果模板引擎是 freemarker
+ String templatePath = "/templates/mapper.xml.ftl";
+
+ // 自定义输出配置
+ List focList = new ArrayList<>();
+ // 自定义配置会被优先输出
+ focList.add(new FileOutConfig(templatePath) {
+ @Override
+ public String outputFile(TableInfo tableInfo) {
+ // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
+ return projectPath + "/src/main/resources/mapper/" + pc.getModuleName() + "/"
+ + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
+ }
+ });
+
+ cfg.setFileOutConfigList(focList);
+ mpg.setCfg(cfg);
+
+ // 配置模板
+ TemplateConfig templateConfig = new TemplateConfig();
+ templateConfig.setXml(null);
+ mpg.setTemplate(templateConfig);
+
+ // 策略配置
+ StrategyConfig strategy = new StrategyConfig();
+ strategy.setNaming(NamingStrategy.underline_to_camel);
+ strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+
+ strategy.setEntityLombokModel(true);
+ strategy.setRestControllerStyle(true);
+
+ strategy.setInclude(scanner("表名"));
+ strategy.setControllerMappingHyphenStyle(true);
+ strategy.setTablePrefix(pc.getModuleName() + "_");
+
+ mpg.setStrategy(strategy);
+ // 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
+ mpg.setTemplateEngine(new FreemarkerTemplateEngine());
+
+ mpg.execute();
+
+ System.out.println();
+ System.out.println("success");
+ }
+
+ /**
+ *
+ * 读取控制台内容
+ *
+ */
+ @SuppressWarnings("resource")
+ public static String scanner(String tip) {
+ Scanner scanner = new Scanner(System.in);
+ StringBuilder help = new StringBuilder();
+ help.append("请输入" + tip + ":");
+ System.out.println(help.toString());
+ if (scanner.hasNext()) {
+ String ipt = scanner.next();
+ if (StringUtils.isNotEmpty(ipt)) {
+ return ipt;
+ }
+ }
+ throw new MybatisPlusException("请输入正确的" + tip + "!");
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/controller/UsersController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/controller/UsersController.java
new file mode 100644
index 0000000..27abcdc
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/controller/UsersController.java
@@ -0,0 +1,41 @@
+package com.md.demo.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.entity.vo.Users;
+import com.md.demo.service.IUsersService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+
+import io.swagger.annotations.ApiOperation;
+
+/**
+ *
+ * 前端控制器
+ *
+ *
+ * @author Minbo
+ * @since 2020-03-27
+ */
+@RestController
+@RequestMapping("/demo/users")
+public class UsersController {
+
+ @Autowired
+ private IUsersService usersService;
+
+ @ApiOperation(value = "获得用户列表信息", httpMethod = "POST")
+ @PostMapping("/listDbInfo")
+ public JsonResult listDbInfo() {
+ List dataList = this.usersService.listDbInfo();
+ if (dataList == null || dataList.size() == 0) {
+ return new JsonResult(ResultCode.SUCCESS_FAIL);
+ }
+ return new JsonResult(ResultCode.SUCCESS, dataList);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/dao/UsersMapper.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/dao/UsersMapper.java
new file mode 100644
index 0000000..134191d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/dao/UsersMapper.java
@@ -0,0 +1,28 @@
+package com.md.demo.dao;
+
+import com.md.demo.entity.vo.Users;
+
+import java.util.List;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * Mapper 接口
+ *
+ *
+ * @author Minbo
+ * @since 2020-03-27
+ */
+//@DS("slave_1")
+public interface UsersMapper extends BaseMapper {
+
+ // 使用@DS注解,可以切换数据源。如果没有配置@DS,则使用默认数据源(使用配置文件中的primary源)
+ // @DS 可以注解在方法上和类上,同时存在方法注解优先于类上注解
+ // 注解在service实现或mapper接口方法上,但强烈不建议同时在service和mapper注解
+
+// @DS("slave_1")
+// @DS("master")
+ public List listDbInfo();
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/entity/vo/Users.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/entity/vo/Users.java
new file mode 100644
index 0000000..b19402e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/entity/vo/Users.java
@@ -0,0 +1,36 @@
+package com.md.demo.entity.vo;
+
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ *
+ *
+ *
+ *
+ * @author Minbo
+ * @since 2020-03-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Users对象", description="")
+public class Users implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(value = "用户名")
+ private String username;
+
+ @ApiModelProperty(value = "密码")
+ private String password;
+
+ @ApiModelProperty(value = "是否启用")
+ private Boolean enabled;
+
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/service/IUsersService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/service/IUsersService.java
new file mode 100644
index 0000000..11e1e23
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/service/IUsersService.java
@@ -0,0 +1,20 @@
+package com.md.demo.service;
+
+import com.md.demo.entity.vo.Users;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ *
+ * 服务类
+ *
+ *
+ * @author Minbo
+ * @since 2020-03-27
+ */
+public interface IUsersService extends IService {
+
+ public List listDbInfo();
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/service/impl/UsersServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/service/impl/UsersServiceImpl.java
new file mode 100644
index 0000000..f9265b8
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/service/impl/UsersServiceImpl.java
@@ -0,0 +1,31 @@
+package com.md.demo.service.impl;
+
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.md.demo.dao.UsersMapper;
+import com.md.demo.entity.vo.Users;
+import com.md.demo.service.IUsersService;
+
+/**
+ *
+ * 服务实现类
+ *
+ *
+ * @author Minbo
+ * @since 2020-03-27
+ */
+@Service
+//@DS("slave_1")
+public class UsersServiceImpl extends ServiceImpl implements IUsersService {
+
+ @Override
+// @DS("master")
+ public List listDbInfo() {
+ return this.baseMapper.listDbInfo();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/application.yml
new file mode 100644
index 0000000..1b5d2be
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/application.yml
@@ -0,0 +1,18 @@
+spring:
+ datasource:
+ dynamic:
+ primary: master #设置默认的数据源或者数据源组,默认值即为master
+ #如果你只是单数据源,则只需要注释掉slave相关配置就好了,这里为了方便演示master与slave保持相同
+ datasource:
+ master:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://localhost:33061/testdb?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
+ username: root
+ password: 123456
+ slave_1:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://localhost:33062/testdb?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
+ username: root
+ password: 123456
+server:
+ port: 9090
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/mapper/demo/UsersMapper.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/mapper/demo/UsersMapper.xml
new file mode 100644
index 0000000..d3525ec
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource/src/main/resources/mapper/demo/UsersMapper.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/README.md
new file mode 100644
index 0000000..c4955b7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-mybatis-plus
+
+【Mybatis-Plus快速开发框架用法】技术点
+
+功能介绍
+
+1. Mybatis-Plus快速开发框架用法
+
+## 本项目文档教程
+
+[Mybatis-Plus快速开发框架用法](https://hemin.blog.csdn.net/article/details/99637913)
+
+## 该系列教程
+
+[SpringBoot系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/db.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/db.sql
new file mode 100644
index 0000000..7b784f2
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/db.sql
@@ -0,0 +1,15 @@
+drop table myuser;
+
+CREATE TABLE `myuser` (
+ `id` bigint(20) NOT NULL COMMENT '主键ID',
+ `name` varchar(30) DEFAULT NULL COMMENT '姓名',
+ `age` int(11) DEFAULT NULL COMMENT '年龄',
+ `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+
+INSERT INTO `myuser` (`id`, `name`, `age`, `email`)
+VALUES
+ (1, 'Minbo', 18, 'test1@163.com'),
+ (2, 'Hemin', 20, 'test2@163.com');
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/log/run.log b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/log/run.log
new file mode 100644
index 0000000..50104f3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/log/run.log
@@ -0,0 +1,38 @@
+2019-10-25 01:11:50,099 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:50)- Starting Application on MInboHes-MacBook-Pro.local with PID 20223 (/Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/target/classes started by Minbo in /Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+2019-10-25 01:11:50,115 [main] [com.md.demo.Application] [DEBUG] (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
+2019-10-25 01:11:50,119 [main] [com.md.demo.Application] [INFO] (SpringApplication.java:654)- No active profile set, falling back to default profiles: default
+2019-10-25 01:12:14,965 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:50)- Starting Application on MInboHes-MacBook-Pro.local with PID 20228 (/Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/target/classes started by Minbo in /Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+2019-10-25 01:12:14,968 [main] [com.md.demo.Application] [DEBUG] (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
+2019-10-25 01:12:14,971 [main] [com.md.demo.Application] [INFO] (SpringApplication.java:654)- No active profile set, falling back to default profiles: default
+2019-10-25 01:12:37,931 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:50)- Starting Application on MInboHes-MacBook-Pro.local with PID 20230 (/Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/target/classes started by Minbo in /Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+2019-10-25 01:12:37,934 [main] [com.md.demo.Application] [DEBUG] (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
+2019-10-25 01:12:37,936 [main] [com.md.demo.Application] [INFO] (SpringApplication.java:654)- No active profile set, falling back to default profiles: default
+2019-10-25 01:12:41,259 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:59)- Started Application in 3.632 seconds (JVM running for 4.078)
+2019-10-25 01:12:44,168 [http-nio-9090-exec-1] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/doc.html, method: GET, params: null
+2019-10-25 01:12:44,343 [http-nio-9090-exec-3] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/swagger-resources, method: GET, params: null
+2019-10-25 01:12:44,350 [http-nio-9090-exec-2] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/webjars/bycdao-ui/images/api.ico, method: GET, params: null
+2019-10-25 01:12:44,402 [http-nio-9090-exec-4] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/v2/api-docs-ext, method: GET, params: group=default
+2019-10-25 01:12:56,580 [http-nio-9090-exec-6] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/webjars/bycdao-ui/ace-editor/theme-eclipse.js, method: GET, params: null
+2019-10-25 01:12:56,580 [http-nio-9090-exec-5] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/webjars/bycdao-ui/ace-editor/mode-json.js, method: GET, params: null
+2019-10-25 01:12:56,699 [http-nio-9090-exec-7] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/webjars/bycdao-ui/layui/font/iconfont.woff, method: GET, params: v=240
+2019-10-25 01:12:56,720 [http-nio-9090-exec-8] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/webjars/bycdao-ui/ace-editor/worker-json.js, method: GET, params: null
+2019-10-25 01:12:59,603 [http-nio-9090-exec-9] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/webjars/bycdao-ui/layer3.0.3/skin/default/loading-1.gif, method: GET, params: null
+2019-10-25 01:12:59,606 [http-nio-9090-exec-10] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/test/myuser/listUser, method: GET, params: null
+2019-10-25 01:12:59,946 [http-nio-9090-exec-10] [com.md.demo.test.dao.MyuserMapper.selectList] [DEBUG] (BaseJdbcLogger.java:143)- ==> Preparing: SELECT id,name,email,age FROM myuser
+2019-10-25 01:12:59,965 [http-nio-9090-exec-10] [com.md.demo.test.dao.MyuserMapper.selectList] [DEBUG] (BaseJdbcLogger.java:143)- ==> Parameters:
+2019-10-25 01:12:59,984 [http-nio-9090-exec-10] [com.md.demo.test.dao.MyuserMapper.selectList] [DEBUG] (BaseJdbcLogger.java:143)- <== Total: 2
+2019-10-25 01:19:04,491 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:50)- Starting Application on MInboHes-MacBook-Pro.local with PID 20289 (/Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/target/classes started by Minbo in /Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+2019-10-25 01:19:04,497 [main] [com.md.demo.Application] [DEBUG] (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
+2019-10-25 01:19:04,531 [main] [com.md.demo.Application] [INFO] (SpringApplication.java:654)- No active profile set, falling back to default profiles: default
+2019-10-25 01:19:09,222 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:59)- Started Application in 5.394 seconds (JVM running for 6.265)
+2019-10-25 01:19:12,864 [http-nio-9090-exec-1] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/doc.html, method: GET, params: null
+2019-10-25 01:19:13,066 [http-nio-9090-exec-2] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/swagger-resources, method: GET, params: null
+2019-10-25 01:19:13,141 [http-nio-9090-exec-3] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/v2/api-docs-ext, method: GET, params: group=default
+2019-10-25 01:19:13,333 [http-nio-9090-exec-4] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/webjars/bycdao-ui/images/api.ico, method: GET, params: null
+2019-10-25 01:19:21,169 [http-nio-9090-exec-5] [com.md.demo.MyHttpInterceptor] [INFO] (MyHttpInterceptor.java:38)- 请求参数, url: http://localhost:9090/test/myuser/getUserByName, method: GET, params: name=minbo
+2019-10-25 01:19:21,592 [http-nio-9090-exec-5] [com.md.demo.test.dao.MyuserMapper.getUserByName] [DEBUG] (BaseJdbcLogger.java:143)- ==> Preparing: select * from myuser where name = ?
+2019-10-25 01:19:21,616 [http-nio-9090-exec-5] [com.md.demo.test.dao.MyuserMapper.getUserByName] [DEBUG] (BaseJdbcLogger.java:143)- ==> Parameters: minbo(String)
+2019-10-25 01:19:21,640 [http-nio-9090-exec-5] [com.md.demo.test.dao.MyuserMapper.getUserByName] [DEBUG] (BaseJdbcLogger.java:143)- <== Total: 1
+2019-10-25 01:22:00,961 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:50)- Starting Application on MInboHes-MacBook-Pro.local with PID 20324 (/Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/target/classes started by Minbo in /Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+2019-10-25 01:22:00,964 [main] [com.md.demo.Application] [DEBUG] (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
+2019-10-25 01:22:00,965 [main] [com.md.demo.Application] [INFO] (SpringApplication.java:654)- No active profile set, falling back to default profiles: default
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/log/run.log.2019-10-21.0 b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/log/run.log.2019-10-21.0
new file mode 100644
index 0000000..7a28ce9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/log/run.log.2019-10-21.0
@@ -0,0 +1,3 @@
+2019-10-21 16:40:25,871 [main] [com.md.demo.Application] [INFO] (StartupInfoLogger.java:50)- Starting Application on MInboHes-MacBook-Pro.local with PID 9410 (/Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/target/classes started by Minbo in /Users/Minbo/Documents/IT/java/code/spring-boot-study/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus)
+2019-10-21 16:40:25,877 [main] [com.md.demo.Application] [DEBUG] (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.6.RELEASE, Spring v5.0.10.RELEASE
+2019-10-21 16:40:25,880 [main] [com.md.demo.Application] [INFO] (SpringApplication.java:654)- No active profile set, falling back to default profiles: default
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/pom.xml
new file mode 100644
index 0000000..385547e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/pom.xml
@@ -0,0 +1,102 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-mybatis-plus
+ jar
+
+ spring-boot2-mybatis-plus
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+ 2.9.2
+ 3.2.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ mysql
+ mysql-connector-java
+
+
+ org.projectlombok
+ lombok
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ junit
+ junit
+
+
+
+ io.springfox
+ springfox-swagger2
+ ${swagger.version}
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${swagger.version}
+
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ 1.9.3
+
+
+
+ com.baomidou
+ mybatis-plus-generator
+ ${mybatisplus.version}
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatisplus.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-freemarker
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..34e6e0f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,52 @@
+package com.md.demo;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+@EnableSwaggerBootstrapUI
+@MapperScan("com.md.demo.test.dao")
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/SwaggerConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/SwaggerConfig.java
new file mode 100644
index 0000000..5f32de3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/SwaggerConfig.java
@@ -0,0 +1,49 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+ /**
+ * 创建一个Docket对象 调用select()方法, 生成ApiSelectorBuilder对象实例,该对象负责定义外漏的API入口
+ * 通过使用RequestHandlerSelectors和PathSelectors来提供Predicate,在此我们使用any()方法,将所有API都通过Swagger进行文档管理
+ *
+ * @return
+ */
+ @Bean
+ public Docket createRestApi() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .apiInfo(apiInfo()).select()
+ //如果不想将所有的接口都通过swagger管理的话,可以将RequestHandlerSelectors.any()修改为RequestHandlerSelectors.basePackage()
+ //.apis(RequestHandlerSelectors.any())
+ .apis(RequestHandlerSelectors.basePackage("com.md"))
+ .paths(PathSelectors.any())
+ .build();
+ }
+
+ @SuppressWarnings("deprecation")
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ // 标题
+ .title("SpringBoot2 中使用Swagger2 构建RESTful APIs")
+ // 简介
+ .description("This a demo for Swagger2")
+ // 服务条款
+ .termsOfServiceUrl("https://blog.csdn.net/hemin1003")
+ // 作者个人信息
+ .contact("Minbo.He")
+ // 版本
+ .version("1.0").build();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..47e232c
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,45 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 解决 swagger-ui.html 404报错
+ registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
+ registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+
+ // 解决 doc.html 404 报错
+ registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
+
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/auto/CodeGenerator.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/auto/CodeGenerator.java
new file mode 100644
index 0000000..830e871
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/auto/CodeGenerator.java
@@ -0,0 +1,133 @@
+package com.md.demo.auto;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.InjectionConfig;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.FileOutConfig;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.PackageConfig;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.TemplateConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+
+/**
+ * 代码生成器
+ *
+ * @author Minbo
+ *
+ */
+public class CodeGenerator {
+
+ /**
+ * RUN THIS
+ */
+ public static void main(String[] args) {
+ AutoGenerator mpg = new AutoGenerator();
+
+ // 全局配置
+ GlobalConfig gc = new GlobalConfig();
+ String projectPath = System.getProperty("user.dir");
+ gc.setOutputDir(projectPath + "/src/main/java");
+ gc.setAuthor(scanner("开发者"));
+ gc.setOpen(false);
+ // 是否启动Swagger2
+ gc.setSwagger2(true);
+ // 默认不覆盖,如果文件存在,将不会再生成,配置true就是覆盖
+ gc.setFileOverride(true);
+ mpg.setGlobalConfig(gc);
+
+ // 数据源配置
+ DataSourceConfig dsc = new DataSourceConfig();
+ dsc.setUrl("jdbc:mysql://localhost:33061/test?useUnicode=true&useSSL=false&characterEncoding=utf8");
+ dsc.setDriverName("com.mysql.jdbc.Driver");
+ dsc.setUsername("root");
+ dsc.setPassword("hs2019");
+ mpg.setDataSource(dsc);
+
+ // 包配置
+ PackageConfig pc = new PackageConfig();
+ pc.setModuleName(scanner("模块名"));
+ pc.setParent("com.md.demo").setEntity("entity.vo").setMapper("dao");
+ mpg.setPackageInfo(pc);
+
+ // 自定义配置
+ InjectionConfig cfg = new InjectionConfig() {
+ @Override
+ public void initMap() {
+ // to do nothing
+ }
+ };
+
+ // 如果模板引擎是 freemarker
+ String templatePath = "/templates/mapper.xml.ftl";
+
+ // 自定义输出配置
+ List focList = new ArrayList<>();
+ // 自定义配置会被优先输出
+ focList.add(new FileOutConfig(templatePath) {
+ @Override
+ public String outputFile(TableInfo tableInfo) {
+ // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
+ return projectPath + "/src/main/resources/mapper/" + pc.getModuleName() + "/"
+ + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
+ }
+ });
+
+ cfg.setFileOutConfigList(focList);
+ mpg.setCfg(cfg);
+
+ // 配置模板
+ TemplateConfig templateConfig = new TemplateConfig();
+ templateConfig.setXml(null);
+ mpg.setTemplate(templateConfig);
+
+ // 策略配置
+ StrategyConfig strategy = new StrategyConfig();
+ strategy.setNaming(NamingStrategy.underline_to_camel);
+ strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+
+ strategy.setEntityLombokModel(true);
+ strategy.setRestControllerStyle(true);
+
+ strategy.setInclude(scanner("表名"));
+ strategy.setControllerMappingHyphenStyle(true);
+ strategy.setTablePrefix(pc.getModuleName() + "_");
+
+ mpg.setStrategy(strategy);
+ // 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
+ mpg.setTemplateEngine(new FreemarkerTemplateEngine());
+
+ mpg.execute();
+
+ System.out.println("success");
+ }
+
+ /**
+ *
+ * 读取控制台内容
+ *
+ */
+ @SuppressWarnings("resource")
+ public static String scanner(String tip) {
+ Scanner scanner = new Scanner(System.in);
+ StringBuilder help = new StringBuilder();
+ help.append("请输入" + tip + ":");
+ System.out.println(help.toString());
+ if (scanner.hasNext()) {
+ String ipt = scanner.next();
+ if (StringUtils.isNotEmpty(ipt)) {
+ return ipt;
+ }
+ }
+ throw new MybatisPlusException("请输入正确的" + tip + "!");
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/controller/MyuserController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/controller/MyuserController.java
new file mode 100644
index 0000000..aa1f238
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/controller/MyuserController.java
@@ -0,0 +1,48 @@
+package com.md.demo.test.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.test.entity.vo.Myuser;
+import com.md.demo.test.service.IMyuserService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ *
+ * 前端控制器
+ *
+ *
+ * @author MMinbo
+ * @since 2019-10-25
+ */
+@RestController
+@RequestMapping("/test/myuser")
+public class MyuserController {
+
+ @Autowired
+ private IMyuserService myuserService;
+
+ @ApiOperation(value = "获得用户列表", notes = "", httpMethod = "GET")
+ @RequestMapping(value = "/listUser")
+ public JsonResult listUser() {
+ // 框架自带的方法
+ List list = this.myuserService.list(null);
+ return new JsonResult(ResultCode.SUCCESS, list);
+ }
+
+ @ApiOperation(value = "根据用户名获得用户记录", notes = "名称不能为空", httpMethod = "GET")
+ @ApiImplicitParam(dataType = "string", name = "name", value = "用户名", required = true)
+ @RequestMapping(value = "/getUserByName")
+ public JsonResult getUserByName(String name) {
+ // 自定义的方法
+ Myuser myuser = this.myuserService.getUserByName(name);
+ return new JsonResult(ResultCode.SUCCESS, myuser);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/dao/MyuserMapper.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/dao/MyuserMapper.java
new file mode 100644
index 0000000..a068f5c
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/dao/MyuserMapper.java
@@ -0,0 +1,17 @@
+package com.md.demo.test.dao;
+
+import com.md.demo.test.entity.vo.Myuser;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * Mapper 接口
+ *
+ *
+ * @author MMinbo
+ * @since 2019-10-25
+ */
+public interface MyuserMapper extends BaseMapper {
+ // 方法名自动对应
+ public Myuser getUserByName(String name);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/entity/vo/Myuser.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/entity/vo/Myuser.java
new file mode 100644
index 0000000..0e32fe4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/entity/vo/Myuser.java
@@ -0,0 +1,39 @@
+package com.md.demo.test.entity.vo;
+
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ *
+ *
+ *
+ *
+ * @author MMinbo
+ * @since 2019-10-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Myuser对象", description="")
+public class Myuser implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(value = "主键ID")
+ private Long id;
+
+ @ApiModelProperty(value = "姓名")
+ private String name;
+
+ @ApiModelProperty(value = "年龄")
+ private Integer age;
+
+ @ApiModelProperty(value = "邮箱")
+ private String email;
+
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/service/IMyuserService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/service/IMyuserService.java
new file mode 100644
index 0000000..f1d2a93
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/service/IMyuserService.java
@@ -0,0 +1,16 @@
+package com.md.demo.test.service;
+
+import com.md.demo.test.entity.vo.Myuser;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ *
+ * 服务类
+ *
+ *
+ * @author MMinbo
+ * @since 2019-10-25
+ */
+public interface IMyuserService extends IService {
+ public Myuser getUserByName(String name);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/service/impl/MyuserServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/service/impl/MyuserServiceImpl.java
new file mode 100644
index 0000000..7d31572
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/test/service/impl/MyuserServiceImpl.java
@@ -0,0 +1,25 @@
+package com.md.demo.test.service.impl;
+
+import com.md.demo.test.entity.vo.Myuser;
+import com.md.demo.test.dao.MyuserMapper;
+import com.md.demo.test.service.IMyuserService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * 服务实现类
+ *
+ *
+ * @author MMinbo
+ * @since 2019-10-25
+ */
+@Service
+public class MyuserServiceImpl extends ServiceImpl implements IMyuserService {
+
+ @Override
+ public Myuser getUserByName(String name) {
+ return this.baseMapper.getUserByName(name);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/application.yml
new file mode 100644
index 0000000..8c5e46e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/application.yml
@@ -0,0 +1,11 @@
+spring:
+ datasource:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://localhost:33061/test?useUnicode=true&autoReconnect=true&allowMultiQueries=true&useSSL=false
+ username: root
+ password: hs2019
+server:
+ port: 9090
+mybatis-plus:
+ # 扫描 mapper.xml
+ mapper-locations: classpath:/mapper/**/*Mapper.xml
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/mapper/test/MyuserMapper.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/mapper/test/MyuserMapper.xml
new file mode 100644
index 0000000..220f4cc
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus/src/main/resources/mapper/test/MyuserMapper.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/README.md
new file mode 100644
index 0000000..5608f42
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/README.md
@@ -0,0 +1,35 @@
+# spring-boot2-mysql-druid
+
+【Druid连接池集成】技术点
+
+功能介绍
+
+1. Druid连接池集成
+2. Druid Web界面用法
+
+## 本项目教程
+
+[Druid连接池集成](https://hemin.blog.csdn.net/article/details/99637453)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/init.sql
new file mode 100644
index 0000000..d9fb70f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/init.sql
@@ -0,0 +1,14 @@
+drop table city;
+
+CREATE TABLE `city` (
+ `id` int(11) NOT NULL primary key,
+ `name` varchar(32) DEFAULT NULL,
+ `state` varchar(32) DEFAULT NULL,
+ `country` varchar(32) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `city` (`id`, `name`, `state`, `country`)
+VALUES
+ (1, '广州16', 'GZ16', 'CH16'),
+ (2, '北京17', 'BJ17', 'CH17'),
+ (3, '深圳18', 'SZ18', 'CH18');
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/pom.xml
new file mode 100644
index 0000000..2b6cab8
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-mysql-druid
+ jar
+
+ spring-boot2-mysql-druid
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/bo/City.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/bo/City.java
new file mode 100644
index 0000000..294902e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/bo/City.java
@@ -0,0 +1,53 @@
+package com.md.demo.bo;
+
+import java.io.Serializable;
+
+public class City implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private Long id;
+
+ private String name;
+
+ private String state;
+
+ private String country;
+
+ public Long getId() {
+ return this.id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getState() {
+ return this.state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCountry() {
+ return this.country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ @Override
+ public String toString() {
+ return getId() + "," + getName() + "," + getState() + "," + getCountry();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/dao/CityDao.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/dao/CityDao.java
new file mode 100644
index 0000000..65f92b4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/dao/CityDao.java
@@ -0,0 +1,13 @@
+package com.md.demo.dao;
+
+import java.util.List;
+
+import com.md.demo.vo.CityVo;
+
+public interface CityDao {
+
+ public List listCities();
+
+ public CityVo getCityById(Long id);
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
new file mode 100644
index 0000000..a1bfecf
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
@@ -0,0 +1,28 @@
+package com.md.demo.dao.impl;
+
+import java.util.List;
+
+import org.mybatis.spring.SqlSessionTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.vo.CityVo;
+
+@Component
+public class CityDaoImpl implements CityDao {
+
+ @Autowired
+ public SqlSessionTemplate sqlSessionTemplate;
+
+ @Override
+ public List listCities() {
+ return this.sqlSessionTemplate.selectList("listCities");
+ }
+
+ @Override
+ public CityVo getCityById(Long id) {
+ return this.sqlSessionTemplate.selectOne("getCityById", id);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..3270ac9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,58 @@
+package com.md.demo.rest;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.service.CityService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+import com.md.demo.vo.CityVo;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ @Autowired
+ private CityService cityService;
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-mysql-druid";
+ }
+
+ /**
+ * http://localhost:9090/listCities
+ *
+ * @return
+ */
+ @GetMapping("/listCities")
+ public JsonResult listCities() {
+ List list = this.cityService.listCities();
+ return new JsonResult(ResultCode.SUCCESS, list);
+ }
+
+ /**
+ * http://localhost:9090/getCityById?id=1
+ *
+ * @return
+ */
+ @GetMapping("/getCityById")
+ public JsonResult listCities(Long id) {
+ CityVo obj = this.cityService.getCityById(id);
+ return new JsonResult(ResultCode.SUCCESS, obj);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/service/CityService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/service/CityService.java
new file mode 100644
index 0000000..391199f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/service/CityService.java
@@ -0,0 +1,11 @@
+package com.md.demo.service;
+
+import java.util.List;
+import com.md.demo.vo.CityVo;
+
+public interface CityService {
+
+ public List listCities();
+
+ public CityVo getCityById(Long id);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/service/impl/CityServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
new file mode 100644
index 0000000..f3cf11b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
@@ -0,0 +1,34 @@
+package com.md.demo.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.service.CityService;
+import com.md.demo.vo.CityVo;
+
+@Service
+public class CityServiceImpl implements CityService {
+
+ @Autowired
+ private CityDao cityDao;
+
+ /**
+ * 获得城市列表
+ */
+ @Override
+ public List listCities() {
+ return this.cityDao.listCities();
+ }
+
+ /**
+ * 根据id,获得某个城市
+ */
+ @Override
+ public CityVo getCityById(Long id) {
+ return this.cityDao.getCityById(id);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/vo/CityVo.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/vo/CityVo.java
new file mode 100644
index 0000000..56fc798
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/java/com/md/demo/vo/CityVo.java
@@ -0,0 +1,9 @@
+package com.md.demo.vo;
+
+import com.md.demo.bo.City;
+
+public class CityVo extends City {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/application.yml
new file mode 100644
index 0000000..2af76f5
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/application.yml
@@ -0,0 +1,28 @@
+spring:
+ datasource:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/cfdb?useUnicode=true&autoReconnect=true&allowMultiQueries=true&useSSL=false
+ username: root
+ password: a123456
+ # 使用alibaba的druid连接池、监控
+ type: com.alibaba.druid.pool.DruidDataSource
+ druid:
+ max-active: 10
+ max-wait: 5000
+ min-idle: 5
+ initial-size: 2
+ validation-query: SELECT 1
+ test-on-borrow: false
+ test-while-idle: true
+ time-between-eviction-runs-millis: 18800
+ web-stat-filter:
+ enabled: true
+ exclusions: js,gif,jpg,png,css,ico,/druid/*
+ stat-view-servlet:
+ enabled: true
+ login-username: druid
+ login-password: druid@2019
+server:
+ port: 9090
+mybatis:
+ config-location: classpath:mybatis-config.xml
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/logback.xml
new file mode 100644
index 0000000..8561ff9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/mybatis-config.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/mybatis-config.xml
new file mode 100644
index 0000000..dbc7d97
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/mybatis-config.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/mybatis/mapper/CityMapper.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/mybatis/mapper/CityMapper.xml
new file mode 100644
index 0000000..135cecd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-druid/src/main/resources/mybatis/mapper/CityMapper.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/README.md
new file mode 100644
index 0000000..dc2c11e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/README.md
@@ -0,0 +1,40 @@
+# spring-boot2-mysql-multi-datasource
+
+【Mysql多数据源和Hikari用法详解】技术点
+
+功能介绍
+
+1. Mysql多数据源配置用法
+2. Hikari用法
+
+## 本项目教程
+
+[Mysql多数据源和Hikari用法详解](https://hemin.blog.csdn.net/article/details/94194400)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 官方资料
+
+[SpringBoot配置多数据源](https://docs.spring.io/spring-boot/docs/2.0.9.RELEASE/reference/htmlsingle/#howto-two-datasources)
+
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/db1-init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/db1-init.sql
new file mode 100644
index 0000000..2d9bc2b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/db1-init.sql
@@ -0,0 +1,16 @@
+-- for db1
+
+drop table city1;
+
+CREATE TABLE `city1` (
+ `id` int(11) NOT NULL primary key,
+ `name` varchar(32) DEFAULT NULL,
+ `state` varchar(32) DEFAULT NULL,
+ `country` varchar(32) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `city1` (`id`, `name`, `state`, `country`)
+VALUES
+ (1, '广州1', 'GZ1', 'CH1'),
+ (2, '北京1', 'BJ1', 'CH1'),
+ (3, '深圳1', 'SZ1', 'CH1');
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/db2-init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/db2-init.sql
new file mode 100644
index 0000000..710db2b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/db2-init.sql
@@ -0,0 +1,16 @@
+-- for db2
+
+drop table city2;
+
+CREATE TABLE `city2` (
+ `id` int(11) NOT NULL primary key,
+ `name` varchar(32) DEFAULT NULL,
+ `state` varchar(32) DEFAULT NULL,
+ `country` varchar(32) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `city2` (`id`, `name`, `state`, `country`)
+VALUES
+ (1, '广州2', 'GZ2', 'CH2'),
+ (2, '北京2', 'BJ2', 'CH2'),
+ (3, '深圳2', 'SZ2', 'CH2');
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/pom.xml
new file mode 100644
index 0000000..ea4dcc9
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-mysql-multi-datasource
+ jar
+
+ spring-boot2-mysql-multi-datasource
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/bo/City.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/bo/City.java
new file mode 100644
index 0000000..294902e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/bo/City.java
@@ -0,0 +1,53 @@
+package com.md.demo.bo;
+
+import java.io.Serializable;
+
+public class City implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private Long id;
+
+ private String name;
+
+ private String state;
+
+ private String country;
+
+ public Long getId() {
+ return this.id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getState() {
+ return this.state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCountry() {
+ return this.country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ @Override
+ public String toString() {
+ return getId() + "," + getName() + "," + getState() + "," + getCountry();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/CityDao.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/CityDao.java
new file mode 100644
index 0000000..cb1626f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/CityDao.java
@@ -0,0 +1,13 @@
+package com.md.demo.dao;
+
+import java.util.List;
+
+import com.md.demo.vo.CityVo;
+
+public interface CityDao {
+
+ public List listCities111();
+
+ public List listCities222();
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/BaseDao.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/BaseDao.java
new file mode 100644
index 0000000..6cbbdec
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/BaseDao.java
@@ -0,0 +1,23 @@
+package com.md.demo.dao.base;
+
+import javax.annotation.Resource;
+
+import org.mybatis.spring.SqlSessionTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public abstract class BaseDao {
+
+ /**
+ * 默认库-主库
+ */
+ @Resource(name = "masterSessionTemplate")
+ @Autowired
+ public SqlSessionTemplate sqlSessionTemplateOfMaster;
+
+ /**
+ * 灾备库-用作读库
+ */
+ @Resource(name = "slaveSessionTemplate")
+ @Autowired
+ public SqlSessionTemplate sqlSessionTemplateOfSlave;
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/DataSourceConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/DataSourceConfig.java
new file mode 100644
index 0000000..876944f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/DataSourceConfig.java
@@ -0,0 +1,29 @@
+package com.md.demo.dao.base.datasource;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+@Configuration
+public class DataSourceConfig {
+
+ @Primary
+ @Qualifier("master")
+ @Bean(name = "master")
+ @ConfigurationProperties(prefix = "spring.datasource.master") // application.yml中对应属性的前缀
+ public DataSource masterDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+
+ @Qualifier("slave")
+ @Bean(name = "slave")
+ @ConfigurationProperties(prefix = "spring.datasource.slave") // application.yml中对应属性的前缀
+ public DataSource slaveDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/MybatisDbAConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/MybatisDbAConfig.java
new file mode 100644
index 0000000..35c4b86
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/MybatisDbAConfig.java
@@ -0,0 +1,38 @@
+package com.md.demo.dao.base.datasource;
+
+import javax.sql.DataSource;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+@Configuration
+@MapperScan(basePackages = {"mybatis.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory1")
+public class MybatisDbAConfig {
+
+ private String localMapper = "classpath:mybatis/mapper/*.xml";
+
+ @Autowired
+ @Qualifier("master")
+ private DataSource ds1;
+
+ @Bean
+ public SqlSessionFactory sqlSessionFactory1() throws Exception {
+ SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
+ factoryBean.setDataSource(ds1); // 使用master数据源, 连接master库
+ factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(localMapper));
+ return factoryBean.getObject();
+ }
+
+ @Bean(name = "masterSessionTemplate")
+ public SqlSessionTemplate sqlSessionTemplate1() throws Exception {
+ SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory1()); // 使用上面配置的Factory
+ return template;
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/MybatisDbBConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/MybatisDbBConfig.java
new file mode 100644
index 0000000..aff4a34
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/base/datasource/MybatisDbBConfig.java
@@ -0,0 +1,38 @@
+package com.md.demo.dao.base.datasource;
+
+import javax.sql.DataSource;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+@Configuration
+@MapperScan(basePackages = { "mybatis.mapper" }, sqlSessionFactoryRef = "sqlSessionFactory2")
+public class MybatisDbBConfig {
+
+ private String localMapper = "classpath:mybatis/mapper/*.xml";
+
+ @Autowired
+ @Qualifier("slave")
+ private DataSource ds2;
+
+ @Bean
+ public SqlSessionFactory sqlSessionFactory2() throws Exception {
+ SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
+ factoryBean.setDataSource(ds2);
+ factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(localMapper));
+ return factoryBean.getObject();
+ }
+
+ @Bean(name = "slaveSessionTemplate")
+ public SqlSessionTemplate sqlSessionTemplate2() throws Exception {
+ SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory2());
+ return template;
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
new file mode 100644
index 0000000..495599d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
@@ -0,0 +1,24 @@
+package com.md.demo.dao.impl;
+
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.dao.base.BaseDao;
+import com.md.demo.vo.CityVo;
+
+@Component
+public class CityDaoImpl extends BaseDao implements CityDao {
+
+ @Override
+ public List listCities111() {
+ return this.sqlSessionTemplateOfMaster.selectList("listCities111");
+ }
+
+ @Override
+ public List listCities222() {
+ return this.sqlSessionTemplateOfSlave.selectList("listCities222");
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..bf5ea67
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,58 @@
+package com.md.demo.rest;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.service.CityService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+import com.md.demo.vo.CityVo;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ @Autowired
+ private CityService cityService;
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-mysql-multi-datasource";
+ }
+
+ /**
+ * http://localhost:9090/listCities111
+ *
+ * @return
+ */
+ @GetMapping("/listCities111")
+ public JsonResult listCities111() {
+ List list = this.cityService.listCities111();
+ return new JsonResult(ResultCode.SUCCESS, list);
+ }
+
+ /**
+ * http://localhost:9090/listCities222
+ *
+ * @return
+ */
+ @GetMapping("/listCities222")
+ public JsonResult listCities222() {
+ List list = this.cityService.listCities222();
+ return new JsonResult(ResultCode.SUCCESS, list);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/service/CityService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/service/CityService.java
new file mode 100644
index 0000000..8ec0b13
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/service/CityService.java
@@ -0,0 +1,11 @@
+package com.md.demo.service;
+
+import java.util.List;
+import com.md.demo.vo.CityVo;
+
+public interface CityService {
+
+ public List listCities111();
+
+ public List listCities222();
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/service/impl/CityServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
new file mode 100644
index 0000000..3043e24
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
@@ -0,0 +1,34 @@
+package com.md.demo.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.service.CityService;
+import com.md.demo.vo.CityVo;
+
+@Service
+public class CityServiceImpl implements CityService {
+
+ @Autowired
+ private CityDao cityDao;
+
+ /**
+ * 获得城市1列表
+ */
+ @Override
+ public List listCities111() {
+ return this.cityDao.listCities111();
+ }
+
+ /**
+ * 获得城市2列表
+ */
+ @Override
+ public List listCities222() {
+ return this.cityDao.listCities222();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/vo/CityVo.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/vo/CityVo.java
new file mode 100644
index 0000000..56fc798
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/java/com/md/demo/vo/CityVo.java
@@ -0,0 +1,9 @@
+package com.md.demo.vo;
+
+import com.md.demo.bo.City;
+
+public class CityVo extends City {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/application.yml
new file mode 100644
index 0000000..e114bbf
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/application.yml
@@ -0,0 +1,34 @@
+spring:
+ datasource:
+ master:
+ jdbc-url: jdbc:mysql://192.168.1.1:33061/cfdb?useUnicode=true&autoReconnect=true&allowMultiQueries=true&useSSL=false
+ username: root
+ password: 123456
+ driver-class-name: com.mysql.jdbc.Driver
+ # 使用默认hikari连接池
+ type: com.zaxxer.hikari.HikariDataSource
+ minimum-idle: 5
+ maximum-pool-size: 15
+ pool-name: MyHikariCPOfMaster
+ max-lifetime: 1800000
+ connection-timeout: 20000
+ connection-test-query: SELECT 1
+ validation-timeout: 5000
+ slave:
+ jdbc-url: jdbc:mysql://192.168.1.1:33062/cfdb?useUnicode=true&autoReconnect=true&allowMultiQueries=true&useSSL=false
+ username: root
+ password: 123456
+ driver-class-name: com.mysql.jdbc.Driver
+ # 使用默认hikari连接池
+ type: com.zaxxer.hikari.HikariDataSource
+ minimum-idle: 5
+ maximum-pool-size: 15
+ pool-name: MyHikariCPOfSlave
+ max-lifetime: 1800000
+ connection-timeout: 20000
+ connection-test-query: SELECT 1
+ validation-timeout: 5000
+server:
+ port: 9090
+mybatis:
+ config-location: classpath:mybatis-config.xml
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/logback.xml
new file mode 100644
index 0000000..0adec0a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/mybatis-config.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/mybatis-config.xml
new file mode 100644
index 0000000..0a0a16d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/mybatis-config.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/mybatis/mapper/CityMapper.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/mybatis/mapper/CityMapper.xml
new file mode 100644
index 0000000..57431e1
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-multi-datasource/src/main/resources/mybatis/mapper/CityMapper.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/README.md
new file mode 100644
index 0000000..8423499
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/README.md
@@ -0,0 +1,40 @@
+# spring-boot2-mysql-mybatis-xml
+
+【Mysql和Mybatis+XML用法详解】技术点
+
+功能介绍
+
+1. Mysql+Datasource集成
+2. Mybatis+XML用法详解
+
+## 本项目教程
+
+[Mysql和Mybatis+XML用法详解](https://hemin.blog.csdn.net/article/details/93123524)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 官方资料
+
+[SpringBoot2配置mysql+datasource](https://docs.spring.io/spring-boot/docs/2.0.9.RELEASE/reference/htmlsingle/#howto-use-yaml-for-external-properties)
+
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/init.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/init.sql
new file mode 100644
index 0000000..d9fb70f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/init.sql
@@ -0,0 +1,14 @@
+drop table city;
+
+CREATE TABLE `city` (
+ `id` int(11) NOT NULL primary key,
+ `name` varchar(32) DEFAULT NULL,
+ `state` varchar(32) DEFAULT NULL,
+ `country` varchar(32) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `city` (`id`, `name`, `state`, `country`)
+VALUES
+ (1, '广州16', 'GZ16', 'CH16'),
+ (2, '北京17', 'BJ17', 'CH17'),
+ (3, '深圳18', 'SZ18', 'CH18');
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/pom.xml
new file mode 100644
index 0000000..ad7071d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-mysql-mybatis-xml
+ jar
+
+ spring-boot2-mysql-mybatis-xml
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/bo/City.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/bo/City.java
new file mode 100644
index 0000000..294902e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/bo/City.java
@@ -0,0 +1,53 @@
+package com.md.demo.bo;
+
+import java.io.Serializable;
+
+public class City implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private Long id;
+
+ private String name;
+
+ private String state;
+
+ private String country;
+
+ public Long getId() {
+ return this.id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getState() {
+ return this.state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCountry() {
+ return this.country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ @Override
+ public String toString() {
+ return getId() + "," + getName() + "," + getState() + "," + getCountry();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/dao/CityDao.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/dao/CityDao.java
new file mode 100644
index 0000000..65f92b4
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/dao/CityDao.java
@@ -0,0 +1,13 @@
+package com.md.demo.dao;
+
+import java.util.List;
+
+import com.md.demo.vo.CityVo;
+
+public interface CityDao {
+
+ public List listCities();
+
+ public CityVo getCityById(Long id);
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
new file mode 100644
index 0000000..a1bfecf
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/dao/impl/CityDaoImpl.java
@@ -0,0 +1,28 @@
+package com.md.demo.dao.impl;
+
+import java.util.List;
+
+import org.mybatis.spring.SqlSessionTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.vo.CityVo;
+
+@Component
+public class CityDaoImpl implements CityDao {
+
+ @Autowired
+ public SqlSessionTemplate sqlSessionTemplate;
+
+ @Override
+ public List listCities() {
+ return this.sqlSessionTemplate.selectList("listCities");
+ }
+
+ @Override
+ public CityVo getCityById(Long id) {
+ return this.sqlSessionTemplate.selectOne("getCityById", id);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/rest/InitRest.java
new file mode 100644
index 0000000..fbe34c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/rest/InitRest.java
@@ -0,0 +1,58 @@
+package com.md.demo.rest;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.md.demo.service.CityService;
+import com.md.demo.util.JsonResult;
+import com.md.demo.util.ResultCode;
+import com.md.demo.vo.CityVo;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ @Autowired
+ private CityService cityService;
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ return "Hello greetings from spring-boot2-mysql-mybatis-xml";
+ }
+
+ /**
+ * http://localhost:9090/listCities
+ *
+ * @return
+ */
+ @GetMapping("/listCities")
+ public JsonResult listCities() {
+ List list = this.cityService.listCities();
+ return new JsonResult(ResultCode.SUCCESS, list);
+ }
+
+ /**
+ * http://localhost:9090/getCityById?id=1
+ *
+ * @return
+ */
+ @GetMapping("/getCityById")
+ public JsonResult listCities(Long id) {
+ CityVo obj = this.cityService.getCityById(id);
+ return new JsonResult(ResultCode.SUCCESS, obj);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/service/CityService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/service/CityService.java
new file mode 100644
index 0000000..391199f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/service/CityService.java
@@ -0,0 +1,11 @@
+package com.md.demo.service;
+
+import java.util.List;
+import com.md.demo.vo.CityVo;
+
+public interface CityService {
+
+ public List listCities();
+
+ public CityVo getCityById(Long id);
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/service/impl/CityServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
new file mode 100644
index 0000000..f3cf11b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/service/impl/CityServiceImpl.java
@@ -0,0 +1,34 @@
+package com.md.demo.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.md.demo.dao.CityDao;
+import com.md.demo.service.CityService;
+import com.md.demo.vo.CityVo;
+
+@Service
+public class CityServiceImpl implements CityService {
+
+ @Autowired
+ private CityDao cityDao;
+
+ /**
+ * 获得城市列表
+ */
+ @Override
+ public List listCities() {
+ return this.cityDao.listCities();
+ }
+
+ /**
+ * 根据id,获得某个城市
+ */
+ @Override
+ public CityVo getCityById(Long id) {
+ return this.cityDao.getCityById(id);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/util/JsonResult.java
new file mode 100644
index 0000000..f4347a3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/util/ResultCode.java
new file mode 100644
index 0000000..c39ba46
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/vo/CityVo.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/vo/CityVo.java
new file mode 100644
index 0000000..56fc798
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/java/com/md/demo/vo/CityVo.java
@@ -0,0 +1,9 @@
+package com.md.demo.vo;
+
+import com.md.demo.bo.City;
+
+public class CityVo extends City {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/application.yml
new file mode 100644
index 0000000..4dc9fd3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/application.yml
@@ -0,0 +1,10 @@
+spring:
+ datasource:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://192.168.1.101:3306/cfdb?useUnicode=true&autoReconnect=true&allowMultiQueries=true&useSSL=false
+ username: root
+ password: 123456
+server:
+ port: 9090
+mybatis:
+ config-location: classpath:mybatis-config.xml
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/logback.xml
new file mode 100644
index 0000000..0adec0a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/mybatis-config.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/mybatis-config.xml
new file mode 100644
index 0000000..0a0a16d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/mybatis-config.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/mybatis/mapper/CityMapper.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/mybatis/mapper/CityMapper.xml
new file mode 100644
index 0000000..135cecd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-mysql-mybatis-xml/src/main/resources/mybatis/mapper/CityMapper.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/README.md
new file mode 100644
index 0000000..7685102
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-oauth2-jwt-resource【资源服务】
+
+【Oauth2+JWT集成/SpringSecurity集成】技术点
+
+功能介绍
+
+1. Oauth2+JWT集成/SpringSecurity
+
+## 本项目教程
+
+[Oauth2+JWT集成/SpringSecurity](https://hemin.blog.csdn.net/article/details/96483461)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/pom.xml
new file mode 100644
index 0000000..f0aee30
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-oauth2-jwt-resource
+ jar
+
+ spring-boot2-oauth2-jwt-resource
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ commons-io
+ commons-io
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/Application.java
new file mode 100644
index 0000000..236a485
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo.oauth;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
new file mode 100644
index 0000000..cbb6f02
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo.oauth;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/WebConfig.java
new file mode 100644
index 0000000..4ad2298
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo.oauth;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/ResourceServerConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/ResourceServerConfiguration.java
new file mode 100644
index 0000000..e3212db
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/ResourceServerConfiguration.java
@@ -0,0 +1,84 @@
+package com.md.demo.oauth.jwt.ds.config;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.io.IOException;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
+import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
+
+@Configuration
+@EnableResourceServer
+@EnableConfigurationProperties(SecurityProperties.class)
+public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
+
+ private static final String ROOT_PATTERN = "/**";
+
+ private final SecurityProperties securityProperties;
+
+ private TokenStore tokenStore;
+
+ public ResourceServerConfiguration(final SecurityProperties securityProperties) {
+ this.securityProperties = securityProperties;
+ }
+
+ @Override
+ public void configure(final ResourceServerSecurityConfigurer resources) {
+ resources.tokenStore(tokenStore());
+ }
+
+ @Override
+ public void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests()
+ // 排除路径验证
+ .antMatchers("/hello")
+ .permitAll()
+ .antMatchers(HttpMethod.GET, ROOT_PATTERN).access("#oauth2.hasScope('read')")
+ .antMatchers(HttpMethod.POST, ROOT_PATTERN).access("#oauth2.hasScope('write')")
+ .antMatchers(HttpMethod.PATCH, ROOT_PATTERN).access("#oauth2.hasScope('write')")
+ .antMatchers(HttpMethod.PUT, ROOT_PATTERN).access("#oauth2.hasScope('write')")
+ .antMatchers(HttpMethod.DELETE, ROOT_PATTERN).access("#oauth2.hasScope('write')");
+ }
+
+ @Bean
+ public DefaultTokenServices tokenServices(final TokenStore tokenStore) {
+ DefaultTokenServices tokenServices = new DefaultTokenServices();
+ tokenServices.setTokenStore(tokenStore);
+ return tokenServices;
+ }
+
+ @Bean
+ public TokenStore tokenStore() {
+ if (tokenStore == null) {
+ tokenStore = new JwtTokenStore(jwtAccessTokenConverter());
+ }
+ return tokenStore;
+ }
+
+ @Bean
+ public JwtAccessTokenConverter jwtAccessTokenConverter() {
+ JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
+ converter.setVerifierKey(getPublicKeyAsString());
+ return converter;
+ }
+
+ private String getPublicKeyAsString() {
+ try {
+ return IOUtils.toString(securityProperties.getJwt().getPublicKey().getInputStream(), UTF_8);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/SecurityProperties.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/SecurityProperties.java
new file mode 100644
index 0000000..164556d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/SecurityProperties.java
@@ -0,0 +1,32 @@
+package com.md.demo.oauth.jwt.ds.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.core.io.Resource;
+
+@ConfigurationProperties("security")
+public class SecurityProperties {
+
+ private JwtProperties jwt;
+
+ public JwtProperties getJwt() {
+ return jwt;
+ }
+
+ public void setJwt(JwtProperties jwt) {
+ this.jwt = jwt;
+ }
+
+ public static class JwtProperties {
+
+ private Resource publicKey;
+
+ public Resource getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(Resource publicKey) {
+ this.publicKey = publicKey;
+ }
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/WebSecurityConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/WebSecurityConfiguration.java
new file mode 100644
index 0000000..c0e2c76
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/jwt/ds/config/WebSecurityConfiguration.java
@@ -0,0 +1,8 @@
+package com.md.demo.oauth.jwt.ds.config;
+
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfiguration {
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/rest/InitRest.java
new file mode 100644
index 0000000..3e7ae0e
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/rest/InitRest.java
@@ -0,0 +1,28 @@
+package com.md.demo.oauth.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * 在ResourceServerConfiguration.java文件中,开启了忽略放行,不验证token
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-oauth2-jwt-resource";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/rest/UserController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/rest/UserController.java
new file mode 100644
index 0000000..053780d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/rest/UserController.java
@@ -0,0 +1,28 @@
+package com.md.demo.oauth.rest;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.security.Principal;
+
+@RestController
+@RequestMapping("/me")
+public class UserController {
+
+ //http://localhost:9100/me?access_token=xxxxxx
+ @GetMapping
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public ResponseEntity get(final Principal principal) {
+ return ResponseEntity.ok(principal);
+ }
+
+ /*
+ * 通过以下接口Post请求获得access_token【从认证服务获得】:
+ * http://localhost:9000/oauth/token?grant_type=password&username=user&password=pass
+ *
+ * 注意:Authorization中使用BasicAuth,Username和Password分别为:clientId,secret
+ */
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/util/JsonResult.java
new file mode 100644
index 0000000..0406457
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.oauth.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/util/ResultCode.java
new file mode 100644
index 0000000..f68cb8d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/java/com/md/demo/oauth/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.oauth.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/application.yml
new file mode 100644
index 0000000..1cd60fe
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/application.yml
@@ -0,0 +1,11 @@
+server:
+ port: 9100
+
+security:
+ jwt:
+ public-key: classpath:public.txt
+
+spring:
+ jackson:
+ serialization:
+ INDENT_OUTPUT: true
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/public.txt b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/public.txt
new file mode 100644
index 0000000..9b13743
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-resource/src/main/resources/public.txt
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmWI2jtKwvf0W1hdMdajc
+h+mFx9FZe3CZnKNvT/d0+2O6V1Pgkz7L2FcQx2uoV7gHgk5mmb2MZUsy/rDKj0dM
+fLzyXqBcCRxD6avALwu8AAiGRxe2dl8HqIHyo7P4R1nUaea1WCZB/i7AxZNAQtcC
+cSvMvF2t33p3vYXY6SqMucMD4yHOTXexoWhzwRqjyyC8I8uCYJ+xIfQvaK9Q1RzK
+Rj99IRa1qyNgdeHjkwW9v2Fd4O/Ln1Tzfnk/dMLqxaNsXPw37nw+OUhycFDPPQF/
+H4Q4+UDJ3ATf5Z2yQKkUQlD45OO2mIXjkWprAmOCi76dLB2yzhCX/plGJwcgb8XH
+EQIDAQAB
+-----END PUBLIC KEY-----
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/README.md
new file mode 100644
index 0000000..09a81e8
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-oauth2-jwt-server【认证服务】
+
+【Oauth2+JWT集成/SpringSecurity集成】技术点
+
+功能介绍
+
+1. Oauth2+JWT集成/SpringSecurity
+
+## 本项目教程
+
+[Oauth2+JWT集成/SpringSecurity](https://hemin.blog.csdn.net/article/details/96483461)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/pom.xml
new file mode 100644
index 0000000..390b29d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-oauth2-jwt-server
+ jar
+
+ spring-boot2-oauth2-jwt-server
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ com.h2database
+ h2
+ runtime
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/Application.java
new file mode 100644
index 0000000..236a485
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo.oauth;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
new file mode 100644
index 0000000..cbb6f02
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo.oauth;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/WebConfig.java
new file mode 100644
index 0000000..4ad2298
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo.oauth;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/props/SecurityProperties.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/props/SecurityProperties.java
new file mode 100644
index 0000000..3991ecd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/props/SecurityProperties.java
@@ -0,0 +1,58 @@
+package com.md.demo.oauth.jwt.config.props;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.core.io.Resource;
+
+@ConfigurationProperties("security")
+public class SecurityProperties {
+
+ private JwtProperties jwt;
+
+ public JwtProperties getJwt() {
+ return jwt;
+ }
+
+ public void setJwt(JwtProperties jwt) {
+ this.jwt = jwt;
+ }
+
+ public static class JwtProperties {
+
+ private Resource keyStore;
+ private String keyStorePassword;
+ private String keyPairAlias;
+ private String keyPairPassword;
+
+ public Resource getKeyStore() {
+ return keyStore;
+ }
+
+ public void setKeyStore(Resource keyStore) {
+ this.keyStore = keyStore;
+ }
+
+ public String getKeyStorePassword() {
+ return keyStorePassword;
+ }
+
+ public void setKeyStorePassword(String keyStorePassword) {
+ this.keyStorePassword = keyStorePassword;
+ }
+
+ public String getKeyPairAlias() {
+ return keyPairAlias;
+ }
+
+ public void setKeyPairAlias(String keyPairAlias) {
+ this.keyPairAlias = keyPairAlias;
+ }
+
+ public String getKeyPairPassword() {
+ return keyPairPassword;
+ }
+
+ public void setKeyPairPassword(String keyPairPassword) {
+ this.keyPairPassword = keyPairPassword;
+ }
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/AuthorizationServerConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/AuthorizationServerConfiguration.java
new file mode 100644
index 0000000..2247021
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/AuthorizationServerConfiguration.java
@@ -0,0 +1,110 @@
+package com.md.demo.oauth.jwt.config.security;
+
+import java.security.KeyPair;
+
+import javax.sql.DataSource;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.ClientDetailsService;
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
+import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
+import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
+
+import com.md.demo.oauth.jwt.config.props.SecurityProperties;
+
+@Configuration
+@EnableAuthorizationServer
+@EnableConfigurationProperties(SecurityProperties.class)
+public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
+
+ private final DataSource dataSource;
+ private final PasswordEncoder passwordEncoder;
+ private final AuthenticationManager authenticationManager;
+ private final SecurityProperties securityProperties;
+ private final UserDetailsService userDetailsService;
+
+ private JwtAccessTokenConverter jwtAccessTokenConverter;
+ private TokenStore tokenStore;
+
+ public AuthorizationServerConfiguration(final DataSource dataSource, final PasswordEncoder passwordEncoder,
+ final AuthenticationManager authenticationManager, final SecurityProperties securityProperties,
+ final UserDetailsService userDetailsService) {
+ this.dataSource = dataSource;
+ this.passwordEncoder = passwordEncoder;
+ this.authenticationManager = authenticationManager;
+ this.securityProperties = securityProperties;
+ this.userDetailsService = userDetailsService;
+ }
+
+ @Bean
+ public TokenStore tokenStore() {
+ if (tokenStore == null) {
+ tokenStore = new JwtTokenStore(jwtAccessTokenConverter());
+ }
+ return tokenStore;
+ }
+
+ @Bean
+ public DefaultTokenServices tokenServices(final TokenStore tokenStore,
+ final ClientDetailsService clientDetailsService) {
+ DefaultTokenServices tokenServices = new DefaultTokenServices();
+ tokenServices.setSupportRefreshToken(true);
+ tokenServices.setTokenStore(tokenStore);
+ tokenServices.setClientDetailsService(clientDetailsService);
+ tokenServices.setAuthenticationManager(this.authenticationManager);
+ return tokenServices;
+ }
+
+ @Bean
+ public JwtAccessTokenConverter jwtAccessTokenConverter() {
+ if (jwtAccessTokenConverter != null) {
+ return jwtAccessTokenConverter;
+ }
+
+ SecurityProperties.JwtProperties jwtProperties = securityProperties.getJwt();
+ KeyPair keyPair = keyPair(jwtProperties, keyStoreKeyFactory(jwtProperties));
+
+ jwtAccessTokenConverter = new JwtAccessTokenConverter();
+ jwtAccessTokenConverter.setKeyPair(keyPair);
+ return jwtAccessTokenConverter;
+ }
+
+ @Override
+ public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
+ clients.jdbc(this.dataSource);
+ }
+
+ @Override
+ public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
+ endpoints.authenticationManager(this.authenticationManager)
+ .accessTokenConverter(jwtAccessTokenConverter())
+ .userDetailsService(this.userDetailsService)
+ .tokenStore(tokenStore());
+ }
+
+ @Override
+ public void configure(final AuthorizationServerSecurityConfigurer oauthServer) {
+ oauthServer.passwordEncoder(this.passwordEncoder).tokenKeyAccess("permitAll()")
+ .checkTokenAccess("isAuthenticated()");
+ }
+
+ private KeyPair keyPair(SecurityProperties.JwtProperties jwtProperties, KeyStoreKeyFactory keyStoreKeyFactory) {
+ return keyStoreKeyFactory.getKeyPair(jwtProperties.getKeyPairAlias(), jwtProperties.getKeyPairPassword().toCharArray());
+ }
+
+ private KeyStoreKeyFactory keyStoreKeyFactory(SecurityProperties.JwtProperties jwtProperties) {
+ return new KeyStoreKeyFactory(jwtProperties.getKeyStore(), jwtProperties.getKeyStorePassword().toCharArray());
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/DefaultPasswordEncoderFactories.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/DefaultPasswordEncoderFactories.java
new file mode 100644
index 0000000..8c89788
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/DefaultPasswordEncoderFactories.java
@@ -0,0 +1,34 @@
+package com.md.demo.oauth.jwt.config.security;
+
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
+import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class DefaultPasswordEncoderFactories {
+
+ @SuppressWarnings("deprecation")
+ static PasswordEncoder createDelegatingPasswordEncoder() {
+ String encodingId = "bcrypt";
+ Map encoders = new HashMap<>();
+ encoders.put(encodingId, new BCryptPasswordEncoder());
+ encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
+ encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
+ encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
+ encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
+ encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
+ encoders.put("scrypt", new SCryptPasswordEncoder());
+ encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
+ encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
+ encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
+
+ DelegatingPasswordEncoder delegatingPasswordEncoder = new DelegatingPasswordEncoder(encodingId, encoders);
+ delegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(new BCryptPasswordEncoder(10));
+ return delegatingPasswordEncoder;
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/ResourceServerConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/ResourceServerConfiguration.java
new file mode 100644
index 0000000..d32ac28
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/ResourceServerConfiguration.java
@@ -0,0 +1,24 @@
+package com.md.demo.oauth.jwt.config.security;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
+
+ private final TokenStore tokenStore;
+
+ public ResourceServerConfiguration(final TokenStore tokenStore) {
+ this.tokenStore = tokenStore;
+ }
+
+ @Override
+ public void configure(final ResourceServerSecurityConfigurer resources) {
+ resources.tokenStore(tokenStore);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/WebSecurityConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/WebSecurityConfiguration.java
new file mode 100644
index 0000000..8da978f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/jwt/config/security/WebSecurityConfiguration.java
@@ -0,0 +1,63 @@
+package com.md.demo.oauth.jwt.config.security;
+
+import javax.sql.DataSource;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@EnableWebSecurity
+public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ private final DataSource dataSource;
+
+ private PasswordEncoder passwordEncoder;
+ private UserDetailsService userDetailsService;
+
+ public WebSecurityConfiguration(final DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ // 排除路径验证
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring().antMatchers("/hello");
+ }
+
+ @Override
+ protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
+ auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
+ }
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ if (passwordEncoder == null) {
+ passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
+ }
+ return passwordEncoder;
+ }
+
+ @Bean
+ @Override
+ public UserDetailsService userDetailsService() {
+ if (userDetailsService == null) {
+ userDetailsService = new JdbcDaoImpl();
+ ((JdbcDaoImpl) userDetailsService).setDataSource(dataSource);
+ }
+ return userDetailsService;
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/rest/InitRest.java
new file mode 100644
index 0000000..0def1d5
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/rest/InitRest.java
@@ -0,0 +1,28 @@
+package com.md.demo.oauth.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9090/hello
+ *
+ * 在WebSecurityConfiguration.java文件中,开启了忽略放行,不验证token
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-oauth2-jwt-server";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/rest/UserController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/rest/UserController.java
new file mode 100644
index 0000000..d99e04f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/rest/UserController.java
@@ -0,0 +1,26 @@
+package com.md.demo.oauth.rest;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.security.Principal;
+
+@RestController
+@RequestMapping("/users")
+public class UserController {
+
+ //http://localhost:9000/users/me?access_token=xxxxxx
+ @GetMapping("/me")
+ public ResponseEntity get(final Principal principal) {
+ return ResponseEntity.ok(principal);
+ }
+
+ /*
+ * 通过以下接口Post请求获得access_token:
+ * http://localhost:9000/oauth/token?grant_type=password&username=user&password=pass
+ *
+ * 注意:Authorization中使用BasicAuth,Username和Password分别为:clientId,secret
+ */
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/util/JsonResult.java
new file mode 100644
index 0000000..0406457
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.oauth.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/util/ResultCode.java
new file mode 100644
index 0000000..f68cb8d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/java/com/md/demo/oauth/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.oauth.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/application.yml
new file mode 100644
index 0000000..cde2e7a
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/application.yml
@@ -0,0 +1,14 @@
+server:
+ port: 9000
+
+security:
+ jwt:
+ key-store: classpath:keystore.jks
+ key-store-password: letmein
+ key-pair-alias: mytestkey
+ key-pair-password: changeme
+
+spring:
+ jackson:
+ serialization:
+ INDENT_OUTPUT: true
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/data.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/data.sql
new file mode 100644
index 0000000..6b2e720
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/data.sql
@@ -0,0 +1,10 @@
+-- The encrypted client_secret it `secret`
+INSERT INTO oauth_client_details (client_id, client_secret, scope, authorized_grant_types, authorities, access_token_validity)
+ VALUES ('clientId', '{bcrypt}$2a$10$vCXMWCn7fDZWOcLnIEhmK.74dvK1Eh8ae2WrWlhr2ETPLoxQctN4.', 'read,write', 'password,refresh_token,client_credentials', 'ROLE_CLIENT', 300);
+
+-- The encrypted password is `pass`
+INSERT INTO users (id, username, password, enabled) VALUES (1, 'user', '{bcrypt}$2a$10$cyf5NfobcruKQ8XGjUJkEegr9ZWFqaea6vjpXWEaSqTa2xL9wjgQC', 1);
+INSERT INTO users (id, username, password, enabled) VALUES (2, 'guest', '{bcrypt}$2a$10$cyf5NfobcruKQ8XGjUJkEegr9ZWFqaea6vjpXWEaSqTa2xL9wjgQC', 1);
+
+INSERT INTO authorities (username, authority) VALUES ('user', 'ROLE_USER');
+INSERT INTO authorities (username, authority) VALUES ('guest', 'ROLE_GUEST');
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/keystore.jks b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/keystore.jks
new file mode 100644
index 0000000..3984485
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/keystore.jks differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/schema.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/schema.sql
new file mode 100644
index 0000000..48e2ca7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-jwt-server/src/main/resources/schema.sql
@@ -0,0 +1,55 @@
+CREATE TABLE IF NOT EXISTS oauth_client_details (
+ client_id VARCHAR(256) PRIMARY KEY,
+ resource_ids VARCHAR(256),
+ client_secret VARCHAR(256) NOT NULL,
+ scope VARCHAR(256),
+ authorized_grant_types VARCHAR(256),
+ web_server_redirect_uri VARCHAR(256),
+ authorities VARCHAR(256),
+ access_token_validity INTEGER,
+ refresh_token_validity INTEGER,
+ additional_information VARCHAR(4000),
+ autoapprove VARCHAR(256)
+);
+
+CREATE TABLE IF NOT EXISTS oauth_client_token (
+ token_id VARCHAR(256),
+ token BLOB,
+ authentication_id VARCHAR(256) PRIMARY KEY,
+ user_name VARCHAR(256),
+ client_id VARCHAR(256)
+);
+
+CREATE TABLE IF NOT EXISTS oauth_access_token (
+ token_id VARCHAR(256),
+ token BLOB,
+ authentication_id VARCHAR(256),
+ user_name VARCHAR(256),
+ client_id VARCHAR(256),
+ authentication BLOB,
+ refresh_token VARCHAR(256)
+);
+
+CREATE TABLE IF NOT EXISTS oauth_refresh_token (
+ token_id VARCHAR(256),
+ token BLOB,
+ authentication BLOB
+);
+
+CREATE TABLE IF NOT EXISTS oauth_code (
+ code VARCHAR(256), authentication BLOB
+);
+
+CREATE TABLE IF NOT EXISTS users (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ username VARCHAR(256) NOT NULL,
+ password VARCHAR(256) NOT NULL,
+ enabled TINYINT(1),
+ UNIQUE KEY unique_username(username)
+);
+
+CREATE TABLE IF NOT EXISTS authorities (
+ username VARCHAR(256) NOT NULL,
+ authority VARCHAR(256) NOT NULL,
+ PRIMARY KEY(username, authority)
+);
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/README.md
new file mode 100644
index 0000000..c1e7927
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-oauth2-opaque-resource【资源服务】
+
+【Oauth2+Token详细用法/SpringSecurity】技术点
+
+功能介绍
+
+1. Oauth2+Token详细用法/SpringSecurity
+
+## 本项目教程
+
+[Oauth2+Token详细用法/SpringSecurity](https://hemin.blog.csdn.net/article/details/96483440)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/pom.xml
new file mode 100644
index 0000000..21aee68
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-oauth2-opaque-resource
+ jar
+
+ spring-boot2-oauth2-opaque-resource
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ commons-io
+ commons-io
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/Application.java
new file mode 100644
index 0000000..236a485
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo.oauth;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
new file mode 100644
index 0000000..cbb6f02
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo.oauth;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/WebConfig.java
new file mode 100644
index 0000000..4ad2298
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo.oauth;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/opaque/ds/config/ResourceServerConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/opaque/ds/config/ResourceServerConfiguration.java
new file mode 100644
index 0000000..87239ff
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/opaque/ds/config/ResourceServerConfiguration.java
@@ -0,0 +1,23 @@
+package com.md.demo.oauth.opaque.ds.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
+
+ private static final String ROOT_PATTERN = "/**";
+
+ @Override
+ public void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests()
+ // 排除路径验证
+ .antMatchers("/hello")
+ .permitAll()
+ .antMatchers(ROOT_PATTERN)
+ .authenticated();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/opaque/ds/config/WebSecurityConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/opaque/ds/config/WebSecurityConfiguration.java
new file mode 100644
index 0000000..2780018
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/opaque/ds/config/WebSecurityConfiguration.java
@@ -0,0 +1,8 @@
+package com.md.demo.oauth.opaque.ds.config;
+
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfiguration {
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/rest/InitRest.java
new file mode 100644
index 0000000..ba57d90
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/rest/InitRest.java
@@ -0,0 +1,28 @@
+package com.md.demo.oauth.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9101/hello
+ *
+ * 在ResourceServerConfiguration.java文件中,开启了忽略放行,不验证token
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-oauth2-opaque-resource";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/rest/UserController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/rest/UserController.java
new file mode 100644
index 0000000..9ec8320
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/rest/UserController.java
@@ -0,0 +1,28 @@
+package com.md.demo.oauth.rest;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.security.Principal;
+
+@RestController
+@RequestMapping("/me")
+public class UserController {
+
+ //http://localhost:9101/me?access_token=xxxxxx
+ @GetMapping
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public ResponseEntity get(final Principal principal) {
+ return ResponseEntity.ok(principal);
+ }
+
+ /*
+ * 通过以下接口Post请求获得access_token:
+ * http://localhost:9001/oauth/token?grant_type=password&username=user&password=pass
+ *
+ * 注意:Authorization中使用BasicAuth,Username和Password分别为:clientId,secret
+ */
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/util/JsonResult.java
new file mode 100644
index 0000000..0406457
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.oauth.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/util/ResultCode.java
new file mode 100644
index 0000000..f68cb8d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/java/com/md/demo/oauth/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.oauth.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/resources/application.yml
new file mode 100644
index 0000000..984f469
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/resources/application.yml
@@ -0,0 +1,12 @@
+server:
+ port: 9101
+
+security:
+ oauth2:
+ resource:
+ user-info-uri: http://localhost:9001/profile/me
+
+spring:
+ jackson:
+ serialization:
+ INDENT_OUTPUT: true
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-resource/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/README.md
new file mode 100644
index 0000000..ac1adb3
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/README.md
@@ -0,0 +1,34 @@
+# spring-boot2-oauth2-opaque-server【认证服务】
+
+【Oauth2+Token详细用法/SpringSecurity】技术点
+
+功能介绍
+
+1. Oauth2+Token详细用法/SpringSecurity
+
+## 本项目教程
+
+[Oauth2+Token详细用法/SpringSecurity](https://hemin.blog.csdn.net/article/details/96483440)
+
+## 该系列教程
+
+[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/pom.xml
new file mode 100644
index 0000000..2d5dbcf
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/pom.xml
@@ -0,0 +1,72 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-oauth2-opaque-server
+ jar
+
+ spring-boot2-oauth2-opaque-server
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ com.h2database
+ h2
+ runtime
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/Application.java
new file mode 100644
index 0000000..236a485
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo.oauth;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
new file mode 100644
index 0000000..cbb6f02
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo.oauth;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/WebConfig.java
new file mode 100644
index 0000000..4ad2298
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo.oauth;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/AuthorizationServerConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/AuthorizationServerConfiguration.java
new file mode 100644
index 0000000..61df420
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/AuthorizationServerConfiguration.java
@@ -0,0 +1,72 @@
+package com.md.demo.oauth.opaque.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.ClientDetailsService;
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
+
+import javax.sql.DataSource;
+
+@Configuration
+@EnableAuthorizationServer
+public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
+
+ private final DataSource dataSource;
+ private final PasswordEncoder passwordEncoder;
+ private final AuthenticationManager authenticationManager;
+
+ private TokenStore tokenStore;
+
+ public AuthorizationServerConfiguration(final DataSource dataSource, final PasswordEncoder passwordEncoder,
+ final AuthenticationManager authenticationManager) {
+ this.dataSource = dataSource;
+ this.passwordEncoder = passwordEncoder;
+ this.authenticationManager = authenticationManager;
+ }
+
+ @Bean
+ public TokenStore tokenStore() {
+ if (tokenStore == null) {
+ tokenStore = new JdbcTokenStore(dataSource);
+ }
+ return tokenStore;
+ }
+
+ @Bean
+ public DefaultTokenServices tokenServices(final ClientDetailsService clientDetailsService) {
+ DefaultTokenServices tokenServices = new DefaultTokenServices();
+ tokenServices.setSupportRefreshToken(true);
+ tokenServices.setTokenStore(tokenStore());
+ tokenServices.setClientDetailsService(clientDetailsService);
+ tokenServices.setAuthenticationManager(authenticationManager);
+ return tokenServices;
+ }
+
+ @Override
+ public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
+ clients.jdbc(dataSource);
+ }
+
+ @Override
+ public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
+ endpoints.authenticationManager(authenticationManager)
+ .tokenStore(tokenStore());
+ }
+
+ @Override
+ public void configure(final AuthorizationServerSecurityConfigurer oauthServer) {
+ oauthServer.passwordEncoder(passwordEncoder)
+ .tokenKeyAccess("permitAll()")
+ .checkTokenAccess("isAuthenticated()");
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/ResourceServerConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/ResourceServerConfiguration.java
new file mode 100644
index 0000000..b54277d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/ResourceServerConfiguration.java
@@ -0,0 +1,24 @@
+package com.md.demo.oauth.opaque.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
+
+ private final TokenStore tokenStore;
+
+ public ResourceServerConfiguration(final TokenStore tokenStore) {
+ this.tokenStore = tokenStore;
+ }
+
+ @Override
+ public void configure(final ResourceServerSecurityConfigurer resources) {
+ resources.tokenStore(tokenStore);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/WebSecurityConfiguration.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/WebSecurityConfiguration.java
new file mode 100644
index 0000000..0067d4f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/opaque/config/WebSecurityConfiguration.java
@@ -0,0 +1,63 @@
+package com.md.demo.oauth.opaque.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import javax.sql.DataSource;
+
+@EnableWebSecurity
+public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ private final DataSource dataSource;
+
+ private PasswordEncoder passwordEncoder;
+ private UserDetailsService userDetailsService;
+
+ public WebSecurityConfiguration(final DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ // 排除路径验证
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring().antMatchers("/hello");
+ }
+
+ @Override
+ protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
+ auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
+ }
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ if (passwordEncoder == null) {
+ passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
+ }
+ return passwordEncoder;
+ }
+
+ @Bean
+ @Override
+ public UserDetailsService userDetailsService() {
+ if (userDetailsService == null) {
+ userDetailsService = new JdbcDaoImpl();
+ ((JdbcDaoImpl) userDetailsService).setDataSource(dataSource);
+ }
+ return userDetailsService;
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/rest/InitRest.java
new file mode 100644
index 0000000..4e4608f
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/rest/InitRest.java
@@ -0,0 +1,28 @@
+package com.md.demo.oauth.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Minbo
+ */
+@RestController
+public class InitRest {
+
+ protected static Logger logger = LoggerFactory.getLogger(InitRest.class);
+
+ /**
+ * http://localhost:9001/hello
+ *
+ * 在WebSecurityConfiguration.java文件中,开启了忽略放行,不验证token
+ *
+ * @return
+ */
+ @GetMapping("/hello")
+ public String hello() {
+ logger.info("hello");
+ return "Hello greetings from spring-boot2-oauth2-opaque-server";
+ }
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/rest/ProfileController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/rest/ProfileController.java
new file mode 100644
index 0000000..5685204
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/rest/ProfileController.java
@@ -0,0 +1,26 @@
+package com.md.demo.oauth.rest;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.security.Principal;
+
+@RestController
+@RequestMapping("/profile")
+public class ProfileController {
+
+ //http://localhost:9001/profile/me?access_token=xxxxxx
+ @GetMapping("/me")
+ public ResponseEntity get(final Principal principal) {
+ return ResponseEntity.ok(principal);
+ }
+
+ /*
+ * 通过以下接口Post请求获得access_token:
+ * http://localhost:9001/oauth/token?grant_type=password&username=user&password=pass
+ *
+ * 注意:Authorization中使用BasicAuth,Username和Password分别为:clientId,secret
+ */
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/util/JsonResult.java
new file mode 100644
index 0000000..0406457
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/util/JsonResult.java
@@ -0,0 +1,60 @@
+package com.md.demo.oauth.util;
+
+import net.sf.json.JSONObject;
+
+public class JsonResult {
+ private String code;
+ private String message;
+ private Object data;
+
+ public JsonResult() {
+ this.setCode(ResultCode.SUCCESS);
+ this.setMessage(ResultCode.SUCCESS.msg());
+ }
+
+ public JsonResult(ResultCode code) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ }
+
+ public JsonResult(ResultCode code, String data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public JsonResult(ResultCode code, Object data) {
+ this.setCode(code);
+ this.setMessage(code.msg());
+ this.setData(data);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(ResultCode code) {
+ this.code = code.val();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public String toJsonString() {
+ JSONObject json = JSONObject.fromObject(this);
+ return json.toString();
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/util/ResultCode.java
new file mode 100644
index 0000000..f68cb8d
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/java/com/md/demo/oauth/util/ResultCode.java
@@ -0,0 +1,36 @@
+package com.md.demo.oauth.util;
+
+public enum ResultCode {
+
+ /** 成功 */
+ SUCCESS("200", "成功"),
+
+ /** 数据为空 */
+ SUCCESS_NO_DATA("201", "数据为空"),
+
+ /** 用户不存在 */
+ SUCCESS_NO_USER("202", "用户不存在"),
+
+ /** 今天的量已经跑光了 */
+ SUCCESS_ALL_GONE("203", "今天的量已经跑光了"),
+
+ /** 失败,请重试 */
+ SUCCESS_FAIL("204", "失败,请重试");
+
+ private ResultCode(String val, String msg) {
+ this.val = val;
+ this.msg = msg;
+ }
+
+ public String val() {
+ return val;
+ }
+
+ public String msg() {
+ return msg;
+ }
+
+ private String val;
+ private String msg;
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/application.yml
new file mode 100644
index 0000000..2797cc5
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/application.yml
@@ -0,0 +1,6 @@
+server:
+ port: 9001
+spring:
+ jackson:
+ serialization:
+ INDENT_OUTPUT: true
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/data.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/data.sql
new file mode 100644
index 0000000..6b2e720
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/data.sql
@@ -0,0 +1,10 @@
+-- The encrypted client_secret it `secret`
+INSERT INTO oauth_client_details (client_id, client_secret, scope, authorized_grant_types, authorities, access_token_validity)
+ VALUES ('clientId', '{bcrypt}$2a$10$vCXMWCn7fDZWOcLnIEhmK.74dvK1Eh8ae2WrWlhr2ETPLoxQctN4.', 'read,write', 'password,refresh_token,client_credentials', 'ROLE_CLIENT', 300);
+
+-- The encrypted password is `pass`
+INSERT INTO users (id, username, password, enabled) VALUES (1, 'user', '{bcrypt}$2a$10$cyf5NfobcruKQ8XGjUJkEegr9ZWFqaea6vjpXWEaSqTa2xL9wjgQC', 1);
+INSERT INTO users (id, username, password, enabled) VALUES (2, 'guest', '{bcrypt}$2a$10$cyf5NfobcruKQ8XGjUJkEegr9ZWFqaea6vjpXWEaSqTa2xL9wjgQC', 1);
+
+INSERT INTO authorities (username, authority) VALUES ('user', 'ROLE_USER');
+INSERT INTO authorities (username, authority) VALUES ('guest', 'ROLE_GUEST');
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/logback.xml
new file mode 100644
index 0000000..2c26e3b
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/logback.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+ UTF-8
+
+
+
+
+ log/run.log
+
+ log/run.log.%d.%i
+
+
+ 64 MB
+
+
+ 7
+
+
+
+ %d [%t] [%c] [%p] (%file:%line\)- %m%n
+
+ UTF-8
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/schema.sql b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/schema.sql
new file mode 100644
index 0000000..48e2ca7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-oauth2-opaque-server/src/main/resources/schema.sql
@@ -0,0 +1,55 @@
+CREATE TABLE IF NOT EXISTS oauth_client_details (
+ client_id VARCHAR(256) PRIMARY KEY,
+ resource_ids VARCHAR(256),
+ client_secret VARCHAR(256) NOT NULL,
+ scope VARCHAR(256),
+ authorized_grant_types VARCHAR(256),
+ web_server_redirect_uri VARCHAR(256),
+ authorities VARCHAR(256),
+ access_token_validity INTEGER,
+ refresh_token_validity INTEGER,
+ additional_information VARCHAR(4000),
+ autoapprove VARCHAR(256)
+);
+
+CREATE TABLE IF NOT EXISTS oauth_client_token (
+ token_id VARCHAR(256),
+ token BLOB,
+ authentication_id VARCHAR(256) PRIMARY KEY,
+ user_name VARCHAR(256),
+ client_id VARCHAR(256)
+);
+
+CREATE TABLE IF NOT EXISTS oauth_access_token (
+ token_id VARCHAR(256),
+ token BLOB,
+ authentication_id VARCHAR(256),
+ user_name VARCHAR(256),
+ client_id VARCHAR(256),
+ authentication BLOB,
+ refresh_token VARCHAR(256)
+);
+
+CREATE TABLE IF NOT EXISTS oauth_refresh_token (
+ token_id VARCHAR(256),
+ token BLOB,
+ authentication BLOB
+);
+
+CREATE TABLE IF NOT EXISTS oauth_code (
+ code VARCHAR(256), authentication BLOB
+);
+
+CREATE TABLE IF NOT EXISTS users (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ username VARCHAR(256) NOT NULL,
+ password VARCHAR(256) NOT NULL,
+ enabled TINYINT(1),
+ UNIQUE KEY unique_username(username)
+);
+
+CREATE TABLE IF NOT EXISTS authorities (
+ username VARCHAR(256) NOT NULL,
+ authority VARCHAR(256) NOT NULL,
+ PRIMARY KEY(username, authority)
+);
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.gitignore
new file mode 100644
index 0000000..153c933
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..72308aa
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/README.md
new file mode 100644
index 0000000..6ccedbe
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/README.md
@@ -0,0 +1,39 @@
+# spring-boot2-redis
+
+【Redis分布式缓存服务集成】技术点
+
+功能介绍
+
+1. Redis集成,常用api用法
+2. 统一封装工具类(兼容解决中文乱码问题)
+
+## 本项目文档教程
+
+[Redis分布式缓存服务集成](https://hemin.blog.csdn.net/article/details/96483538)
+
+## 该系列教程
+
+[SpringBoot系列](https://blog.csdn.net/hemin1003/column/info/40170)
+
+## 官方资料
+
+[SpringBoot连接redis](https://docs.spring.io/spring-boot/docs/2.0.6.BUILD-SNAPSHOT/reference/html/boot-features-nosql.html#boot-features-connecting-to-redis)
+
+## 个人说明
+
+期望和大家”一起学习,一起成长“,共勉,O(∩_∩)O谢谢
+
+不讲虚的,只做实干家
+
+Talk is cheap,show me the code
+
+
+
+
+## [关于我](http://heminit.com/about/)
+
+欢迎交流问题,可加我的个人QQ 469580884,或Q群号 751925591,一起探讨交流问题
+
+[我的博客地址](http://blog.csdn.net/hemin1003)
+
+[个人域名](http://heminit.com)
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/pom.xml
new file mode 100644
index 0000000..3e4c0cd
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+
+ com.md
+ spring-boot2-parent
+ 0.0.1-SNAPSHOT
+ ../pom.xml
+
+
+ spring-boot2-redis
+ jar
+
+ spring-boot2-redis
+ Spring Boot, MVC, Rest API for App
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/.DS_Store
new file mode 100644
index 0000000..e1029c6
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/.DS_Store
new file mode 100644
index 0000000..5ddc54c
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/.DS_Store
new file mode 100644
index 0000000..35a54bf
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..57a5553
Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/.DS_Store differ
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/Application.java
new file mode 100644
index 0000000..58bf6cb
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/Application.java
@@ -0,0 +1,47 @@
+package com.md.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 程序主入口
+ *
+ * @author Minbo
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * 开启过滤器功能
+ *
+ * @return
+ */
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig());
+ return new CorsFilter(source);
+ }
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/MyHttpInterceptor.java
new file mode 100644
index 0000000..34ff705
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/MyHttpInterceptor.java
@@ -0,0 +1,43 @@
+package com.md.demo;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+/**
+ * 拦截处理类
+ *
+ * @author Minbo.He
+ */
+@Component
+public class MyHttpInterceptor extends HandlerInterceptorAdapter {
+
+ protected static Logger logger = LoggerFactory.getLogger(MyHttpInterceptor.class);
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+ String url = request.getRequestURL().toString();
+ String method = request.getMethod();
+ String queryString = "";
+ // 去掉最后一个空格
+ Map params = request.getParameterMap();
+ for (String key : params.keySet()) {
+ String[] values = params.get(key);
+ for (int i = 0; i < values.length; i++) {
+ String value = values[i];
+ queryString += key + "=" + value + "&";
+ }
+ }
+ queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1);
+ logger.info(String.format("请求参数, url: %s, method: %s, params: %s", url, method, queryString));
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/WebConfig.java
new file mode 100644
index 0000000..ede99c7
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/WebConfig.java
@@ -0,0 +1,34 @@
+package com.md.demo;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+/**
+ * 拦截器定义
+ *
+ * @author Minbo.He
+ */
+@Configuration
+public class WebConfig extends WebMvcConfigurationSupport {
+
+ // 让bean提前加载,让拦截器中的@Autowired生效
+ @Bean
+ public HandlerInterceptor getMyInterceptor() {
+ return new MyHttpInterceptor();
+ }
+
+ /**
+ * 可定义多个拦截器
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 定义过滤拦截的url名称,拦截所有请求
+ registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/**");
+// registry.addInterceptor(其他拦截器).addPathPatterns("/**");
+ super.addInterceptors(registry);
+ }
+
+}
diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/redis/util/RedisUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/redis/util/RedisUtil.java
new file mode 100644
index 0000000..8b79e03
--- /dev/null
+++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/redis/util/RedisUtil.java
@@ -0,0 +1,569 @@
+package com.md.demo.redis.util;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * @author Minbo
+ *
+ */
+public class RedisUtil {
+
+ /**
+ * 指定缓存失效时间
+ *
+ * @param key 键
+ * @param time 时间(秒)
+ * @return
+ */
+ public static boolean expire(RedisTemplate redisTemplate, String key, long time) {
+ try {
+ if (time > 0) {
+ redisTemplate.expire(key, time, TimeUnit.SECONDS);
+ }
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 根据key 获取过期时间
+ *
+ * @param key 键 不能为null
+ * @return 时间(秒) 返回0代表为永久有效
+ */
+ public static long getExpire(RedisTemplate redisTemplate, String key) {
+ return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 判断key是否存在
+ *
+ * @param key 键
+ * @return true 存在 false不存在
+ */
+ public static boolean hasKey(RedisTemplate redisTemplate, String key) {
+ try {
+ return redisTemplate.hasKey(key);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 删除缓存
+ *
+ * @param key 可以传一个值 或多个
+ */
+ @SuppressWarnings("unchecked")
+ public static void del(RedisTemplate redisTemplate, String... key) {
+ if (key != null && key.length > 0) {
+ if (key.length == 1) {
+ redisTemplate.delete(key[0]);
+ } else {
+ redisTemplate.delete(CollectionUtils.arrayToList(key));
+ }
+ }
+ }
+
+ // ============================String=============================
+
+ /**
+ * 普通缓存获取
+ *
+ * @param key 键
+ * @return 值
+ */
+ public static Object get(RedisTemplate redisTemplate, String key) {
+ return key == null ? null : redisTemplate.opsForValue().get(key);
+ }
+
+ /**
+ * 普通缓存放入
+ *
+ * @param key 键
+ * @param value 值
+ * @return true成功 false失败
+ */
+ public static boolean set(RedisTemplate redisTemplate, String key, Object value) {
+ try {
+ redisTemplate.opsForValue().set(key, value);
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ }
+
+ /**
+ * 普通缓存放入并设置时间
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
+ * @return true成功 false 失败
+ */
+ public static boolean set(RedisTemplate redisTemplate, String key, Object value, long time) {
+ try {
+ if (time > 0) {
+ redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+ } else {
+ set(redisTemplate, key, value);
+ }
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 递增
+ *
+ * @param key 键
+ * @param by 要增加几(大于0)
+ * @return
+ */
+ public static long incr(RedisTemplate redisTemplate, String key, long delta) {
+ if (delta < 0) {
+ throw new RuntimeException("递增因子必须大于0");
+ }
+ return redisTemplate.opsForValue().increment(key, delta);
+ }
+
+ /**
+ * 递减
+ *
+ * @param key 键
+ * @param by 要减少几(小于0)
+ * @return
+ */
+ public static long decr(RedisTemplate redisTemplate, String key, long delta) {
+ if (delta < 0) {
+ throw new RuntimeException("递减因子必须大于0");
+ }
+ return redisTemplate.opsForValue().increment(key, -delta);
+ }
+
+ // ================================Map=================================
+
+ /**
+ * HashGet
+ *
+ * @param key 键 不能为null
+ * @param item 项 不能为null
+ * @return 值
+ */
+ public static Object hget(RedisTemplate redisTemplate, String key, String item) {
+ return redisTemplate.opsForHash().get(key, item);
+ }
+
+ /**
+ * 获取hashKey对应的所有键值
+ *
+ * @param key 键
+ * @return 对应的多个键值
+ */
+ public static Map