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 hmget(RedisTemplate redisTemplate, String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public static boolean hmset(RedisTemplate redisTemplate, String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public static boolean hmset(RedisTemplate redisTemplate, String key, Map map, + long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(redisTemplate, key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public static boolean hset(RedisTemplate redisTemplate, String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public static boolean hset(RedisTemplate redisTemplate, String key, String item, Object value, + long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(redisTemplate, key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public static void hdel(RedisTemplate redisTemplate, String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public static boolean hHasKey(RedisTemplate redisTemplate, String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public static double hincr(RedisTemplate redisTemplate, String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public static double hdecr(RedisTemplate redisTemplate, String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + + /** + * 根据key获取Set中的所有值 + * + * @param key 键 + * @return + */ + public static Set sGet(RedisTemplate redisTemplate, String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public static boolean sHasKey(RedisTemplate redisTemplate, String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public static long sSet(RedisTemplate redisTemplate, String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public static long sSetAndTime(RedisTemplate redisTemplate, String key, long time, + Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) + expire(redisTemplate, key, time); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key 键 + * @return + */ + public static long sGetSetSize(RedisTemplate redisTemplate, String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public static long setRemove(RedisTemplate redisTemplate, String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public static List lGet(RedisTemplate redisTemplate, String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public static long lGetListSize(RedisTemplate redisTemplate, String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public static Object lGetIndex(RedisTemplate redisTemplate, String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public static boolean lSet(RedisTemplate redisTemplate, String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public static boolean lSet(RedisTemplate redisTemplate, String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) + expire(redisTemplate, key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public static boolean lSet(RedisTemplate redisTemplate, String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public static boolean lSet(RedisTemplate redisTemplate, String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(redisTemplate, key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public static boolean lUpdateIndex(RedisTemplate redisTemplate, String key, long index, + Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public static long lRemove(RedisTemplate redisTemplate, String key, long count, Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/InitRest.java new file mode 100644 index 0000000..5a5d668 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/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-redis"; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/ObjectRedisTestRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/ObjectRedisTestRest.java new file mode 100644 index 0000000..340d8ba --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/ObjectRedisTestRest.java @@ -0,0 +1,48 @@ +package com.md.demo.rest; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.md.demo.redis.util.RedisUtil; +import com.md.demo.util.JsonResult; +import com.md.demo.util.ResultCode; +import com.md.demo.vo.Person; + +/** + * @author Minbo + */ +@RestController +public class ObjectRedisTestRest { + + protected static Logger logger = LoggerFactory.getLogger(ObjectRedisTestRest.class); + + @Resource + private RedisTemplate redisTemplate; + + // 例如:http://localhost:9090/setObj?id=A001&name=minbo英文名&age=100 + @RequestMapping("/setObj") + public JsonResult setObj(String id, String name, Integer age) { + Person person = new Person(); + person.setId(id); + person.setName(name); + person.setAge(age); + logger.debug("访问set:" + person.toString()); + RedisUtil.set(this.redisTemplate, "person:" + person.getId(), person); + return new JsonResult(ResultCode.SUCCESS); + } + + // 例如:http://localhost:9090/getObj?id=A001 + @RequestMapping("/getObj") + public JsonResult getObj(String id) { + logger.debug("访问get:key id={}", id); + Person person = (Person) RedisUtil.get(this.redisTemplate, "person:" + id); + String result = person.toString(); + logger.debug("get obj result=" + result); + return new JsonResult(ResultCode.SUCCESS, person); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/StringRedisTestRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/StringRedisTestRest.java new file mode 100644 index 0000000..743fb50 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/rest/StringRedisTestRest.java @@ -0,0 +1,42 @@ +package com.md.demo.rest; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.md.demo.redis.util.RedisUtil; +import com.md.demo.util.JsonResult; +import com.md.demo.util.ResultCode; + +/** + * @author Minbo + */ +@RestController +public class StringRedisTestRest { + + protected static Logger logger = LoggerFactory.getLogger(StringRedisTestRest.class); + + @Resource + private RedisTemplate redisTemplate; + + // 例如:http://localhost:9090/set?key=name&value=minbo英文名 + @RequestMapping("/set") + public JsonResult setKeyAndValue(String key, String value) { + logger.debug("访问set:key={},value={}", key, value); + RedisUtil.set(this.redisTemplate, key, value); + return new JsonResult(ResultCode.SUCCESS); + } + + // 例如:http://localhost:9090/get?key=name + @RequestMapping("/get") + public JsonResult getKey(String key) { + logger.debug("访问get:key={}", key); + String result = (String) RedisUtil.get(this.redisTemplate, key); + logger.debug("get result=" + result); + return new JsonResult(ResultCode.SUCCESS, result); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/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-redis/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-redis/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/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-redis/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-redis/src/main/java/com/md/demo/vo/Person.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/vo/Person.java new file mode 100644 index 0000000..83da240 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/java/com/md/demo/vo/Person.java @@ -0,0 +1,51 @@ +package com.md.demo.vo; + +import java.io.Serializable; + +public class Person implements Serializable { + + private static final long serialVersionUID = -6112847285691942529L; + + private String id; + private String name; + private Integer age; + + public Person() { + super(); + } + + public Person(String id, String name, Integer age) { + this.id = id; + this.name = name; + this.age = age; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + @Override + public String toString() { + return "Person [id=" + id + ", name=" + name + ", age=" + age + "]"; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/resources/application.yml new file mode 100644 index 0000000..fe2d30a --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/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-redis/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/src/main/resources/logback.xml new file mode 100644 index 0000000..8561ff9 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-redis/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-rocketmq/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.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-rocketmq/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.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-rocketmq/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.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-rocketmq/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/.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-rocketmq/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/README.md new file mode 100644 index 0000000..b257bcd --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/README.md @@ -0,0 +1,89 @@ +# spring-boot2-rocketmq + +## 【RocketMQ】技术点 + +RocketMq是一个由阿里巴巴开源的消息中间件,在设计上借鉴了Kafka,其2012年开源,2017年成为Apache顶级项目。 + +RocketMQ基础组件: + +1. Producer是消息生产者 +2. Consumer是消息消费者 +3. Topic是消息传递中间者,其中存放的是消息逻辑地址 + +## 功能介绍 + +1. 如何与springboot集成 +2. 如何建立连接,发送不同消息数据类型 +3. 如何订阅,且消费不同消息数据类型 +4. 场景案例分析 + +## 场景案例分析 + +一般MQ适用场景如下 + +1. 流量削峰,提升系统高并发处理能力,比如秒杀场景 +2. 异步处理,应用解耦,提高系统吞吐量 + +## 附加说明 + +使用命令新建Topic + +1、安装完后,进入到apache-rocketmq目录 +2、使用命令:sh /bin/mqadmin updateTopic -n localhost:9876 -b localhost:10911 -t test-topic-1 + +updateTopic命令主要是三个参数: + +-n nameserver地址和端口,一般启动broker时要指定 +-b broker_ip:broker_port,ip是启动broker机器的ip,默认是10911 +-t 新主题名称 + +### 问题:注意事项(autoCreateTopicEnable=true) + +1、使用默认设置autoCreateTopicEnable=true,这样会导致topic的设置不能规范管理,没有统一的审核等 +2、使用默认设置autoCreateTopicEnable=true,还会造成负载均衡失效 + +所以,一般生产环境中会设置autoCreateTopicEnable=false + +设置方式:启动broker时关闭掉,命令如nohup sh bin/mqbroker -n localhost:9876 autoCreateTopicEnable=false & + +## 其他官方资料 + +[RocketMq官方网址](http://rocketmq.apache.org/) + +[RocketMq官方安装详细步骤,和案例演示说明](http://rocketmq.apache.org/docs/quick-start/) + +[RocketMQ-SpringBoot官方代码Demo](https://github.com/hemin1003/rocketmq-spring) + +[RocketMQ-SpringBoot官方代码Demo-中文教程说明](https://github.com/hemin1003/rocketmq-spring/blob/master/README_zh_CN.md) + +[RocketMQ控制台-运维管理系统搭建文档](https://github.com/apache/rocketmq-externals/blob/master/rocketmq-console/doc/1_0_0/UserGuide_CN.md) + +[RocketMQ-常见问题FAQ](https://github.com/hemin1003/rocketmq-spring/blob/master/README_zh_CN.md) + +## 本项目教程 + +[RocketMQ集成和场景案例分析](https://blog.csdn.net/hemin1003/article/details/90405506) + +## 该系列教程 + +[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) diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/pom.xml new file mode 100644 index 0000000..49ffd9e --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-rocketmq + jar + + spring-boot2-rocketmq + 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 + + + + + com.github.org-hejianhui + spring-boot-starter-rocketmq + + + + com.google.code.gson + gson + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/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-rocketmq/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/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-rocketmq/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/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-rocketmq/src/main/java/com/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/MyHttpInterceptor.java new file mode 100644 index 0000000..76da3e0 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/MyHttpInterceptor.java @@ -0,0 +1,42 @@ +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 + "&"; + } + } + 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-rocketmq/src/main/java/com/md/demo/MyTopics.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/MyTopics.java new file mode 100644 index 0000000..ad19603 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/MyTopics.java @@ -0,0 +1,16 @@ +package com.md.demo; + +public interface MyTopics { + + public static final String TOPIC1 = "test-topic-1"; + + /** + * 普通文本消息 + */ + public static final String TAG1 = "my-tag-normal"; + + /** + * 对象数据消息 + */ + public static final String TAG2 = "my-tag-object"; +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/ProducerApplication.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/ProducerApplication.java new file mode 100644 index 0000000..2d60f36 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/ProducerApplication.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; + +/** + * 程序主入口(Producer生产者,发送消息) + * + * @author Minbo + * + */ +@SpringBootApplication +public class ProducerApplication { + + public static void main(String[] args) { + SpringApplication.run(ProducerApplication.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-rocketmq/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/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-rocketmq/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-rocketmq/src/main/java/com/md/demo/consumer/ConsumerApplication.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/consumer/ConsumerApplication.java new file mode 100644 index 0000000..3a063b3 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/consumer/ConsumerApplication.java @@ -0,0 +1,76 @@ +package com.md.demo.consumer; + +import java.util.List; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.message.MessageExt; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.md.demo.MyTopics; +import com.md.demo.vo.OrderPaidEvent; + +/** + * 消费者,消费消息 + * + * 直接run运行即可 + * + * @author Minbo + * + */ +public class ConsumerApplication { + + protected static Logger logger = LoggerFactory.getLogger(ConsumerApplication.class); + + public static void main(String[] args) throws InterruptedException, MQClientException { + + // 指定消费组名 + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my-mq-group"); + + // 指定服务器地址名 + consumer.setNamesrvAddr("localhost:9876"); + + // 订阅一个或多个主题 + consumer.subscribe(MyTopics.TOPIC1, "*"); + + // 注册回调 + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + for (MessageExt msg : msgs) { + logger.info("入口,消息tag=" + msg.getTags()); + + // 区分不同Tag,不同处理方式 + switch (msg.getTags()) { + + // 1. 普通文本消息 + case MyTopics.TAG1: + logger.info("消息tag=" + msg.getTags() + ",消费者,消费数据【普通文本消息】:msg=" + new String(msg.getBody())); + break; + + // 2. 对象数据消息 + case MyTopics.TAG2: + Gson gson = new Gson(); + OrderPaidEvent obj = gson.fromJson(new String(msg.getBody()), OrderPaidEvent.class); + logger.info("消息tag=" + msg.getTags() + ",消费者,消费数据【对象数据】:order=" + obj.toString()); + break; + + } + } + + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + // 启动消费者实例 + consumer.start(); + + logger.info("Consumer Started."); + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/rest/InitRest.java new file mode 100644 index 0000000..adf5a94 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/rest/InitRest.java @@ -0,0 +1,73 @@ +package com.md.demo.rest; + +import java.math.BigDecimal; +import java.util.Random; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.md.demo.MyTopics; +import com.md.demo.vo.OrderPaidEvent; +import com.zc.smartcity.rocketmq.core.RocketMQTemplate; + +/** + * @author Minbo + */ +@RestController +public class InitRest { + + protected static Logger logger = LoggerFactory.getLogger(InitRest.class); + + @Resource + private RocketMQTemplate rocketMQTemplate; + + @GetMapping("/hello") + public String hello() { + return "Hello greetings from spring-boot2-rocketmq"; + } + + /** + * 发送普通文本消息 + * http://localhost:9090/sendMsgText + * @return + */ + @RequestMapping("/sendMsgText") + public String sendMsgText() { + // 发送普通文本消息 + String msg = "Hello,World,spring-boot2-rocketmq! flag=" + new Random().nextInt(100); + String destination1 = MyTopics.TOPIC1 + ":" + MyTopics.TAG1; + rocketMQTemplate.convertAndSend(destination1, msg); + logger.info("sendMsg success。发送普通文本消息 msg=" + msg); + + return "success for text"; + } + + /** + * 发送对象数据消息 + * http://localhost:9090/sendMsgObj + * @return + */ + @RequestMapping("/sendMsgObj") + public String sendMsgObj() { + // 发送对象数据消息 + OrderPaidEvent order = new OrderPaidEvent("T_001_ID_" + new Random().nextInt(100), new BigDecimal("88.00")); + String destination2 = MyTopics.TOPIC1 + ":" + MyTopics.TAG2; + rocketMQTemplate.convertAndSend(destination2, order); + logger.info("sendMsg success。发送对象消息 order=" + order.toString()); + + return "success for obj"; + } + + /* + * RocketMQ的最佳实践中推荐:一个应用尽可能用一个Topic,消息子类型用tags来标识,tags可以由应用自由设置。 + * 在使用rocketMQTemplate发送消息时,通过设置发送方法的destination参数来设置消息的目的地, + * destination的格式为topicName:tagName,:前面表示topic的名称,后面表示tags名称。 + * + * 注意: tags从命名来看像是一个复数,但发送消息时,目的地只能指定一个topic下的一个tag,不能指定多个。 + */ +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/vo/OrderPaidEvent.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/vo/OrderPaidEvent.java new file mode 100644 index 0000000..1e467f3 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/java/com/md/demo/vo/OrderPaidEvent.java @@ -0,0 +1,44 @@ +package com.md.demo.vo; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 虚拟一个订单支付事件 + * + * @author Minbo + * + */ +public class OrderPaidEvent implements Serializable { + + private static final long serialVersionUID = 3613990271572167383L; + + private String orderId; + private BigDecimal paidMoney; + + public OrderPaidEvent(String orderId, BigDecimal paidMoney) { + this.orderId = orderId; + this.paidMoney = paidMoney; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public BigDecimal getPaidMoney() { + return paidMoney; + } + + public void setPaidMoney(BigDecimal paidMoney) { + this.paidMoney = paidMoney; + } + + @Override + public String toString() { + return "OrderPaidEvent [orderId=" + orderId + ", paidMoney=" + paidMoney + "]"; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/resources/application.yml new file mode 100644 index 0000000..52ea4a2 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/resources/application.yml @@ -0,0 +1,15 @@ +# tomcat +server: + port: 9090 +spring: + # mq service + rocketmq: + name-server: localhost:9876 + producer: + group: my-mq-group + send-message-timeout: 86400 + compress-message-body-threshold: 4096 + max-message-size: 4194304 + retry-times-when-send-async-failed: 0 + retry-next-server: true + retry-times-when-send-failed: 2 \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/src/main/resources/logback.xml new file mode 100644 index 0000000..e5abfaf --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-rocketmq/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-schedule/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.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-schedule/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.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-schedule/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.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-schedule/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/.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-schedule/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/README.md new file mode 100644 index 0000000..9e6ee05 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/README.md @@ -0,0 +1,66 @@ +# spring-boot2-schedule + +【@scheduled定时器】技术点 + +功能介绍 + +1. 定时器计划用法介绍 +2. 开启并行多线程任务两种方式 +3. 场景案例分析 + +## 本项目教程 + +[@Scheduled定时器用法和场景案例分析](https://blog.csdn.net/hemin1003/article/details/90454462) + +## 该系列教程 + +[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170) + +## 场景案例分析 + +### 1. 分布式部署下任务重复执行问题 + +可以通过分布式锁实现,多节点部署时,在任务启动时先获取锁是否存在,如果不存在,则加锁后、自身执行 + +比如通过redis setnx实现,向redis中存一个key值,每次会先判断该key值是否存在 + +### 2. 当服务器有问题如宕机,那失败或丢失的任务如何处理,怎么补偿 + +可以把每次执行时间持久化到db中(我们目前使用中的方式),或者存入到redis中,然后判定周期区间,重新执行任务 + +## 推荐平台 + +1. [Elastic-Job](http://elasticjob.io/index_zh.html) + +Elastic-Job是一个分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成。 +Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务;Elastic-Job-Cloud采用自研Mesos Framework的解决方案,额外提供资源治理、应用分发以及进程隔离等功能。 + +2. [XXL-JOB](http://www.xuxueli.com/xxl-job/#/),这里推荐此家,轻量、简单易用 + +XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展,与springboot集成十分简单。 + +### 附加 + +当项目不大、业务逻辑不是很复杂时,利用@Scheduled来执行任务或跑批,一般来说就够用了 + +随着项目发展壮大,业务越来越复杂时,就可以考虑使用上面提到的推荐平台其中之一了 + + +## 个人说明 + +期望和大家”一起学习,一起成长“,共勉,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-schedule/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/pom.xml new file mode 100644 index 0000000..f418c1d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-schedule + jar + + spring-boot2-schedule + 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-schedule/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/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-schedule/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/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-schedule/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/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-schedule/src/main/java/com/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/Application.java new file mode 100644 index 0000000..ba182cd --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/Application.java @@ -0,0 +1,23 @@ +package com.md.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * 程序主入口 + * + * @author Minbo.He + * + */ +@SpringBootApplication +@EnableScheduling +@EnableAsync +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-schedule/src/main/java/com/md/demo/ScheduleConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduleConfig.java new file mode 100644 index 0000000..f37fac6 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduleConfig.java @@ -0,0 +1,22 @@ +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.He + */ +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + // 开启一个固定10个大小的线程池,也使用Executors下其他的线程池 + taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10)); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduledTasks.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduledTasks.java new file mode 100644 index 0000000..4ec5db4 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduledTasks.java @@ -0,0 +1,60 @@ +package com.md.demo; + +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.service.DemoService; + +/** + * 任务中心1 + * + * @author Minbo.He + * + */ +@Component +public class ScheduledTasks { + + protected static Logger logger = LoggerFactory.getLogger(ScheduledTasks.class); + + @Autowired + private DemoService service; + + /* + * 一般用法详解 + * + * initialDelay表示一个初始延迟时间,第一次被调用前延迟的时间 + * fixedDelay表示一个固定延迟时间执行,上个任务完成后,延迟多久执行 + */ + + // 启动立即执行 + // 每5秒执行一次 + @Scheduled(initialDelay = 1000, fixedDelay = 5000) + public void test1() { + logger.info("test1这里,每5秒执行一次。DemoService --->>> " + this.service.sayHello()); + } + + // 每5秒执行一次 + @Scheduled(initialDelay = 1000, fixedDelay = 5000) + public void test2() { + logger.info("test2这里,每5秒执行一次"); + } + + +// Cron表达式用法:秒 分 时 日 月 周 +// 比如: +// 每5秒执行一次:*/5 * * * * * +// 每30分钟执行一次:* */30 * * * * +// 每1小时执行一次:* * */1 * * * +// 每天2点执行一次:* * 2 * * * + + // 固定时间才执行,即为10秒的整数倍执行,比如20秒,30秒,40秒时,会执行 + // 每10秒执行一次 + @Scheduled(cron = "*/10 * * * * *") + public void test3() { + logger.info("test3这里,每10秒执行一次"); + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduledTasksAsync.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduledTasksAsync.java new file mode 100644 index 0000000..dcac852 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/ScheduledTasksAsync.java @@ -0,0 +1,33 @@ +package com.md.demo; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * + * 并行多线程任务功能(方式二) + * + * 任务中心2:通过异步方式执行调度任务 + * + * 配置Application入口的@EnableAsync,在定时任务方法前面配置@Async,即配置了任务线程池 + * + * @author Minbo.He + * + */ +@Component +public class ScheduledTasksAsync { + + protected static Logger logger = LoggerFactory.getLogger(ScheduledTasksAsync.class); + + // 启动立即执行 + // 每5秒执行一次 + @Async + @Scheduled(initialDelay = 1000, fixedDelay = 5000) + public void test4() { + logger.info("test4这里,每5秒执行一次"); + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/java/com/md/demo/service/DemoService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/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-schedule/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-schedule/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/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-schedule/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-schedule/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/resources/application.yml new file mode 100644 index 0000000..2ea1b3e --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/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-schedule/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/src/main/resources/logback.xml new file mode 100644 index 0000000..0adec0a --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-schedule/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-sharding-jdbc/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.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-sharding-jdbc/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.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-sharding-jdbc/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.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-sharding-jdbc/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/.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-sharding-jdbc/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/pom.xml new file mode 100644 index 0000000..f1a3b28 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-sharding-jdbc + jar + + spring-boot2-sharding-jdbc + 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-sharding-jdbc/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/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-sharding-jdbc/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/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-sharding-jdbc/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/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-sharding-jdbc/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/main/java/com/md/demo/rest/InitRest.java new file mode 100644 index 0000000..6335fa6 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc"; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/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-sharding-jdbc/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/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-sharding-jdbc/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/main/resources/application.yml new file mode 100644 index 0000000..afef73d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-sharding-jdbc/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/src/main/resources/logback.xml new file mode 100644 index 0000000..2c26e3b --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-sharding-jdbc/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-swagger-req-params-log/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.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-swagger-req-params-log/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.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-swagger-req-params-log/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.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-swagger-req-params-log/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/.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-swagger-req-params-log/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/README.md new file mode 100644 index 0000000..8eb0e40 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/README.md @@ -0,0 +1,34 @@ +# spring-boot2-swagger-req-params-log + +【日志输出header/body接口参数】技术点 + +功能介绍 + +1. 日志输出header/body接口参数 + +## 本项目教程 + +[日志输出header/body接口参数](xxx) + +## 该系列教程 + +[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-swagger-req-params-log/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/pom.xml new file mode 100644 index 0000000..ff51909 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-swagger-req-params-log + jar + + spring-boot2-swagger-req-params-log + Spring Boot, MVC, Rest API for App + + + UTF-8 + 1.8 + 2.9.2 + + + + + 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 + ${swagger.version} + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.3 + + + org.projectlombok + lombok + + + com.alibaba + fastjson + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/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-swagger-req-params-log/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/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-swagger-req-params-log/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/Application.java new file mode 100644 index 0000000..2e4e77c --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/Application.java @@ -0,0 +1,21 @@ +package com.md.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +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); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/SwaggerConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/SwaggerConfig.java new file mode 100644 index 0000000..6b8b261 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/SwaggerConfig.java @@ -0,0 +1,63 @@ +package com.md.demo; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Parameter; +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() { + // 定义全局header参数 + ParameterBuilder useridPar = new ParameterBuilder(); + List pars = new ArrayList<>(); + useridPar.name("userId").defaultValue("").description("用户id").modelRef(new ModelRef("string")) + .parameterType("header").required(false).build(); + pars.add(useridPar.build()); + + 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() + .globalOperationParameters(pars); + } + + @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-swagger-req-params-log/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/WebConfig.java new file mode 100644 index 0000000..6e1b59e --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/WebConfig.java @@ -0,0 +1,58 @@ +package com.md.demo; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +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; + +import com.md.demo.params.CustomHttpInterceptor; +import com.md.demo.params.RepeatedlyReadFilter; + +/** + * 拦截器定义 + * + * @author Minbo.He + */ +@Configuration +public class WebConfig extends WebMvcConfigurationSupport { + + // 让bean提前加载,让拦截器中的@Autowired生效 + @Bean + public HandlerInterceptor getInterceptor() { + return new CustomHttpInterceptor(); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + public FilterRegistrationBean repeatedlyReadFilter() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + RepeatedlyReadFilter repeatedlyReadFilter = new RepeatedlyReadFilter(); + registration.setFilter(repeatedlyReadFilter); + registration.addUrlPatterns("/*"); + return registration; + } + + @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.getInterceptor()).addPathPatterns("/**"); + super.addInterceptors(registry); + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/dto/GetByIdDTO.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/dto/GetByIdDTO.java new file mode 100644 index 0000000..7cf9ade --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/dto/GetByIdDTO.java @@ -0,0 +1,23 @@ +package com.md.demo.dto; + +import javax.validation.constraints.NotEmpty; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("根据用户ID标识查询") +public class GetByIdDTO { + + @ApiModelProperty(value = "用户ID标识", required = true) + @NotEmpty(message = "用户ID标识不能为空") + private String id; + + // 当配置多个验证字段,验证失败时提示内容会一起返回 + +// @ApiModelProperty(value = "用户名", required = true) +// @NotEmpty(message = "用户名不能为空") +// private String name; + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/CustomHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/CustomHttpInterceptor.java new file mode 100644 index 0000000..84090b2 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/CustomHttpInterceptor.java @@ -0,0 +1,65 @@ +package com.md.demo.params; + +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; + +import com.md.demo.util.NetworkUtil; + +/** + * 拦截处理类 + * + * @author Minbo + */ +@Component +public class CustomHttpInterceptor extends HandlerInterceptorAdapter { + + protected static Logger logger = LoggerFactory.getLogger(CustomHttpInterceptor.class); + + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + long start = System.currentTimeMillis(); + String url = request.getRequestURL().toString(); + // 接口过滤打印 + if (url != null && url.contains("/hello")) { + return true; + } + + 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 + "&"; + } + } + // URL 参数 + queryString = queryString.equals("") ? null : queryString.substring(0, queryString.length() - 1); + + // body 参数 + RequestWrapper requestWrapper = new RequestWrapper(request); + String bodyParams = ParamsUtil.replace(requestWrapper.getBody()); + + // header参数 + String headersParams = ParamsUtil.getHeadersInfo(requestWrapper); + + // 对方IP + String cIp = NetworkUtil.getIpAddress(request); + + long end = System.currentTimeMillis(); + + logger.info(String.format( + "请求参数, url: %s, method: %s, query-params: %s, body-params: %s, headers-params: %s, c-ip: %s, run-time/ms: %s", + url, method, queryString, bodyParams, headersParams, cIp, (end - start) + "")); + return true; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/ParamsUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/ParamsUtil.java new file mode 100644 index 0000000..e112c5f --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/ParamsUtil.java @@ -0,0 +1,39 @@ +package com.md.demo.params; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; + +import com.alibaba.fastjson.JSON; + +public class ParamsUtil { + + @SuppressWarnings("rawtypes") + public static String getHeadersInfo(HttpServletRequest request) { + Map map = new HashMap(); + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String key = (String) headerNames.nextElement().toString().toUpperCase(); + if (key.contains("USERID") || key.contains("TIMESTAMP") || key.contains("SID") || key.contains("SIGN")) { + String value = request.getHeader(key); + map.put(key, value); + } + } + return JSON.toJSONString(map); + } + + // 去除字符串中的空格、回车、换行符、制表符 + public static String replace(String str) { + String dest = ""; + if (str != null) { + Pattern p = Pattern.compile("\\s*|\t|\r|\n"); + Matcher m = p.matcher(str); + dest = m.replaceAll(""); + } + return dest; + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/RepeatedlyReadFilter.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/RepeatedlyReadFilter.java new file mode 100644 index 0000000..a3c38f6 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/RepeatedlyReadFilter.java @@ -0,0 +1,38 @@ +package com.md.demo.params; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +public class RepeatedlyReadFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + ServletRequest requestWrapper = null; + if (servletRequest instanceof HttpServletRequest) { + requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest); + } + if (requestWrapper == null) { + filterChain.doFilter(servletRequest, servletResponse); + } else { + filterChain.doFilter(requestWrapper, servletResponse); + } + } + + @Override + public void destroy() { + + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/RequestWrapper.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/RequestWrapper.java new file mode 100644 index 0000000..5454944 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/params/RequestWrapper.java @@ -0,0 +1,86 @@ +package com.md.demo.params; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.*; + +public class RequestWrapper extends HttpServletRequestWrapper { + + private final String body; + + public RequestWrapper(HttpServletRequest request) { + super(request); + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = null; + InputStream inputStream = null; + try { + inputStream = request.getInputStream(); + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + char[] charBuffer = new char[128]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } else { + stringBuilder.append(""); + } + } catch (IOException ex) { + + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); + ServletInputStream servletInputStream = new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + return servletInputStream; + + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + public String getBody() { + return this.body; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/rest/DemoController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/rest/DemoController.java new file mode 100644 index 0000000..574eb30 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/rest/DemoController.java @@ -0,0 +1,58 @@ +package com.md.demo.rest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.md.demo.dto.GetByIdDTO; +import com.md.demo.service.IUserService; +import com.md.demo.util.BaseController; +import com.md.demo.util.HttpStatusCodeUtil; +import com.md.demo.util.JsonResult; +import com.md.demo.vo.UserVO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; + +/** + * @author Minbo + */ +@RestController +@RequestMapping("/demo") +@Api(tags = { "接口-演示" }) +@Slf4j +public class DemoController extends BaseController { + + @Autowired + private IUserService userService; + + @ApiOperation(value = "根据id获得用户信息", notes = "id不能为空", httpMethod = "POST") + @PostMapping(value = "/getUserById") + @SuppressWarnings({ "rawtypes", "unchecked" }) + public JsonResult getUserById(@Validated @RequestBody GetByIdDTO dto, BindingResult result, + HttpServletRequest request, HttpServletResponse response) { + // 验证参数合法性 + JsonResult validResult = super.getJsonResult(dto, result); + if (validResult != null) { + // 设置http响应码,利于监控工具,不要统一使用200 + HttpStatusCodeUtil.setCode(response, 4403); + return validResult; + } + + // 获取用户ID + String userId = request.getHeader("userId"); + log.info("获取用户ID,userId={}", userId); + + // 逻辑处理 + UserVO obj = this.userService.getUserById(dto); + return JsonResult.ok(obj); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/rest/InitController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/rest/InitController.java new file mode 100644 index 0000000..eb8e1ac --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/rest/InitController.java @@ -0,0 +1,58 @@ +package com.md.demo.rest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.JsonResult; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; + +/** + * @author Minbo + */ +@RestController +public class InitController { + + protected static Logger logger = LoggerFactory.getLogger(InitController.class); + + /** + * http://localhost:9090/hello + * + * @return + */ + @ApiOperation(value = "/hello 欢迎入口", httpMethod = "GET") + @RequestMapping(value = "/hello") + public String hello() { + logger.info("hello"); + return "Hello greetings from spring-boot2-swagger-req-params-log"; + } + + @ApiOperation(value = "/getUserName 根据用户id获得用户的姓名", notes = "id不能为空", httpMethod = "GET") + @ApiImplicitParam(dataType = "string", name = "userId", value = "用户id", required = true) + @RequestMapping(value = "/getUserName") + @SuppressWarnings({ "rawtypes" }) + public JsonResult getUserName(@RequestHeader String userId) { + String result = "hello " + userId + ",name=张三"; + return JsonResult.ok(result); + } + + /** + * 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-swagger-req-params-log/src/main/java/com/md/demo/service/IUserService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/service/IUserService.java new file mode 100644 index 0000000..4b264cf --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/service/IUserService.java @@ -0,0 +1,21 @@ +package com.md.demo.service; + +import com.md.demo.dto.GetByIdDTO; +import com.md.demo.vo.UserVO; + +/** + * 用户信息中心 + * + * @author Minbo + * + */ +public interface IUserService { + + /** + * 根据id获取用户信息 + * + * @param dto + * @return + */ + public UserVO getUserById(GetByIdDTO dto); +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/service/impl/UserServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..711aaee --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/service/impl/UserServiceImpl.java @@ -0,0 +1,29 @@ +package com.md.demo.service.impl; + +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson.JSON; +import com.md.demo.dto.GetByIdDTO; +import com.md.demo.service.IUserService; +import com.md.demo.vo.UserVO; + +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class UserServiceImpl implements IUserService { + + @Override + public UserVO getUserById(GetByIdDTO dto) { + // 模拟数据 + UserVO obj = new UserVO(); + obj.setUserId(dto.getId()); + obj.setNickName("Minbo"); + obj.setBlogUrl("https://hemin.blog.csdn.net/"); + obj.setWechat("hemin_it"); + + log.info("获取成功,dto={},返回数据obj={}", JSON.toJSONString(dto), JSON.toJSONString(obj)); + return obj; + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/BaseController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/BaseController.java new file mode 100644 index 0000000..0bb4971 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/BaseController.java @@ -0,0 +1,30 @@ +package com.md.demo.util; + +import java.util.List; + +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; + +/** + * 基类 + * + * @author Minbo + * + */ +public class BaseController { + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public JsonResult getJsonResult(Object model, BindingResult result) { + if (result.hasErrors()) { + StringBuilder stringBuilder = new StringBuilder(); + List allErrors = result.getAllErrors(); + for (ObjectError objectError : allErrors) { + String defaultMessage = objectError.getDefaultMessage(); + // 验证失败时提示内容一起拼接返回 + stringBuilder.append(defaultMessage).append(";"); + } + return new JsonResult(CodeEnums.PARA_ERR.getCode(), stringBuilder.toString(), model); + } + return null; + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/CodeEnums.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/CodeEnums.java new file mode 100644 index 0000000..a6b8b1c --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/CodeEnums.java @@ -0,0 +1,128 @@ +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), "请联系管理员配置不存在的版本信息"), + + + //---------end--公共业务参数---------------- +// LIANLIAN_QUERY_ACCT_INFO_FAILED(Integer.valueOf(30022), "连连支付查询账户信息失败"), +// LIANLIAN_UNLINKED_ACCTIND_APPLY_FAILED(Integer.valueOf(30024), "连连支付个人用户解绑银行卡失败"), +// LIANLIAN_QUERY_USER_INFO_FAILED(Integer.valueOf(30026), "连连支付查询用户信息失败"), +// LIANLIAN_GET_RANDOM_PASSWORD_FAILED(Integer.valueOf(30028), "连连支付获取随机密码因子失败"), +// LIANLIAN_OPENACCT_APPLY_UNACTIVATED_FAILED(Integer.valueOf(30030), "连连支付个人待激活开户申请失败"), +// LIANLIAN_OPENACCT_APPLY_FAILED(Integer.valueOf(30032), "连连支付个人开户申请失败"), +// LIANLIAN_OPENACCT_VERIFY_FAILED(Integer.valueOf(30034), "连连个人开户验证失败"), +// LIANLIAN_QUERY_LINKEDACCT_FAILED(Integer.valueOf(30036), "连连查询绑卡信息失败"), +// LIANLIAN_CANCEL_APPLY_FAILED(Integer.valueOf(30038), "连连个人销户失败"), +// LIANLIAN_FIND_PASSWORD_APPLY_FAILED(Integer.valueOf(30040), "连连支付个人开户申请失败"), +// LIANLIAN_FIND_PASSWORD_VERIFY_FAILED(Integer.valueOf(30042), "连连个人开户验证失败"), + + //--------------业务参数---------------- + 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-swagger-req-params-log/src/main/java/com/md/demo/util/HttpStatusCodeUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/HttpStatusCodeUtil.java new file mode 100644 index 0000000..d753eb8 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/HttpStatusCodeUtil.java @@ -0,0 +1,29 @@ +package com.md.demo.util; + +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + +/** + * http响应码工具类 + * + * @author Minbo + * + */ +@Slf4j +public class HttpStatusCodeUtil { + + /** + * 设置http响应码 + * + * @param response + * @param statusCode + */ + public static void setCode(HttpServletResponse response, Integer statusCode) { + try { + response.setStatus(statusCode); + } catch (Exception ex) { + log.error("设置http响应码异常:" + ex.getMessage(), ex); + } + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/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-swagger-req-params-log/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-swagger-req-params-log/src/main/java/com/md/demo/util/NetworkUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/NetworkUtil.java new file mode 100644 index 0000000..c129bb9 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/util/NetworkUtil.java @@ -0,0 +1,270 @@ +package com.md.demo.util; + +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地址 + * http://blog.csdn.net/zhenzhendeblog/article/details/49702575 + * @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]; + } + + /** + * 获取用户真实IP地址-新版,惠头条提供的代码 + * @return + */ + public static String getIpAddressNew(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + 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(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = (String) ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + + /** + * 获取来访者的浏览器版本 + * + * @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-swagger-req-params-log/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/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-swagger-req-params-log/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-swagger-req-params-log/src/main/java/com/md/demo/vo/UserVO.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/vo/UserVO.java new file mode 100644 index 0000000..bea7600 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/java/com/md/demo/vo/UserVO.java @@ -0,0 +1,22 @@ +package com.md.demo.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("用户信息") +public class UserVO { + + @ApiModelProperty(value = "昵称") + private String nickName; + + @ApiModelProperty(value = "用户ID") + private String userId; + + @ApiModelProperty(value = "博客地址") + private String blogUrl; + + @ApiModelProperty(value = "微信号") + private String wechat; +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/resources/application.yml new file mode 100644 index 0000000..afef73d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/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-swagger-req-params-log/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/src/main/resources/logback.xml new file mode 100644 index 0000000..2c26e3b --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params-log/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-swagger-req-params/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.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-swagger-req-params/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.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-swagger-req-params/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.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-swagger-req-params/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/.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-swagger-req-params/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/README.md new file mode 100644 index 0000000..4aa9636 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/README.md @@ -0,0 +1,35 @@ +# spring-boot2-swagger-req-params + +【header/body接口参数+Swagger2集成用法】技术点 + +功能介绍 + +1. header/body接口参数+Swagger2集成用法 +2. 接口常用规范用法 + +## 本项目教程 + +[header/body接口参数+Swagger2集成用法](https://hemin.blog.csdn.net/article/details/99638102) + +## 该系列教程 + +[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-swagger-req-params/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/pom.xml new file mode 100644 index 0000000..8ade5a8 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-swagger-req-params + jar + + spring-boot2-swagger-req-params + Spring Boot, MVC, Rest API for App + + + UTF-8 + 1.8 + 2.9.2 + + + + + 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 + ${swagger.version} + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.3 + + + org.projectlombok + lombok + + + com.alibaba + fastjson + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/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-swagger-req-params/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/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-swagger-req-params/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/Application.java new file mode 100644 index 0000000..2e4e77c --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/Application.java @@ -0,0 +1,21 @@ +package com.md.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +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); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/MyHttpInterceptor.java new file mode 100644 index 0000000..d320cbd --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/MyHttpInterceptor.java @@ -0,0 +1,50 @@ +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("/")) { + 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-swagger-req-params/src/main/java/com/md/demo/SwaggerConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/SwaggerConfig.java new file mode 100644 index 0000000..6b8b261 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/SwaggerConfig.java @@ -0,0 +1,63 @@ +package com.md.demo; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Parameter; +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() { + // 定义全局header参数 + ParameterBuilder useridPar = new ParameterBuilder(); + List pars = new ArrayList<>(); + useridPar.name("userId").defaultValue("").description("用户id").modelRef(new ModelRef("string")) + .parameterType("header").required(false).build(); + pars.add(useridPar.build()); + + 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() + .globalOperationParameters(pars); + } + + @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-swagger-req-params/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/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-swagger-req-params/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-swagger-req-params/src/main/java/com/md/demo/dto/GetByIdDTO.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/dto/GetByIdDTO.java new file mode 100644 index 0000000..7cf9ade --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/dto/GetByIdDTO.java @@ -0,0 +1,23 @@ +package com.md.demo.dto; + +import javax.validation.constraints.NotEmpty; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("根据用户ID标识查询") +public class GetByIdDTO { + + @ApiModelProperty(value = "用户ID标识", required = true) + @NotEmpty(message = "用户ID标识不能为空") + private String id; + + // 当配置多个验证字段,验证失败时提示内容会一起返回 + +// @ApiModelProperty(value = "用户名", required = true) +// @NotEmpty(message = "用户名不能为空") +// private String name; + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/rest/DemoController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/rest/DemoController.java new file mode 100644 index 0000000..3fea62d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/rest/DemoController.java @@ -0,0 +1,58 @@ +package com.md.demo.rest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.md.demo.dto.GetByIdDTO; +import com.md.demo.service.IUserService; +import com.md.demo.util.BaseController; +import com.md.demo.util.HttpStatusCodeUtil; +import com.md.demo.util.JsonResult; +import com.md.demo.vo.UserVO; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; + +/** + * @author Minbo + */ +@RestController +@RequestMapping("/demo") +@Api(tags = { "接口-演示" }) +@Slf4j +public class DemoController extends BaseController { + + @Autowired + private IUserService userService; + + @ApiOperation(value = "根据id获得用户信息", notes = "id不能为空", httpMethod = "POST") + @PostMapping(value = "/getUserById") + @SuppressWarnings({ "rawtypes", "unchecked" }) + public JsonResult getUserById(@Validated @RequestBody GetByIdDTO dto, BindingResult result, + HttpServletRequest request, HttpServletResponse response) { + // 验证参数合法性(@NotEmpty注解) + JsonResult validResult = super.getJsonResult(dto, result); + if (validResult != null) { + // 设置http响应码,利于监控工具,不要统一使用200 + HttpStatusCodeUtil.setCode(response, 4403); + return validResult; + } + + // 获取用户ID + String userId = request.getHeader("userId"); + log.info("获取用户ID,userId={}", userId); + + // 逻辑处理 + UserVO obj = this.userService.getUserById(dto); + return JsonResult.ok(obj); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/rest/InitController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/rest/InitController.java new file mode 100644 index 0000000..1372ff2 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/rest/InitController.java @@ -0,0 +1,58 @@ +package com.md.demo.rest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.JsonResult; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; + +/** + * @author Minbo + */ +@RestController +public class InitController { + + protected static Logger logger = LoggerFactory.getLogger(InitController.class); + + /** + * http://localhost:9090/hello + * + * @return + */ + @ApiOperation(value = "/hello 欢迎入口", httpMethod = "GET") + @RequestMapping(value = "/hello") + public String hello() { + logger.info("hello"); + return "Hello greetings from spring-boot2-swagger-req-params"; + } + + @ApiOperation(value = "/getUserName 根据用户id获得用户的姓名", notes = "id不能为空", httpMethod = "GET") + @ApiImplicitParam(dataType = "string", name = "userId", value = "用户id", required = true) + @RequestMapping(value = "/getUserName") + @SuppressWarnings({ "rawtypes" }) + public JsonResult getUserName(@RequestHeader String userId) { + String result = "hello " + userId + ",name=张三"; + return JsonResult.ok(result); + } + + /** + * 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-swagger-req-params/src/main/java/com/md/demo/service/IUserService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/service/IUserService.java new file mode 100644 index 0000000..4b264cf --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/service/IUserService.java @@ -0,0 +1,21 @@ +package com.md.demo.service; + +import com.md.demo.dto.GetByIdDTO; +import com.md.demo.vo.UserVO; + +/** + * 用户信息中心 + * + * @author Minbo + * + */ +public interface IUserService { + + /** + * 根据id获取用户信息 + * + * @param dto + * @return + */ + public UserVO getUserById(GetByIdDTO dto); +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/service/impl/UserServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..711aaee --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/service/impl/UserServiceImpl.java @@ -0,0 +1,29 @@ +package com.md.demo.service.impl; + +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson.JSON; +import com.md.demo.dto.GetByIdDTO; +import com.md.demo.service.IUserService; +import com.md.demo.vo.UserVO; + +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class UserServiceImpl implements IUserService { + + @Override + public UserVO getUserById(GetByIdDTO dto) { + // 模拟数据 + UserVO obj = new UserVO(); + obj.setUserId(dto.getId()); + obj.setNickName("Minbo"); + obj.setBlogUrl("https://hemin.blog.csdn.net/"); + obj.setWechat("hemin_it"); + + log.info("获取成功,dto={},返回数据obj={}", JSON.toJSONString(dto), JSON.toJSONString(obj)); + return obj; + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/BaseController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/BaseController.java new file mode 100644 index 0000000..0bb4971 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/BaseController.java @@ -0,0 +1,30 @@ +package com.md.demo.util; + +import java.util.List; + +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; + +/** + * 基类 + * + * @author Minbo + * + */ +public class BaseController { + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public JsonResult getJsonResult(Object model, BindingResult result) { + if (result.hasErrors()) { + StringBuilder stringBuilder = new StringBuilder(); + List allErrors = result.getAllErrors(); + for (ObjectError objectError : allErrors) { + String defaultMessage = objectError.getDefaultMessage(); + // 验证失败时提示内容一起拼接返回 + stringBuilder.append(defaultMessage).append(";"); + } + return new JsonResult(CodeEnums.PARA_ERR.getCode(), stringBuilder.toString(), model); + } + return null; + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/CodeEnums.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/CodeEnums.java new file mode 100644 index 0000000..a6b8b1c --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/CodeEnums.java @@ -0,0 +1,128 @@ +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), "请联系管理员配置不存在的版本信息"), + + + //---------end--公共业务参数---------------- +// LIANLIAN_QUERY_ACCT_INFO_FAILED(Integer.valueOf(30022), "连连支付查询账户信息失败"), +// LIANLIAN_UNLINKED_ACCTIND_APPLY_FAILED(Integer.valueOf(30024), "连连支付个人用户解绑银行卡失败"), +// LIANLIAN_QUERY_USER_INFO_FAILED(Integer.valueOf(30026), "连连支付查询用户信息失败"), +// LIANLIAN_GET_RANDOM_PASSWORD_FAILED(Integer.valueOf(30028), "连连支付获取随机密码因子失败"), +// LIANLIAN_OPENACCT_APPLY_UNACTIVATED_FAILED(Integer.valueOf(30030), "连连支付个人待激活开户申请失败"), +// LIANLIAN_OPENACCT_APPLY_FAILED(Integer.valueOf(30032), "连连支付个人开户申请失败"), +// LIANLIAN_OPENACCT_VERIFY_FAILED(Integer.valueOf(30034), "连连个人开户验证失败"), +// LIANLIAN_QUERY_LINKEDACCT_FAILED(Integer.valueOf(30036), "连连查询绑卡信息失败"), +// LIANLIAN_CANCEL_APPLY_FAILED(Integer.valueOf(30038), "连连个人销户失败"), +// LIANLIAN_FIND_PASSWORD_APPLY_FAILED(Integer.valueOf(30040), "连连支付个人开户申请失败"), +// LIANLIAN_FIND_PASSWORD_VERIFY_FAILED(Integer.valueOf(30042), "连连个人开户验证失败"), + + //--------------业务参数---------------- + 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-swagger-req-params/src/main/java/com/md/demo/util/HttpStatusCodeUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/HttpStatusCodeUtil.java new file mode 100644 index 0000000..d753eb8 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/HttpStatusCodeUtil.java @@ -0,0 +1,29 @@ +package com.md.demo.util; + +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + +/** + * http响应码工具类 + * + * @author Minbo + * + */ +@Slf4j +public class HttpStatusCodeUtil { + + /** + * 设置http响应码 + * + * @param response + * @param statusCode + */ + public static void setCode(HttpServletResponse response, Integer statusCode) { + try { + response.setStatus(statusCode); + } catch (Exception ex) { + log.error("设置http响应码异常:" + ex.getMessage(), ex); + } + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/JsonResult.java new file mode 100644 index 0000000..2a1f284 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/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 + '}'; + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/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-swagger-req-params/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-swagger-req-params/src/main/java/com/md/demo/vo/UserVO.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/vo/UserVO.java new file mode 100644 index 0000000..bea7600 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/java/com/md/demo/vo/UserVO.java @@ -0,0 +1,22 @@ +package com.md.demo.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("用户信息") +public class UserVO { + + @ApiModelProperty(value = "昵称") + private String nickName; + + @ApiModelProperty(value = "用户ID") + private String userId; + + @ApiModelProperty(value = "博客地址") + private String blogUrl; + + @ApiModelProperty(value = "微信号") + private String wechat; +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/resources/application.yml new file mode 100644 index 0000000..afef73d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/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-swagger-req-params/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/src/main/resources/logback.xml new file mode 100644 index 0000000..2c26e3b --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger-req-params/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-swagger/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.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-swagger/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.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-swagger/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.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-swagger/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/.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-swagger/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/README.md new file mode 100644 index 0000000..673537f --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/README.md @@ -0,0 +1,34 @@ +# spring-boot2-swagger + +【Swagger2集成用法】技术点 + +功能介绍 + +1. Swagger2集成用法 + +## 本项目教程 + +[Swagger2集成用法](https://hemin.blog.csdn.net/article/details/99637936) + +## 该系列教程 + +[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-swagger/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/pom.xml new file mode 100644 index 0000000..a2b6379 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-swagger + jar + + spring-boot2-swagger + Spring Boot, MVC, Rest API for App + + + UTF-8 + 1.8 + 2.9.2 + + + + + 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 + ${swagger.version} + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.3 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/java/com/md/demo/Application.java new file mode 100644 index 0000000..c89f7d0 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/java/com/md/demo/Application.java @@ -0,0 +1,21 @@ +package com.md.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +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); + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/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-swagger/src/main/java/com/md/demo/SwaggerConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/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-swagger/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/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-swagger/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/java/com/md/demo/rest/InitRest.java new file mode 100644 index 0000000..ea8765d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/java/com/md/demo/rest/InitRest.java @@ -0,0 +1,57 @@ +package com.md.demo.rest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.md.demo.util.JsonResult; +import com.md.demo.util.ResultCode; + +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; + +/** + * @author Minbo + */ +@RestController +public class InitRest { + + protected static Logger logger = LoggerFactory.getLogger(InitRest.class); + + /** + * http://localhost:9090/hello + * + * @return + */ + @ApiOperation(value = "/hello 欢迎入口", httpMethod = "GET") + @RequestMapping(value = "/hello") + public String hello() { + logger.info("hello"); + return "Hello greetings from spring-boot2-swagger"; + } + + @ApiOperation(value = "/getUserName 根据用户id获得用户的姓名", notes = "id不能为空", httpMethod = "GET") + @ApiImplicitParam(dataType = "string", name = "userId", value = "用户id", required = true) + @RequestMapping(value = "/getUserName") + public JsonResult getUserName(String userId) { + String result = "hello " + userId + ",name=张三"; + return new JsonResult(ResultCode.SUCCESS, result); + } + + /** + * 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-swagger/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/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-swagger/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/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-swagger/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/resources/application.yml new file mode 100644 index 0000000..afef73d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-swagger/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/src/main/resources/logback.xml new file mode 100644 index 0000000..2c26e3b --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-swagger/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-tomcat/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.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-tomcat/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.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-tomcat/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.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-tomcat/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/.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-tomcat/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/README.md new file mode 100644 index 0000000..8ccc74d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/README.md @@ -0,0 +1,41 @@ +# spring-boot2-tomcat + +【Tomcat容器自定义】技术点 + +功能介绍 + +1. Tomcat容器配置用法,使用.yml文件方式 +2. 设置tomcat的最大连接数和最大并发数 +3. Springboot1和Springboot2版本之间的差异用法 + +## 本项目教程 + +[内嵌Tomcat自定义配置用法](https://blog.csdn.net/hemin1003/article/details/91991433) + +## 该系列教程 + +[SpringBoot2系列](https://blog.csdn.net/hemin1003/column/info/40170) + +## 官方资料 + +[SpringBoot2配置Tomcat](https://docs.spring.io/spring-boot/docs/2.0.6.RELEASE/reference/html/howto-embedded-web-servers.html#howto-enable-multiple-connectors-in-tomcat) + + +## 个人说明 + +期望和大家”一起学习,一起成长“,共勉,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-tomcat/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/pom.xml new file mode 100644 index 0000000..a0a3d30 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-tomcat + jar + + spring-boot2-tomcat + 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-tomcat/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/com/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/src/main/java/com/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/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-tomcat/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/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-tomcat/src/main/java/com/md/demo/MyTomcatCustomizer.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/com/md/demo/MyTomcatCustomizer.java new file mode 100644 index 0000000..8631268 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/com/md/demo/MyTomcatCustomizer.java @@ -0,0 +1,37 @@ +package com.md.demo; + +import org.apache.catalina.connector.Connector; +import org.apache.coyote.http11.Http11NioProtocol; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 自定义实现Tomcat配置 + * + * @author Minbo + * + * 当和配置application.yml一起都配置时,以配置文件为准。想要代码生效,可把文件重命名为application.yml.bak + */ +@Configuration +public class MyTomcatCustomizer { + + @Bean + public ConfigurableServletWebServerFactory configurableServletWebServerFactory() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + tomcat.addAdditionalTomcatConnectors(createConnector()); + return tomcat; + } + + private Connector createConnector() { + Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); + Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); + connector.setPort(8090); + // 最大线程数 + protocol.setMaxThreads(2); + // 最大连接数 + protocol.setMaxConnections(10); + return connector; + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/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-tomcat/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/com/md/demo/rest/InitRest.java new file mode 100644 index 0000000..0d28838 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/java/com/md/demo/rest/InitRest.java @@ -0,0 +1,36 @@ +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-tomcat"; + } + + /** + * http://localhost:9090/getUserInfo?userId=minbo + * + * @param userId + * @return + */ + @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-tomcat/src/main/java/com/md/demo/service/DemoService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/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-tomcat/src/main/java/com/md/demo/service/impl/DemoServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-tomcat/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-tomcat/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/resources/application.yml new file mode 100644 index 0000000..3feac22 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/resources/application.yml @@ -0,0 +1,9 @@ +# tomcat +server: + tomcat: + # 最大线程数 + max-threads: 2 + # 最大连接数 + max-connections: 10 + # 监听端口 + port: 9090 \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/src/main/resources/logback.xml new file mode 100644 index 0000000..0adec0a --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-tomcat/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-valid/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.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-valid/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.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-valid/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.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-valid/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/.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-valid/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/README.md new file mode 100644 index 0000000..d829231 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/README.md @@ -0,0 +1,35 @@ +# spring-boot2-valid + +【@Valid注解用法详解+全局处理器Exception优雅处理参数验证用法】技术点 + +功能介绍 + +1. @Valid注解用法详解 +2. 全局处理器Exception优雅处理参数验证 + +## 本项目教程 + +[@Valid注解用法详解+全局处理器Exception优雅处理参数验证用法](https://hemin.blog.csdn.net/article/details/103241022) + +## 该系列教程 + +[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-valid/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/pom.xml new file mode 100644 index 0000000..0454760 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-valid + jar + + spring-boot2-valid + 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 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/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-valid/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/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-valid/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/Application.java new file mode 100644 index 0000000..f26646f --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/Application.java @@ -0,0 +1,52 @@ +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.ComponentScan; +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 +@ComponentScan(basePackages = "com.md") +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-valid/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/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-valid/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-valid/src/main/java/com/md/demo/SwaggerConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/SwaggerConfig.java new file mode 100644 index 0000000..5203837 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/SwaggerConfig.java @@ -0,0 +1,60 @@ +package com.md.demo; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Parameter; +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() { + // 定义全局header参数 + ParameterBuilder useridPar = new ParameterBuilder(); + List pars = new ArrayList<>(); + useridPar.name("access_token").defaultValue("").description("访问身份令牌").modelRef(new ModelRef("string")) + .parameterType("header").required(false).build(); + pars.add(useridPar.build()); + + 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() + .globalOperationParameters(pars); + } + + @SuppressWarnings("deprecation") + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + // 标题 + .title("在线接口测试平台:spring-boot2-valid服务") + // 简介 + .description("rest接口层:xxx接口服务") + // 服务条款 + .termsOfServiceUrl("https://blog.csdn.net/hemin1003") + // 作者个人信息 + .contact("Minbo.He") + // 版本 + .version("1.0").build(); + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/WebConfig.java new file mode 100644 index 0000000..f99d7b8 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/WebConfig.java @@ -0,0 +1,44 @@ +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 getInterceptor() { + 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.getInterceptor()).addPathPatterns("/**"); + super.addInterceptors(registry); + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/GetController.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/GetController.java new file mode 100644 index 0000000..4182b13 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/GetController.java @@ -0,0 +1,56 @@ +package com.md.demo.controller; + +import javax.validation.Valid; + +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.md.demo.controller.base.BaseDTO; +import com.md.demo.dto.GetUserByIdDTO; +import com.md.demo.exception.ParamaErrorException; +import com.md.demo.util.JsonResult; +import com.md.demo.util.ResultCode; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; + +/** + * @author Minbo + */ +@RestController +@RequestMapping("/api/") +@Api(tags = { "查询接口" }) +@Slf4j +public class GetController { + + /** + * 测试Post请求 + */ + @ApiOperation(value = "TestPost接口", httpMethod = "POST") + @PostMapping("/test/post") + public JsonResult testPost(@Valid @RequestBody BaseDTO dto) { + log.debug("enter test post api..."); + return new JsonResult(ResultCode.SUCCESS); + } + + /** + * 测试Get请求 + */ + @Validated + @ApiOperation(value = "TestGet接口", httpMethod = "GET") + @GetMapping("/test/get/{userName}") + public JsonResult testGet(@PathVariable String userName) { + log.debug("enter test get api..."); + if (userName == null || "".equals(userName)) { + throw new ParamaErrorException("userName 不能为空"); + } + return new JsonResult(ResultCode.SUCCESS); + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/Initcontroller.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/Initcontroller.java new file mode 100644 index 0000000..c9b4231 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/Initcontroller.java @@ -0,0 +1,40 @@ +package com.md.demo.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.ApiOperation; + +/** + * @author Minbo + */ +@RestController +public class Initcontroller { + + protected static Logger logger = LoggerFactory.getLogger(Initcontroller.class); + + /** + * http://localhost:9090/hello + * + * @return + */ + @GetMapping("/hello") + public String hello() { + logger.info("hello"); + return "Hello greetings from spring-boot2-valid"; + } + + /** + * http://localhost:9090/exception + * + * @return + */ + @ApiOperation(value = "异常测试", httpMethod = "GET") + @GetMapping("/exception") + public String exception() { + int a = 10 / 0; + return "exception," + a; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/base/BaseDTO.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/base/BaseDTO.java new file mode 100644 index 0000000..b501e18 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/controller/base/BaseDTO.java @@ -0,0 +1,42 @@ +package com.md.demo.controller.base; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("请求参数基础模型") +public class BaseDTO { + + @ApiModelProperty(value = "轨迹跟踪traceId/长度固定19位,由服务端下发", example = "2002271818562848295", required = true) + @NotEmpty(message = "轨迹跟踪traceId不能为空") + private String traceId; + + @ApiModelProperty(value = "请求requestId/长度固定8位(字母转大写)", example = "ABCD1234", required = true) + @NotEmpty(message = "请求requestId不能为空") + private String requestId; + + @ApiModelProperty(value = "请求时间/格式要求:时间戳/毫秒", example = "1581928973000", required = true) + @NotEmpty(message = "请求时间不能为空") + private String time; + + @ApiModelProperty(value = "请求源标识,填appId值", example = "A123456", required = true) + @NotEmpty(message = "请求源标识不能为空") + private String caller; + + @ApiModelProperty(value = "请求接口名", example = "getUserById", required = true) + @NotEmpty(message = "请求接口名不能为空") + private String api; + + // 嵌套必须加 @Valid,否则嵌套中的验证不生效 + @Valid + @ApiModelProperty(value = "业务参数", required = true) + private T param; + + @ApiModelProperty(value = "接口签名值:把业务参数param按照ASCII码排序,再拼接秘钥后进行md5加密,得出32位值(字母转大写)", required = true) + private String sign; + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/dto/GetUserByIdDTO.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/dto/GetUserByIdDTO.java new file mode 100644 index 0000000..7bb4146 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/dto/GetUserByIdDTO.java @@ -0,0 +1,19 @@ +package com.md.demo.dto; + +import javax.validation.constraints.NotEmpty; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("测试-查询条件") +public class GetUserByIdDTO { + + @ApiModelProperty(value = "id标识值", required = true) + @NotEmpty(message = "[userId值]不能为空") + private String userId; + + @ApiModelProperty(value = "用户名") + private String userName; +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/exception/GlobalExceptionHandler.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..324b3c5 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/exception/GlobalExceptionHandler.java @@ -0,0 +1,99 @@ +package com.md.demo.exception; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.util.StringUtils; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import com.md.demo.util.JsonResult; +import com.md.demo.util.ResultCode; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestControllerAdvice("com.md") +public class GlobalExceptionHandler { + + @ExceptionHandler(Exception.class) + public JsonResult handleException(Exception e) { + log.error("系统异常【全局异常处理】:" + e.getMessage(), e); + return new JsonResult(ResultCode.SYS_EXCEPTION, "系统异常:" + e.getMessage()); + } + + /** + * 忽略参数异常处理器 + * + * @param e 忽略参数异常 + * @return ResponseResult + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MissingServletRequestParameterException.class) + public JsonResult parameterMissingExceptionHandler(MissingServletRequestParameterException e) { + log.error("忽略参数异常", e); + return new JsonResult(ResultCode.PARAM_ERROR, "请求参数 " + e.getParameterName() + " 不能为空"); + } + + /** + * 缺少请求体异常处理器 + * + * @param e 缺少请求体异常 + * @return ResponseResult + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(HttpMessageNotReadableException.class) + public JsonResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) { + log.error("缺少请求体异常", e); + return new JsonResult(ResultCode.PARAM_ERROR, "参数体不能为空"); + } + + /** + * 参数效验异常处理器 + * + * @param e 参数验证异常 + * @return ResponseInfo + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentNotValidException.class) + public JsonResult parameterExceptionHandler(MethodArgumentNotValidException e) { + log.error("数验证异常", e); + // 获取异常信息 + BindingResult exceptions = e.getBindingResult(); + // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息 + if (exceptions.hasErrors()) { + List errors = exceptions.getAllErrors(); + if (!errors.isEmpty()) { + // 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可 + FieldError fieldError = (FieldError) errors.get(0); + return new JsonResult(ResultCode.PARAM_ERROR, fieldError.getDefaultMessage()); + } + } + return new JsonResult(ResultCode.PARAM_ERROR); + } + + /** + * 自定义参数错误异常处理器 + * + * @param e 自定义参数 + * @return ResponseInfo + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler({ ParamaErrorException.class }) + public JsonResult paramExceptionHandler(ParamaErrorException e) { + log.error("自定义参数参数", e); + // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息 + if (!StringUtils.isEmpty(e.getMessage())) { + return new JsonResult(ResultCode.PARAM_ERROR, e.getMessage()); + } + return new JsonResult(ResultCode.PARAM_ERROR); + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/exception/ParamaErrorException.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/exception/ParamaErrorException.java new file mode 100644 index 0000000..d1c5d82 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/exception/ParamaErrorException.java @@ -0,0 +1,14 @@ +package com.md.demo.exception; + +public class ParamaErrorException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ParamaErrorException() { + } + + public ParamaErrorException(String message) { + super(message); + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/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-valid/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-valid/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/util/ResultCode.java new file mode 100644 index 0000000..8239f8f --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/java/com/md/demo/util/ResultCode.java @@ -0,0 +1,42 @@ +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", "失败,请重试"), + + /** 系统异常 */ + SYS_EXCEPTION("205", "系统异常"), + + /** 请求参数错误 */ + PARAM_ERROR("206", "请求参数错误"); + + 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-valid/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/resources/application.yml new file mode 100644 index 0000000..afef73d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/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-valid/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/src/main/resources/logback.xml new file mode 100644 index 0000000..2c26e3b --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-valid/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-wechat-pay/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.DS_Store new file mode 100644 index 0000000..feca861 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.gitignore b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.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-wechat-pay/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..72308aa --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.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-wechat-pay/.mvn/wrapper/maven-wrapper.jar b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.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-wechat-pay/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.mvn/wrapper/maven-wrapper.properties b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/.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-wechat-pay/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/README.md new file mode 100644 index 0000000..f59c566 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/README.md @@ -0,0 +1,34 @@ +# spring-boot2-wechat-pay + +【微信企业支付集成】技术点 + +功能介绍 + +1. 微信企业支付集成(最快五分钟集成) + +## 本项目教程 + +[微信企业支付集成(最快五分钟集成)](https://hemin.blog.csdn.net/article/details/104605815) + +## 该系列教程 + +[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-wechat-pay/cert/README.md b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/cert/README.md new file mode 100644 index 0000000..02205d5 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/cert/README.md @@ -0,0 +1 @@ +这里放支付证书,微信后台生成下载 \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/pom.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/pom.xml new file mode 100644 index 0000000..ac9035f --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + + com.md + spring-boot2-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + spring-boot2-wechat-pay + jar + + spring-boot2-wechat-pay + 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.apache.httpcomponents + httpmime + + + jdom + jdom + + + org.projectlombok + lombok + true + + + io.springfox + springfox-swagger2 + + + io.springfox + springfox-swagger-ui + + + com.github.xiaoymin + swagger-bootstrap-ui + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/.DS_Store new file mode 100644 index 0000000..e1029c6 Binary files /dev/null and b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/src/main/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/.DS_Store b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/src/main/java/.DS_Store differ diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/Application.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/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-wechat-pay/src/main/java/com/md/demo/MyHttpInterceptor.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/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-wechat-pay/src/main/java/com/md/demo/ScheduleConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/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-wechat-pay/src/main/java/com/md/demo/WebConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/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-wechat-pay/src/main/java/com/md/demo/pay/test/WechatPayServiceTest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/test/WechatPayServiceTest.java new file mode 100644 index 0000000..dad8d3b --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/test/WechatPayServiceTest.java @@ -0,0 +1,33 @@ +package com.md.demo.pay.test; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import com.md.demo.pay.utils.variation.PayServiceUtils; + +/** + * 本地测试类 + * + * @author Minbo + * + */ +@Service +public class WechatPayServiceTest { + + protected static Logger logger = LoggerFactory.getLogger(WechatPayServiceTest.class); + + // 测试 + public static void main(String[] args) { + + // 订单查询 +// wechat.doEquery("996846M20180330115059R5X9H9MHM", null); + + // 支付打款 + PayServiceUtils.doEpay("wx3ff92cec62c097d1", "o7Hzn0rr6U3Xb7Q1W9M-bH7SQXys", "192.168.1.1", "100", + "996846M20180330115059R5X9H9MHY", null, null, null, "xxx的红包"); + + System.out.println("done"); + } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/ConfigUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/ConfigUtil.java new file mode 100644 index 0000000..541eabd --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/ConfigUtil.java @@ -0,0 +1,16 @@ +package com.md.demo.pay.utils; + +/** + * 微信支付相关配置信息 + */ +public class ConfigUtil { + + /** + * 企业付款地址 + */ + // 企业付款接口(POST) + public final static String PROMOTION_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; + + // 企业付款查询接口(POST) + public final static String PROMOTION_QUERY_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo"; +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/DateUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/DateUtil.java new file mode 100644 index 0000000..149a7b1 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/DateUtil.java @@ -0,0 +1,632 @@ +package com.md.demo.pay.utils; + +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-wechat-pay/src/main/java/com/md/demo/pay/utils/FsClientWithCertSSL.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/FsClientWithCertSSL.java new file mode 100644 index 0000000..2886104 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/FsClientWithCertSSL.java @@ -0,0 +1,312 @@ +package com.md.demo.pay.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.SSLContext; + +import org.apache.commons.codec.Charsets; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLContexts; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.Args; +import org.apache.http.util.EntityUtils; + +import com.md.demo.pay.utils.variation.WeixinPayConfig; + +/** + * 通过微信支付的企业证书建立安全连接 + */ +@SuppressWarnings("deprecation") +public class FsClientWithCertSSL { + + // 携带证书的client + private static CloseableHttpClient httpClient; // 可以优化加上httpclient池来管理httpclient + // 编码格式 utf-8 + private static String CHARSET = "UTF-8"; + // 指定读取证书格式为PKCS12 + private final static String CEART_MODE = "PKCS12"; + +// static { +// // 设置http请求连接超时时间 +// RequestConfig config = RequestConfig.custom().setConnectTimeout(30000).setSocketTimeout(60000).build();// timeunit +// // seconds +// httpClient = createClient(config);// 创建 client +// } + + /** + * get请求 + * + * @param url 请求url + * @param params 请求参数 + * @return + */ + public static String doGet(String url, Map params, String projectFlag) { + return doGet(url, params, CHARSET, projectFlag); + } + + /** + * post请求 + * + * @param url 请求url + * @param params 请求参数 + * @return + */ + public static String doPost(String url, Map params, String projectFlag) { + return doPost(url, params, CHARSET, projectFlag); + } + + /** + * post请求 + * + * @param url 请求地址 + * @param paramsXml 请求的参数xml格式 + * @return + */ + public static String doPost(String url, String paramsXml, String projectFlag) { + return doPost(url, paramsXml, CHARSET, projectFlag); + } + + /** + * post请求 + * + * @param url 请求地址 + * @param paramsXml 请求的参数xml格式 + * @param charset 设置编码格式 + * @return + */ + public static String doPost(String url, String paramsXml, String charset, String projectFlag) { + Args.notNull(url, "请求目标url"); + try { + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("Connection", "keep-alive"); + httpPost.addHeader("Accept", "*/*"); + httpPost.addHeader("Content-Type", "text/xml; charset=UTF-8"); + httpPost.addHeader("Host", "api.mch.weixin.qq.com"); + httpPost.addHeader("X-Requested-With", "XMLHttpRequest"); + httpPost.addHeader("Cache-Control", "max-age=0"); + httpPost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) "); + if (paramsXml != null) { + httpPost.setEntity((new StringEntity(paramsXml, ContentType.TEXT_XML.getMimeType(), CHARSET))); + } + RequestConfig config = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(6000).build();// timeunit + // : + // seconds + httpClient = createClient(config, projectFlag);// 创建 client + CloseableHttpResponse response = httpClient.execute(httpPost);// 异常? + int statusCode = response.getStatusLine().getStatusCode(); + try { + if (statusCode != 200) { + httpPost.abort(); + throw new RuntimeException("HttpClient,error status code :" + statusCode); + } + HttpEntity entity = response.getEntity(); + String result = null; + if (entity != null) { + result = EntityUtils.toString(entity, Charsets.UTF_8); + } + EntityUtils.consume(entity); + return result; + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } finally { + response.close(); + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } finally { + // 关闭连接,释放资源 + if (httpClient != null) { + try { + httpClient.close(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } + } + } + + /** + * HTTP Get 获取内容 + * + * @param url 请求的url地址 ?之前的地址 + * @param params 请求的参数 + * @param charset 编码格式 + * @return 响应结果 + */ + public static String doGet(String url, Map params, String charset, String projectFlag) { + Args.notNull(url, "请求目标url"); + try { + if (params != null && !params.isEmpty()) { + List pairs = new ArrayList(params.size()); + for (Map.Entry entry : params.entrySet()) { + String value = entry.getValue(); + if (value != null) { + pairs.add(new BasicNameValuePair(entry.getKey(), value)); + } + } + url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset)); + } + HttpGet httpGet = new HttpGet(url); + RequestConfig config = RequestConfig.custom().setConnectTimeout(30000).setSocketTimeout(60000).build();// timeunit + // : + // seconds + httpClient = createClient(config, projectFlag);// 创建 client + CloseableHttpResponse response = httpClient.execute(httpGet); + int statusCode = response.getStatusLine().getStatusCode(); + try { + if (statusCode != 200) { + httpGet.abort(); + throw new RuntimeException("HttpClient,error status code :" + statusCode); + } + HttpEntity entity = response.getEntity(); + String result = null; + if (entity != null) { + result = EntityUtils.toString(entity, Charsets.UTF_8); + } + EntityUtils.consume(entity); + return result; + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } finally { + response.close(); + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } finally { + // 关闭连接,释放资源 + if (httpClient != null) { + try { + httpClient.close(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } + } + } + + /** + * HTTP Post 获取内容 + * + * @param url 请求的url地址 ?之前的地址 + * @param params 请求的参数 + * @param charset 编码格式 + * @return 响应结果 + */ + public static String doPost(String url, Map params, String charset, String projectFlag) { + Args.notNull(url, "请求目标url"); + try { + List pairs = null; + if (params != null && !params.isEmpty()) { + pairs = new ArrayList(params.size()); + for (Map.Entry entry : params.entrySet()) { + String value = (String) entry.getValue(); + if (value != null) { + pairs.add(new BasicNameValuePair(entry.getKey(), value)); + } + } + } + HttpPost httpPost = new HttpPost(url); + if (pairs != null && pairs.size() > 0) { + httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET)); + } + RequestConfig config = RequestConfig.custom().setConnectTimeout(30000).setSocketTimeout(60000).build();// timeunit + // : + // seconds + httpClient = createClient(config, projectFlag);// 创建 client + CloseableHttpResponse response = httpClient.execute(httpPost); + try { + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != 200) { + httpPost.abort(); + throw new RuntimeException("HttpClient,error status code :" + statusCode); + } + HttpEntity entity = response.getEntity(); + String result = null; + if (entity != null) { + result = EntityUtils.toString(entity, Charsets.UTF_8); + } + EntityUtils.consume(entity); + return result; + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } finally { + response.close(); + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } finally { + // 关闭连接,释放资源 + if (httpClient != null) { + try { + httpClient.close(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } + } + } + + /** + * + * 获取带证书的安全client + * + * @param config 请求参数 + * @return + */ + private static CloseableHttpClient createClient(RequestConfig config, String projectFlag) { + String certFile = WeixinPayConfig.CERT_FILE; + String mchId = WeixinPayConfig.MCHID; + CloseableHttpClient httpclient = null; + try { + // 指定读取证书格式为PKCS12 + KeyStore keyStore = KeyStore.getInstance(CEART_MODE); + // 读取本机存放的PKCS12证书文件 + FileInputStream instream = new FileInputStream(new File(certFile)); +// InputStream instream = FsClientWithCertSSL.class.getResourceAsStream(CERT); + try { + // 指定PKCS12的密码(商户ID) + keyStore.load(instream, mchId.toCharArray()); + } catch (CertificateException e) { + e.printStackTrace(); + } finally { + instream.close(); + } + // 相信自己的CA和所有自签名的证书 + // SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keyStore, new + // TrustSelfSignedStrategy()).build(); + // Trust own CA and all self-signed certs 加上密钥 + SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build(); + // Allow TLSv1 protocol only 指定TLS版本 (IETF Internet Enginnering TaskForce ) + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, // TLSv1 + // 等于 + // SSLv3 + null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + // 设置httpclient的SSLSocketFactory + httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(config) + // .setConnectionManager(connManager) + .build(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } + return httpclient; + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/MD5Util.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/MD5Util.java new file mode 100644 index 0000000..9c39da8 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/MD5Util.java @@ -0,0 +1,43 @@ +package com.md.demo.pay.utils; + +import java.security.MessageDigest; + +/** + * MD5工具 + */ +public class MD5Util { + + 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; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (charsetname == null || "".equals(charsetname)) + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + else + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } catch (Exception exception) { + } + return resultString; + } + + private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", + "e", "f" }; +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/MapUtils.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/MapUtils.java new file mode 100644 index 0000000..ed6c47e --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/MapUtils.java @@ -0,0 +1,74 @@ +package com.md.demo.pay.utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +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; + +/** + * 对map的key进行ASCII排序 + */ +public class MapUtils { + + /** + * 对map根据key进行排序 ASCII 顺序 + * + * @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 (o1.getKey()).toString().compareTo(o2.getKey()); + } + }); + // 排序后 + SortedMap sortmap = new TreeMap(); + System.out.println("根据key进行排序ASCII顺序,infoIds=" + infoIds.toString()); + for (int i = 0; i < infoIds.size(); i++) { + String[] split = infoIds.get(i).toString().split("="); + sortmap.put(split[0], split[1]); + } + return sortmap; + } + + /** + * map to String + * + * @param map + * @return + */ + public static String toString(Map map) { + StringBuffer buf = new StringBuffer(); + buf.append("{"); + Iterator> i = map.entrySet().iterator(); + boolean hasNext = i.hasNext(); + while (hasNext) { + Entry e = i.next(); + Object key = e.getKey(); + Object value = e.getValue(); + if (key == MapUtils.class) + buf.append("(this Map)"); + else + buf.append(key); + buf.append("="); + if (value == MapUtils.class) + buf.append("(this Map)"); + else + buf.append(value); + hasNext = i.hasNext(); + if (hasNext) + buf.append(", "); + } + buf.append("}"); + return buf.toString(); + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/PayCommonUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/PayCommonUtil.java new file mode 100644 index 0000000..abb8647 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/PayCommonUtil.java @@ -0,0 +1,132 @@ +package com.md.demo.pay.utils; + +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.SortedMap; + +import com.md.demo.pay.utils.variation.WeixinPayConfig; + +/** + * 微信支付随机字符串和签名工具 + */ +public class PayCommonUtil { + + /** + * 自定义长度随机字符串 + * + * @param length + * @return + */ + public static String createConceStr(int length) { + String strs = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + String str = ""; + for (int i = 0; i < length; i++) { + char achar = strs.charAt(new Random().nextInt(strs.length() - 1)); + str += achar; + } + return str; + } + + /** + * 默认16 位随机字符串 + * + * @return + */ + public static String CreateNoncestr() { + String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + String res = ""; + for (int i = 0; i < 16; i++) { + Random rd = new Random(); + res += chars.charAt(rd.nextInt(chars.length() - 1)); + } + return res; + } + + /** + * 签名工具 FOR PUBLIBC + * + * @param characterEncoding + * @param parameters + * @return + */ + public static String createSignPublic(String characterEncoding, Map parameters, + String projectFlag) { + String keyWechat = WeixinPayConfig.KEY; + 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) && !"key".equals(key)) { + sb.append(key + "=" + value + "&"); + } + } + sb.append("key=" + keyWechat); + // 注意sign转为大写 + return MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); + } + + /** + * 签名工具 不含商户密钥 -暂时不用 + * + * @param characterEncoding 编码格式 UTF-8 + * @param parameters + * @return + */ + public static String createSignNoKey(String characterEncoding, Map parameters) { + 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) && !"key".equals(key)) { + sb.append(key + "=" + value + "&"); + } + } + String signStr = sb.toString(); + String subStr = signStr.substring(0, signStr.length() - 1); + // 注意sign转为大写 + return MD5Util.MD5Encode(subStr, characterEncoding).toUpperCase(); + } + + /** + * @date + * @Description:将请求参数转换为xml格式的string + * @param parameters 请求参数 + * @return + */ + public static String getRequestXml(SortedMap parameters) { + StringBuffer sb = new StringBuffer(); + sb.append(""); + Iterator> iterator = parameters.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator.next(); + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) { + sb.append("<" + key + ">" + ""); + } else { + sb.append("<" + key + ">" + value + ""); + } + } + sb.append(""); + return sb.toString(); + } + + /** + * @date + * @Description:返回给微信的参数 + * @param return_code 返回编码 + * @param return_msg 返回信息 + * @return + */ + public static String setXML(String return_code, String return_msg) { + return ""; + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/StrUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/StrUtil.java new file mode 100644 index 0000000..094c8d2 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/StrUtil.java @@ -0,0 +1,355 @@ +package com.md.demo.pay.utils; + +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-wechat-pay/src/main/java/com/md/demo/pay/utils/XMLUtil.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/XMLUtil.java new file mode 100644 index 0000000..e97c6fe --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/XMLUtil.java @@ -0,0 +1,85 @@ +package com.md.demo.pay.utils; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; + +/** + * XML解析工具 + */ +@SuppressWarnings("all") +public class XMLUtil { + + /** + * 解析xml,返回第一级元素键值对。 如果第一级元素有子节点, 则此节点的值是子节点的xml数据。 + * + * @param strxml + * @return + * @throws JDOMException + * @throws IOException + */ + public static SortedMap doXMLParse(String strxml) throws JDOMException, IOException { + strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); + if (null == strxml || "".equals(strxml)) { + return null; + } + SortedMap map = new TreeMap(); + InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8")); + SAXBuilder builder = new SAXBuilder(); + Document doc = builder.build(in); + Element root = doc.getRootElement(); + List list = root.getChildren(); + Iterator it = list.iterator(); + while (it.hasNext()) { + Element e = (Element) it.next(); + String key = e.getName(); + String value = ""; + List children = e.getChildren(); + if (children.isEmpty()) { + value = e.getTextNormalize(); + } else { + value = XMLUtil.getChildrenText(children); + } + map.put(key, value); + } + // 关闭流 + in.close(); + return map; + } + + /** + * 获取子结点的xml + * + * @param children + * @return + */ + public static String getChildrenText(List children) { + StringBuffer sb = new StringBuffer(); + if (!children.isEmpty()) { + Iterator it = children.iterator(); + while (it.hasNext()) { + Element e = (Element) it.next(); + String name = e.getName(); + String value = e.getTextNormalize(); + List list = e.getChildren(); + sb.append("<" + name + ">"); + if (!list.isEmpty()) { + sb.append(XMLUtil.getChildrenText(list)); + } + sb.append(value); + sb.append(""); + } + } + return sb.toString(); + } + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/PayServiceUtils.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/PayServiceUtils.java new file mode 100644 index 0000000..6a888e6 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/PayServiceUtils.java @@ -0,0 +1,275 @@ +package com.md.demo.pay.utils.variation; + +import java.net.InetAddress; +import java.util.Collections; +import java.util.Map; +import java.util.SortedMap; + +import com.google.common.base.Charsets; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.md.demo.pay.utils.ConfigUtil; +import com.md.demo.pay.utils.FsClientWithCertSSL; +import com.md.demo.pay.utils.MapUtils; +import com.md.demo.pay.utils.PayCommonUtil; +import com.md.demo.pay.utils.StrUtil; +import com.md.demo.pay.utils.XMLUtil; +import com.md.demo.pay.utils.vo.PayWithdrawHis; + +import lombok.extern.slf4j.Slf4j; + +/** + * 支付服务工具类 + * + * @author Minbo + * + */ +@Slf4j +public class PayServiceUtils { + + /** + * 打款 + */ + public static int doEpay(String appId, String openId, String ip, String amount, String orderId, String re_user_name, + PayWithdrawHis objInfo, String projectFlag, String appIdName) { + if (Strings.isNullOrEmpty(orderId) || Strings.isNullOrEmpty(openId)) { + log.info("企业支付开始,openid: " + openId + " orderId: " + orderId); + return 1; + } + + int amountInt = Integer.valueOf(amount).intValue(); + if (amountInt < 100 || Strings.isNullOrEmpty(amount)) { + log.warn("企业支付开始=> 金额不得少于100分(1元)"); + return 2; + } + + try { + if (Strings.isNullOrEmpty(ip)) { + InetAddress addr = InetAddress.getLocalHost(); + ip = addr.getHostAddress().toString(); + } + log.info("企业支付开始,用户:" + openId + " 订单号:" + orderId + " 金额:" + amount + ", ip=" + ip); + + // 设置支付参数 + SortedMap parameters = getSignParams(appId, orderId, openId, amountInt, ip, re_user_name, + projectFlag, appIdName); + parameters.put("sign", PayCommonUtil.createSignPublic(Charsets.UTF_8.toString(), parameters, projectFlag));// sign签名 + String requestXML = PayCommonUtil.getRequestXml(parameters);// 生成xml格式字符串 + String responseStr = FsClientWithCertSSL.doPost(ConfigUtil.PROMOTION_URL, requestXML, projectFlag); + + // 解析结果 + Map resutlMap = XMLUtil.doXMLParse(responseStr); + log.info("企业付款,微信返回结果:resutlMap=" + resutlMap.toString()); + + // 校验响应结果return_code + if (resutlMap != null && WeixinConstant.FAIL.equalsIgnoreCase(resutlMap.get("return_code").toString())) { + log.error("企业支付调用失败"); + return 3; + } + if (StrUtil.null2Str(resutlMap.get("err_code")).equals("SENDNUM_LIMIT")) { + return 66; + } + if (StrUtil.null2Str(resutlMap.get("err_code")).equals("NOTENOUGH")) { + return 99; + } + if (StrUtil.null2Str(resutlMap.get("err_code")).equals("SYSTEMERROR") + && StrUtil.null2Str(resutlMap.get("err_code_des")).equals("系统繁忙,请稍后再试")) { + return 77; + } + if (StrUtil.null2Str(resutlMap.get("err_code")).equals("SYSTEMERROR")) { + return 88; + } + + if (resutlMap != null && WeixinConstant.FAIL.equals(resutlMap.get("result_code"))) { + log.error("企业付款失败:orderId=" + orderId + ",失败原因:return_msg=" + resutlMap.get("return_msg") + "," + + objInfo.toString()); + // 真实姓名不一致 + // 非实名用户账号不可发放 + // 用户账号被冻结,无法付款 + if (StrUtil.null2Str(resutlMap.get("err_code")).equals("NAME_MISMATCH") + || StrUtil.null2Str(resutlMap.get("err_code")).equals("V2_ACCOUNT_SIMPLE_BAN") + || StrUtil.null2Str(resutlMap.get("err_code")).equals("NO_AUTH")) { + if (objInfo != null) { + objInfo.setFailErrorMsg( + resutlMap.get("err_code").toString() + ":" + resutlMap.get("err_code_des").toString()); + objInfo.setOrderStatusName("提现失败,金币已返还--" + resutlMap.get("err_code_des").toString()); + return 4; + } + + // 参数错误 + } else if (StrUtil.null2Str(resutlMap.get("err_code")).equals("PARAM_ERROR")) { + if (objInfo != null) { + objInfo.setFailErrorMsg( + resutlMap.get("err_code").toString() + ":" + resutlMap.get("err_code_des").toString()); + objInfo.setOrderStatusName("提现失败,金币已返还--" + "支付失败,请重新申请"); + return 4; + } + } + + String return_msg = resutlMap.get("return_msg").toString(); + if (return_msg.equals("openid与商户appid不匹配")) { + log.error("提现失败【准备重试】,openid与商户appid不匹配。" + objInfo.toString()); + return 44; + } + return 55; + } + + if (WeixinConstant.SUCCESS.equalsIgnoreCase(resutlMap.get("result_code").toString())) { + Map map = buildClientJson(resutlMap); + log.info("企业付款成功:" + map.toString()); + return 0; + } + + } catch (Exception e) { + log.error("企业付款异常:" + e.getMessage(), e); + return 5; + } + return 1; + } + + /** + * 查询指定订单id状态 + */ + public static int doEquery(String appId, String outOrderNo, String projectFlag) { + if (Strings.isNullOrEmpty(outOrderNo)) { + return 1; + } + try { + // 组装查询参数 + SortedMap params = buildQueryParams(appId, outOrderNo, projectFlag); + String requestXML = PayCommonUtil.getRequestXml(params);// 生成xml格式字符串 + // 带上post请求支付查询接口 + String responseStr = FsClientWithCertSSL.doPost(ConfigUtil.PROMOTION_QUERY_URL, requestXML, projectFlag); + SortedMap responseMap = XMLUtil.doXMLParse(responseStr);// 解析响应xml格式字符串 + log.info("企业付款查询=> " + responseMap.toString()); + + // 校验响应结果return_code + if (WeixinConstant.FAIL.equalsIgnoreCase(responseMap.get("return_code").toString())) { + log.error("企业支付调用失败"); + return 2; + } + + // 校验业务结果result_code + if (WeixinConstant.FAIL.equalsIgnoreCase(responseMap.get("result_code").toString())) { + if ("NOT_FOUND".equalsIgnoreCase(responseMap.get("err_code").toString())) { + log.info("指定单号数据不存在,放行打款..."); + return 4; + } + return 3; + } + + if (StrUtil.null2Str(responseMap.get("err_code")).equals("SYSTEMERROR") + && StrUtil.null2Str(responseMap.get("status")).equals("PROCESSING")) { + // 扣款消耗失败,退回提现 + if (StrUtil.null2Str(responseMap.get("reason")).equals("consumefund failed.") + && StrUtil.null2Str(responseMap.get("return_msg")).equals("consumefund failed.")) { + log.error("扣款消耗失败,consumefund failed,退回提现"); + return 99; + } + return 77; + } + + if (StrUtil.null2Str(responseMap.get("err_code")).equals("SYSTEMERROR")) { + return 88; + } + + if (WeixinConstant.SUCCESS.equalsIgnoreCase(responseMap.get("result_code").toString())) { + log.error("已打款,不能重复打款"); + return 0; + } + + // 组装响应数据 + Map resultMap = PayServiceUtils.buildResponse(responseMap); + log.info("企业付款查询结果:" + resultMap.toString()); + return -1; + + } catch (Exception e) { + log.error("付款查询异常:" + e.getMessage(), e); + return 5; + } + } + + /** + * 组装响应数据 + * + * @param resutlMap 付款响应结果 + * @return + */ + private static Map buildClientJson(Map resutlMap) { + + if (resutlMap == null || resutlMap.isEmpty()) { + return Collections.emptyMap(); + } + Map returnMap = ImmutableMap.builder() + .put("trade_no", resutlMap.get("partner_trade_no")).put("payment_no", resutlMap.get("payment_no")) + .put("payment_time", resutlMap.get("payment_time")).put("result_msg", resutlMap.get("result_code")) + .build(); + return returnMap; + } + + /** + * 组合sign签名参数 + * + * @return + */ + private static SortedMap getSignParams(String appId, String tradeNo, String openId, int amount, + String ip, String re_user_name, String projectFlag, String appDesc) { +// String appId = WeixinPayConfig.APPID; + String mchId = WeixinPayConfig.MCHID; + Map oparams = ImmutableMap.builder().put("mch_appid", appId) +// .put("desc", WeixinConstant.EPAY_DESC) + .put("desc", appDesc) + // 企业付款描述信息 + .put("mchid", mchId) + // 商户号 + .put("nonce_str", PayCommonUtil.CreateNoncestr()) + // 16随机字符串(大小写字母加数字) + .put("device_info", PayCommonUtil.createConceStr(32).toUpperCase())// 设备号 暂时写死 + .put("partner_trade_no", tradeNo)// 商户订单号 + .put("openid", openId)// 用户openid 注意:微信的openid + .put("check_name", "NO_CHECK")// 不校验真实姓名 +// .put("check_name", "FORCE_CHECK")// 校验真实姓名 +// .put("re_user_name", re_user_name)// 校验真实姓名 + .put("amount", amount)// 金额 + .put("spbill_create_ip", ip)// ip地址 + .build(); + return MapUtils.sortMap(oparams); + } + + /** + * 封装查询结果数据 + * + * @param responseMap 查询结果 + * @return + */ + private static Map buildResponse(SortedMap responseMap) { + Map returnMap = ImmutableMap.builder() + .put("trade_no", responseMap.get("partner_trade_no")).put("payment_no", responseMap.get("detail_id")) + .put("payment_account", responseMap.get("payment_amount")) + .put("transfer_time", responseMap.get("transfer_time")) + .put("result_code", responseMap.get("result_code")).build(); + return returnMap; + } + + /** + * 组装查询参数 + * + * @param outTradeNo + * @return + */ + private static SortedMap buildQueryParams(String appId, String outTradeNo, String projectFlag) { + String mchId = WeixinPayConfig.MCHID; + // 组装查询参数- 可以使用treemap + Map queryParams = ImmutableMap.builder().put("appid", appId)// 商户号的appid + .put("mch_id", mchId)// 商户号 + .put("nonce_str", PayCommonUtil.CreateNoncestr())// 16随机字符串(大小写字母加数字) + .put("partner_trade_no", outTradeNo)// 商户订单号 + .build(); + // key ASCII 排序 + SortedMap sortMap = MapUtils.sortMap(queryParams); + // MD5签名 + String createSign = PayCommonUtil.createSignPublic(Charsets.UTF_8.toString(), sortMap, projectFlag); + sortMap.put("sign", createSign); + return sortMap; + } +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/WeixinConstant.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/WeixinConstant.java new file mode 100644 index 0000000..d9f52b0 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/WeixinConstant.java @@ -0,0 +1,13 @@ +package com.md.demo.pay.utils.variation; + +/** + * 微信支付常量类 + */ +public class WeixinConstant { + + public static String SUCCESS = "SUCCESS"; // 成功return_code + + public static String FAIL = "FAIL"; // 失败return_code + +// public static String EPAY_DESC = "申请提现转账";// 企业付款描述 +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/WeixinPayConfig.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/WeixinPayConfig.java new file mode 100644 index 0000000..a1f1789 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/variation/WeixinPayConfig.java @@ -0,0 +1,20 @@ +package com.md.demo.pay.utils.variation; + +/** + * 微信公众号支付配置信息 + */ +public class WeixinPayConfig { + +// // APPID(可固化,也可以动态变,DB中可同时记录AppID) +// public final static String APPID = "xxxxxx"; + + // 公众平台商户ID + public final static String MCHID = "xxxxxx"; + + // 公众平台商户KEY + public final static String KEY = "xxxxxx"; + + // 微信企业支付证书 + public static String CERT_FILE = System.getProperty("user.dir") + System.getProperty("file.separator") + "cert" + + System.getProperty("file.separator") + "apiclient_cert.p12"; +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/vo/PayWithdrawHis.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/vo/PayWithdrawHis.java new file mode 100644 index 0000000..13f207d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/pay/utils/vo/PayWithdrawHis.java @@ -0,0 +1,56 @@ +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 = "系统用户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 = "微信openID") + private String wechatOpenId; + + @ApiModelProperty(value = "提现完成时间") + private Date finishedTime; + + @ApiModelProperty(value = "提现失败原因") + private String failErrorMsg; + +} diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/rest/InitRest.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/rest/InitRest.java new file mode 100644 index 0000000..36426c7 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay"; + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/service/IWechatPayService.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/service/IWechatPayService.java new file mode 100644 index 0000000..04fb731 --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/service/IWechatPayService.java @@ -0,0 +1,16 @@ +package com.md.demo.service; + +/** + *

    + * 微信支付打款服务 + *

    + * + * @author minbo + */ +public interface IWechatPayService { + + /** + * 微信批量打款 + */ + public void wechatBatchPay(); +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/service/impl/WechatPayServiceImpl.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/service/impl/WechatPayServiceImpl.java new file mode 100644 index 0000000..be4759a --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/service/impl/WechatPayServiceImpl.java @@ -0,0 +1,272 @@ +package com.md.demo.service.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.md.demo.pay.utils.StrUtil; +import com.md.demo.pay.utils.variation.PayServiceUtils; +import com.md.demo.pay.utils.vo.PayWithdrawHis; +import com.md.demo.service.IWechatPayService; + +import lombok.extern.slf4j.Slf4j; + +/** + *

    + * 服务实现类 + *

    + * + * @author minbo + */ +@Service +@Slf4j +public class WechatPayServiceImpl implements IWechatPayService { + + /** + * 悦头条-新版-微信批量打款 + */ + @Override + public void wechatBatchPay() { + + // TODO 这里可从DB中获得订单数据 +// String startDate = DateUtil.getCurrentDate(-7); +// String endDate = DateUtil.getCurrentDateTimeHours(-1); +// List list = +// this.withdrawHisService.listPassWithdrawData(startDate, endDate); + + List list = new ArrayList(); + loopFlag: for (PayWithdrawHis objInfo : list) { + log.info("---------------------------------------------"); + log.info("--------------------start--------------------"); + try { + + // 这里的openId,是当前应用或公众号下的openId + String openId = StrUtil.null2Str(objInfo.getWechatOpenId()); + + String ip = "0.0.0.0"; + // 提现金币,微信官方后台是分为单位,则要乘以100 + String amount = String.valueOf(Integer.valueOf(objInfo.getIncome()) * 100); + // 订单ID + String orderId = objInfo.getOrderId(); + +// // 获得appId的配置,可以把支付信息等做成DB可配置项 +// PayAppConfig sdkPayAppConfig = this.sdkPayAppConfigService.getById(objInfo.getAppId()); +// String appIdName = sdkPayAppConfig.getProductName() + "的红包"; +// String wxAppId = sdkPayAppConfig.getWxAppId(); + + // 企业付款描述 + String appIdName = "填入账信息详情展示"; // 例如:XXX产品的红包 + String wxAppId = "微信后台的appId"; + + // 1. 先查询订单的状态 + int flag = PayServiceUtils.doEquery(wxAppId, orderId, null); + if (flag == 99) { + log.warn("查询,扣款消耗失败,退回打款"); + + // TODO 扣款消耗失败处理 +// objInfo.setFailErrorMsg("微信官方后台-扣款消耗失败"); +// objInfo.setOrderStatusName("提现失败,金币已返还--提现失败,请重新申请"); +// this.updateWithdrawHisForfail(objInfo); + continue; + + } + + if (flag == 88) { + log.error("查询,后台企业微信账户系统异常,停止打款", new RuntimeException("微信账户异常,停止此次打款")); + break loopFlag; + + } + + if (flag == 77) { + log.error("查询,后台企业微信账户系统订单正在处理中", new RuntimeException("微信账户订单正在处理中,跳过处理")); + continue; + + } + + if (flag == 0) { + log.info("之前已经打款成功,直接更新状态即可。"); + // TODO 已打款成功,不重复打款,直接更新状态处理 +// this.updateWithdrawHis(objInfo); + continue; + } + + // 不存在此订单数据,真正开始打款 + if (flag == 4) { + log.info("开始真正打款,然后更新订单状态..."); + int result = PayServiceUtils.doEpay(wxAppId, openId, ip, amount, orderId, null, objInfo, null, + appIdName); + + if (result == 99) { + log.error("打款,后台企业微信账户支付余额不足,停止打款", new RuntimeException("余额不足,停止此次打款")); + break loopFlag; + } + + if (result == 88) { + log.error("打款,后台企业微信账户系统异常,停止打款。" + objInfo.toString(), new RuntimeException("微信账户异常,停止此次打款")); + break loopFlag; + } + + if (result == 77) { + log.error("打款速度过快,微信账户处理繁忙,休眠十秒。" + objInfo.toString()); + Thread.sleep(10000); + continue; + } + + if (result == 66) { + log.error("该用户今日付款次数超过限制,如有需要请登录微信支付商户平台更改API安全配置。", + new RuntimeException("该用户今日付款次数超过限制,跳过该用户的打款")); + continue; + } + + if (result == 55) { + log.error("打款报错【微信】,请检查。" + objInfo.toString(), new RuntimeException("打款报错,跳过该用户打款")); + continue; + } + + // 最后结果处理 + if (result == 0) { + // TODO 打款成功处理 +// this.updateWithdrawHis(objInfo); + + } else if (result == 4) { + // TODO 打款失败处理 +// this.updateWithdrawHisForfail(objInfo); + } + } + } catch (Exception e) { + log.error("提现记录异常:orderId=" + objInfo.getOrderId() + ", msg=" + e.getMessage(), e); + } + log.info("--------------------end--------------------"); + log.info("---------------------------------------------"); + } + } + +// /** +// * 更新提现记录-‘提现成功’状态 +// * +// * @param PayWithdrawHis +// */ +// private void updateWithdrawHis(PayWithdrawHis entity) { +// entity.setOrderStatus(2); +// entity.setOrderStatusName("提现成功"); +// entity.setUpdatedDate(new Date()); +// boolean status = this.withdrawHisService.updateById(entity); +// if (status) { +// log.info("状态更新成功 for 提现成功"); +// +// } else { +// log.error("状态更新失败 for 提现成功"); +// } +// } + +// /** +// * 提现失败处理 +// * +// * @param PayWithdrawHis +// */ +// private boolean updateWithdrawHisForfail(PayWithdrawHis entity) { +// Date cTime = new Date(); +// +// PayUserRedpacketInfo sdkPayUserRedpacketInfo = this.sdkPayUserRedpacketInfoService +// .getById(entity.getSysUserId()); +// if (sdkPayUserRedpacketInfo == null) { +// log.error("用户数据不存在,不允许返还金币,跳过处理。entity={}", JSON.toJSONString(entity)); +// return false; +// } +// +// // 先查订单是否已发放过(奖励历史) +// QueryWrapper queryWrapper = new QueryWrapper(); +// queryWrapper.eq("busId", entity.getOrderId()); +// +// List listOfPayAwardHis = this.sdkPayAwardHisService.list(queryWrapper); +// if (listOfPayAwardHis != null && listOfPayAwardHis.size() > 0) { +// +// log.error("此订单已返还了金币数据,不允许再次返还金币,跳过处理。entity={}", JSON.toJSONString(entity)); +// +// // 直接更新订单状态 +// this.updateOrderStatusForFailById(entity, cTime); +// +// return false; +// } +// +// // 1. 金币需返还 +// Long oldVersion = sdkPayUserRedpacketInfo.getVersion(); +// // 旧值 +// Long oldLeftGold = Long.valueOf(sdkPayUserRedpacketInfo.getLeftGold()); +// // 新值 +// Long newLeftGold = oldLeftGold + Math.abs(Long.valueOf(entity.getGold())); +// +// // 更新用户余额 +// sdkPayUserRedpacketInfo.setLeftGold(String.valueOf(newLeftGold)); +// sdkPayUserRedpacketInfo.setVersion(sdkPayUserRedpacketInfo.getVersion() + 1); +// sdkPayUserRedpacketInfo.setUpdatedDate(cTime); +// +// // 更新条件 +// UpdateWrapper updateWrapper = new UpdateWrapper(); +// updateWrapper.eq("sysUserId", entity.getSysUserId()); +// updateWrapper.eq("version", oldVersion); +// boolean result = this.sdkPayUserRedpacketInfoService.update(sdkPayUserRedpacketInfo, updateWrapper); +// if (!result) { +// log.error("更新用户余额失败,跳过处理。sdkPayUserRedpacketInfo={}", JSON.toJSONString(sdkPayUserRedpacketInfo)); +// return false; +// } +// log.info("金币返还成功, sysUserId={}, oldLeftGold={}, 要返还的gold={}, newLeftGold={}, orderId={}", entity.getSysUserId(), +// oldLeftGold, entity.getGold(), newLeftGold, entity.getOrderId()); +// +// // 2. 记录返还奖励历史 +// boolean result2 = this.addPayAwardHis(sdkPayUserRedpacketInfo, entity, cTime); +// if (result2) { +// // 3. 更新订单状态 +// this.updateOrderStatusForFailById(entity, cTime); +// return true; +// +// } else { +// return false; +// } +// } + +// /** +// * 记录返还奖励历史 +// * +// * @param sdkPayUserRedpacketInfo +// * @param entity +// * @param cTime +// * @return +// */ +// private boolean addPayAwardHis(PayUserRedpacketInfo sdkPayUserRedpacketInfo, PayWithdrawHis entity, +// Date cTime) { +// PayAwardHis sdkPayAwardHis = new PayAwardHis(); +// sdkPayAwardHis.setSysUserId(sdkPayUserRedpacketInfo.getSysUserId()); +// sdkPayAwardHis.setAppId(sdkPayUserRedpacketInfo.getAppId()); +// sdkPayAwardHis.setAppUserId(sdkPayUserRedpacketInfo.getAppUserId()); +// sdkPayAwardHis.setType(99); +// sdkPayAwardHis.setAwardValue(entity.getGold()); +// sdkPayAwardHis.setBusId(entity.getOrderId()); +// sdkPayAwardHis.setCreatedDate(cTime); +// boolean result2 = this.sdkPayAwardHisService.save(sdkPayAwardHis); +// if (!result2) { +// log.error("记录返还奖励历史失败,跳过处理。sdkPayAwardHis={}", JSON.toJSONString(sdkPayAwardHis)); +// return false; +// } +// return true; +// } + +// /** +// * 更新订单状态(失败) +// * +// * @param entity +// * @param cTime +// */ +// private void updateOrderStatusForFailById(PayWithdrawHis entity, Date cTime) { +// entity.setOrderStatus(4); +// entity.setUpdatedDate(cTime); +// boolean status = this.withdrawHisService.updateById(entity); +// if (status) { +// log.info("提现记录状态(for 提现失败),更新success。entity={}", JSON.toJSONString(entity)); +// } else { +// log.error("提现记录状态(fot 提现失败),更新fail。entity={}", JSON.toJSONString(entity)); +// } +// } + +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/task/ScheduledTasks.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/task/ScheduledTasks.java new file mode 100644 index 0000000..b61e37f --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/task/ScheduledTasks.java @@ -0,0 +1,33 @@ +package com.md.demo.task; + +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.service.IWechatPayService; + +@Component +public class ScheduledTasks { + + protected static Logger logger = LoggerFactory.getLogger(ScheduledTasks.class); + + @Autowired + private IWechatPayService wechatEpayService; + + /** + * 每60秒执行一次,从DB中获得订单数据 + */ + @Scheduled(initialDelay = 5000, fixedDelay = 60000) + public void httTaskOfWechatPay() { + logger.info("------------------------------------------------"); + logger.info("============微信打款任务,start==================="); + + // TODO 调用打款服务 +// this.wechatEpayService.wechatBatchPayHtt(); + + logger.info("============微信打款任务,end==================="); + logger.info("------------------------------------------------"); + } +} \ No newline at end of file diff --git a/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/java/com/md/demo/util/JsonResult.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/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-wechat-pay/src/main/java/com/md/demo/util/ResultCode.java b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/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-wechat-pay/src/main/resources/application.yml b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/resources/application.yml new file mode 100644 index 0000000..afef73d --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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-wechat-pay/src/main/resources/logback.xml b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/src/main/resources/logback.xml new file mode 100644 index 0000000..2c26e3b --- /dev/null +++ b/spring-boot2-study/spring-boot2-parent/spring-boot2-wechat-pay/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/src/main/java/com/minbo/springdemo/ids/IdUtils.java b/src/main/java/com/minbo/springdemo/ids/IdUtils.java new file mode 100644 index 0000000..40b14e8 --- /dev/null +++ b/src/main/java/com/minbo/springdemo/ids/IdUtils.java @@ -0,0 +1,46 @@ +package com.minbo.springdemo.ids; + +import java.util.Properties; +import java.util.Random; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +/** + * 分布式唯一主键ID工具类 + * @author Minbo + * + */ +public class IdUtils { + + protected static Logger logger = LoggerFactory.getLogger(IdUtils.class); + + private static IdWorker idWorker; + + static { + //方案1,从配置文件中获取 + Resource resource = new ClassPathResource( + "application.properties"); + Properties p = new Properties(); + try { + p.load(resource.getInputStream()); + Long workerId = Long.valueOf(p.getProperty("worker.id")); + idWorker = new IdWorker(workerId); + logger.info("分布式唯一主键ID工具类,[从配置中参数中获取],workerId=" + workerId); + + } catch (Exception e) { + logger.error("分布式进程id配置文件异常,请检查", new RuntimeException("配置文件异常")); + idWorker = new IdWorker(Long.valueOf(new Random().nextInt(1000) + 1)); + } + } + + public static Long getId(){ + return idWorker.nextId(); + } + + public static void main(String[] args) { + System.out.println(IdUtils.getId()); + } +} \ No newline at end of file diff --git a/src/main/java/com/minbo/springdemo/ids/IdWorker.java b/src/main/java/com/minbo/springdemo/ids/IdWorker.java new file mode 100644 index 0000000..0dd3afa --- /dev/null +++ b/src/main/java/com/minbo/springdemo/ids/IdWorker.java @@ -0,0 +1,75 @@ +package com.minbo.springdemo.ids; + +import java.text.SimpleDateFormat; + +/** + * 全局唯一的ID 工厂 使用的是 Twitter-Snowflake 算法 可以参考 + * http://yuanhsh.iteye.com/blog/2209696 经过测试 在4个线程 同事不间断生产 1000W主键的时候 + * 性能和准确性都能得到保障 每秒能产生26W+的唯一主键 + * workerId值为1~1023之间 + * + * @author Minbo + */ +public class IdWorker { + + final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private final long workerId; + private final static long twepoch = 1361753741828L; + private long sequence = 0L; + private final static long workerIdBits = 10L; + public final long maxWorkerId = -1L ^ -1L << workerIdBits; + private final static long sequenceBits = 12L; + + private final long workerIdShift = sequenceBits; + private final static long timestampLeftShift = sequenceBits + workerIdBits; + public final long sequenceMask = -1L ^ -1L << sequenceBits; + + private long lastTimestamp = -1L; + + public IdWorker(final long workerId) { + super(); + if (workerId > this.maxWorkerId || workerId < 0) { + throw new IllegalArgumentException( + String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId)); + } + this.workerId = workerId; + } + + public synchronized long nextId() { + long timestamp = this.timeGen(); + if (this.lastTimestamp == timestamp) { + this.sequence = (this.sequence + 1) & this.sequenceMask; + if (this.sequence == 0) { + // System.out.println("###########" + sequenceMask); + timestamp = this.tilNextMillis(this.lastTimestamp); + } + } else { + this.sequence = 0; + } + if (timestamp < this.lastTimestamp) { + try { + throw new Exception(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", + this.lastTimestamp - timestamp)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + this.lastTimestamp = timestamp; + long nextId = ((timestamp - twepoch << timestampLeftShift)) | (this.workerId << this.workerIdShift) + | (this.sequence); + return nextId; + } + + private long tilNextMillis(final long lastTimestamp) { + long timestamp = this.timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = this.timeGen(); + } + return timestamp; + } + + private long timeGen() { + return System.currentTimeMillis(); + } +} diff --git a/src/main/java/com/minbo/springdemo/web/rocketmq/AsyncProducer.java b/src/main/java/com/minbo/springdemo/web/rocketmq/AsyncProducer.java new file mode 100644 index 0000000..e5528ee --- /dev/null +++ b/src/main/java/com/minbo/springdemo/web/rocketmq/AsyncProducer.java @@ -0,0 +1,39 @@ +package com.minbo.springdemo.web.rocketmq; + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +public class AsyncProducer { + public static void main(String[] args) throws Exception { + // Instantiate with a producer group name. + DefaultMQProducer producer = new DefaultMQProducer("my_rocket_mq"); + // Specify name server addresses. + producer.setNamesrvAddr("localhost:9876"); + // Launch the instance. + producer.start(); + producer.setRetryTimesWhenSendAsyncFailed(0); + for (int i = 0; i < 100; i++) { + final int index = i; + // Create a message instance, specifying topic, tag and message body. + Message msg = new Message("TopicTest", "TagA", "OrderID188", + "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET)); + producer.send(msg, new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + System.out.printf("%-10d OK %s %n", index, sendResult.getMsgId()); + } + + @Override + public void onException(Throwable e) { + System.out.printf("%-10d Exception %s %n", index, e); + e.printStackTrace(); + } + }, 86400); + } + // Shut down once the producer instance is not longer in use. + producer.shutdown(); + } +} diff --git a/src/main/java/com/minbo/springdemo/web/rocketmq/Consumer.java b/src/main/java/com/minbo/springdemo/web/rocketmq/Consumer.java new file mode 100644 index 0000000..b718d82 --- /dev/null +++ b/src/main/java/com/minbo/springdemo/web/rocketmq/Consumer.java @@ -0,0 +1,42 @@ +package com.minbo.springdemo.web.rocketmq; + +import java.util.List; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.message.MessageExt; + +public class Consumer { + public static void main(String[] args) throws InterruptedException, MQClientException { + + // Instantiate with specified consumer group name. + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my_rocket_mq"); + + // Specify name server addresses. + consumer.setNamesrvAddr("localhost:9876"); + + // Subscribe one more more topics to consume. + consumer.subscribe("TopicTest", "*"); + + // Register callback to execute on arrival of messages fetched from brokers. + consumer.registerMessageListener(new MessageListenerConcurrently() { + + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + //System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); + for (MessageExt msg : msgs) { + System.out.println("消费者消费数据:" + new String(msg.getBody())); + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + + // Launch the consumer instance. + consumer.start(); + + System.out.printf("Consumer Started.%n"); + } +} diff --git a/src/main/java/com/minbo/springdemo/web/rocketmq/OnewayProducer.java b/src/main/java/com/minbo/springdemo/web/rocketmq/OnewayProducer.java new file mode 100644 index 0000000..522defb --- /dev/null +++ b/src/main/java/com/minbo/springdemo/web/rocketmq/OnewayProducer.java @@ -0,0 +1,27 @@ +package com.minbo.springdemo.web.rocketmq; + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +public class OnewayProducer { + public static void main(String[] args) throws Exception { + // Instantiate with a producer group name. + DefaultMQProducer producer = new DefaultMQProducer("my_rocket_mq"); + // Specify name server addresses. + producer.setNamesrvAddr("localhost:9876"); + // Launch the instance. + producer.start(); + for (int i = 0; i < 100; i++) { + // Create a message instance, specifying topic, tag and message body. + Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, + ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + // Call send message to deliver message to one of brokers. + producer.sendOneway(msg); + + } + // Shut down once the producer instance is not longer in use. + producer.shutdown(); + } +} diff --git a/src/main/java/com/minbo/springdemo/web/rocketmq/SyncProducer.java b/src/main/java/com/minbo/springdemo/web/rocketmq/SyncProducer.java new file mode 100644 index 0000000..3dc38d8 --- /dev/null +++ b/src/main/java/com/minbo/springdemo/web/rocketmq/SyncProducer.java @@ -0,0 +1,40 @@ +package com.minbo.springdemo.web.rocketmq; + +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; + +public class SyncProducer { + + public static void main(String[] args) throws Exception { + + try { + // Instantiate with a producer group name. + DefaultMQProducer producer = new DefaultMQProducer("my_rocket_mq"); + + // Specify name server addresses. + producer.setNamesrvAddr("localhost:9876"); + + // Launch the instance. + producer.start(); + + for (int i = 0; i < 10; i++) { + // Create a message instance, specifying topic, tag and message body. + Message msgs = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, + ("Hello My RocketMQ" + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ + ); + // Call send message to deliver message to one of brokers. + SendResult sendResult = producer.send(msgs, 86400); + System.out.printf("%s%n", sendResult); + } + + // Shut down once the producer instance is not longer in use. + producer.shutdown(); + + } catch (Exception e) { + e.printStackTrace(); + } + + } +} diff --git a/src/main/java/com/minbo/springdemo/web/rocketmq/test/Consumer.java b/src/main/java/com/minbo/springdemo/web/rocketmq/test/Consumer.java new file mode 100644 index 0000000..6ae4e96 --- /dev/null +++ b/src/main/java/com/minbo/springdemo/web/rocketmq/test/Consumer.java @@ -0,0 +1,32 @@ +package com.minbo.springdemo.web.rocketmq.test; + +import java.util.List; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.message.MessageExt; + +public class Consumer { + public static void main(String[] args) throws MQClientException { + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test-group"); + + consumer.setNamesrvAddr("localhost:9876"); + consumer.setInstanceName("rmq-instance"); + consumer.subscribe("log-topic", "user-tag"); + + consumer.registerMessageListener(new MessageListenerConcurrently() { + + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + for (MessageExt msg : msgs) { + System.out.println("消费者消费数据:" + new String(msg.getBody())); + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + consumer.start(); + System.out.printf("Consumer Started"); + } +} diff --git a/src/main/java/com/minbo/springdemo/web/rocketmq/test/Producer.java b/src/main/java/com/minbo/springdemo/web/rocketmq/test/Producer.java new file mode 100644 index 0000000..6231967 --- /dev/null +++ b/src/main/java/com/minbo/springdemo/web/rocketmq/test/Producer.java @@ -0,0 +1,61 @@ +package com.minbo.springdemo.web.rocketmq.test; + +import java.io.Serializable; + +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.common.message.Message; + +import com.alibaba.fastjson.JSON; + +public class Producer { + public static void main(String[] args) throws MQClientException { + DefaultMQProducer producer = new DefaultMQProducer("test-group"); + producer.setNamesrvAddr("localhost:9876"); + producer.setInstanceName("rmq-instance"); + producer.start(); + try { + for (int j = 1; j < 100; j++) { + for (int i = 0; i < 5000; i++) { + User user = new User(); + user.setLoginName("abc" + i); + user.setPwd(String.valueOf(i)); + Message message = new Message("log-topic", "user-tag", JSON.toJSONString(user).getBytes()); + System.out.println("生产者发送消息:" + JSON.toJSONString(user)); + producer.send(message, 86400); + } + Thread.sleep(300); + } + + } catch (Exception e) { + e.printStackTrace(); + } + producer.shutdown(); + } + + /** + * 发送用户消息 + */ + static class User implements Serializable { + private static final long serialVersionUID = 1L; + + private String loginName; + private String pwd; + + public String getLoginName() { + return loginName; + } + + public void setLoginName(String loginName) { + this.loginName = loginName; + } + + public String getPwd() { + return pwd; + } + + public void setPwd(String pwd) { + this.pwd = pwd; + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..3f9bd76 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,2 @@ +#share.worker.id +worker.id=100 \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index cb57b4c..64be2a7 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -25,7 +25,7 @@ UTF-8 - +