├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── encodings.xml ├── jarRepositories.xml ├── misc.xml ├── uiDesigner.xml └── vcs.xml ├── LICENSE ├── README.md ├── pom.xml ├── springboot-mybatis-plus ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── springboot │ │ └── all │ │ └── mybatisplus │ │ ├── MyBatisPlusApp.java │ │ ├── MyBatisPlusGenerator.java │ │ ├── config │ │ └── MyBatisPlusConfig.java │ │ ├── controller │ │ └── UserController.java │ │ ├── entity │ │ └── User.java │ │ ├── mapper │ │ └── UserMapper.java │ │ ├── model │ │ └── User.java │ │ ├── plugin │ │ └── MybatisPlusTestPlugin.java │ │ ├── service │ │ ├── UserService.java │ │ └── impl │ │ │ └── UserServiceImpl.java │ │ └── test │ │ └── UserTest.java │ └── resources │ ├── application.yml │ ├── mappers │ └── UserMapper.xml │ └── templates │ └── controller.java.vm ├── springboot-shiro ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── example │ │ └── shiro │ │ ├── ShiroApplication.java │ │ ├── authentication │ │ ├── CustomRealm.java │ │ ├── JwtFilter.java │ │ ├── JwtToken.java │ │ ├── JwtUtil.java │ │ └── ShiroConfig.java │ │ ├── config │ │ ├── CustomRealm.java │ │ ├── ShiroConfig.java │ │ └── ShiroSessionListener.java │ │ ├── controller │ │ ├── ExceptionController.java │ │ ├── IndexController.java │ │ └── LoginController.java │ │ ├── dao │ │ ├── User.java │ │ └── UserOnline.java │ │ └── mock │ │ └── UserMock.java │ └── resources │ ├── application-dev.yml │ ├── application-prod.yml │ ├── application.yml │ └── logback-spring.xml ├── springboot-study ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── example │ │ └── app │ │ ├── Application.java │ │ ├── common │ │ └── CommonPage.java │ │ ├── component │ │ ├── App.java │ │ ├── RedisUtil.java │ │ └── WebLogFilter.java │ │ ├── config │ │ ├── AppConfig.java │ │ ├── GlobalCorsConfig.java │ │ ├── MyBatisConfig.java │ │ └── ThreadPoolConfig.java │ │ ├── controller │ │ ├── ExceptionController.java │ │ ├── HelloController.java │ │ ├── RedisController.java │ │ ├── UserController.java │ │ └── WebController.java │ │ ├── dto │ │ ├── Post.java │ │ └── WebLog.java │ │ ├── mapper │ │ └── UserRoleMapper.java │ │ ├── model │ │ └── UserRole.java │ │ └── service │ │ ├── HelloService.java │ │ └── impl │ │ ├── Hello1ServiceImpl.java │ │ └── HelloServiceImpl.java │ └── resources │ ├── application.yml │ ├── banner.txt │ ├── logback-spring.xml │ ├── mapper │ └── UserRoleMapper.xml │ └── templates │ └── index.html ├── springcloud-hystrix ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── hystrix │ │ ├── HystrixApplication.java │ │ ├── config │ │ └── RestTemplateConfig.java │ │ ├── controller │ │ └── HelloController.java │ │ ├── model │ │ └── User.java │ │ └── service │ │ └── UserService.java │ └── resources │ └── bootstrap.yml ├── springcloud-jaeger ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── jaeger │ │ ├── JaegerApplication.java │ │ └── controller │ │ └── HelloController.java │ └── resources │ └── bootstrap.yml ├── springcloud-nacos ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── nacos │ │ ├── NacosAppication.java │ │ └── controller │ │ └── ConfigController.java │ └── resources │ └── bootstrap.yml ├── springcloud-openfeign ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── openfeign │ │ ├── OpenFeignApplicaiton.java │ │ ├── api │ │ └── OpenFeignService.java │ │ ├── controller │ │ └── HelloController.java │ │ └── model │ │ └── User.java │ └── resources │ └── bootstrap.yml ├── springcloud-rest-consumer ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── rest │ │ └── consumer │ │ ├── ConsumerApplication.java │ │ ├── config │ │ └── RestTemplateConfig.java │ │ ├── controller │ │ └── HelloController.java │ │ └── model │ │ └── User.java │ └── resources │ └── bootstrap.yml ├── springcloud-rest-producer ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── rest │ │ └── producer │ │ ├── ProducerApplication.java │ │ ├── controller │ │ └── HelloController.java │ │ └── model │ │ └── User.java │ └── resources │ └── bootstrap.yml ├── springcloud-ribbon ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── ribbon │ │ ├── RibbonApplication.java │ │ ├── config │ │ └── RestTemplateConfig.java │ │ ├── controller │ │ └── HelloController.java │ │ └── model │ │ └── User.java │ └── resources │ └── bootstrap.yml ├── springcloud-sentinel ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── sentinel │ │ ├── SentinelApplication.java │ │ ├── controller │ │ └── TestController.java │ │ └── service │ │ └── HelloService.java │ └── resources │ └── bootstrap.yml ├── springcloud-zuul ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cloud │ │ └── zuul │ │ ├── ZuulApplication.java │ │ └── filter │ │ ├── ErrorZuulFilter.java │ │ ├── PostZuulFilter.java │ │ └── PreZuulFilter.java │ └── resources │ └── bootstrap.yml └── wx.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | # Build and Release Folders 2 | bin-debug/ 3 | bin-release/ 4 | [Oo]bj/ 5 | [Bb]in/ 6 | 7 | # Other files and folders 8 | .settings/ 9 | 10 | # Executables 11 | *.swf 12 | *.air 13 | *.ipa 14 | *.apk 15 | 16 | # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` 17 | # should NOT be excluded as they contain compiler settings and other important 18 | # information for Eclipse / Flash Builder. 19 | 20 | /logs/** 21 | 22 | */target/** 23 | /.idea/ 24 | 25 | /target/ 26 | /logs/ 27 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 43 | 44 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 13 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 qiuchenglei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # springboot-all 2 | 3 | ## 介绍 4 | 5 | springboot从入门到进阶源码 欢迎star ⭐️ [我的博客(阅读体验较佳)](https://www.qiuchenglei.top) 6 | 7 | ### 基础部分 8 | 9 | - [Springboot入门](https://mp.weixin.qq.com/s/FFgVhS5p6GdgTXlCsbgY6g) 10 | 11 | - [Springboot基础(一)](https://mp.weixin.qq.com/s/5RYdxejXz8n6rVTopPVWzw) 12 | 13 | - [Springboot基础(二)](https://mp.weixin.qq.com/s/EBOntbc5YLWGin56cSE9Cg) 14 | 15 | - [Springboot基础(三)](https://mp.weixin.qq.com/s/GmA1Q4oftlaMq4LVcu8tEA) 16 | 17 | - [Springboot基础(四)](https://mp.weixin.qq.com/s/NADDy2WpaHkb17ypsSu9SA) 18 | 19 | - [Springboot基础(五)](https://mp.weixin.qq.com/s/dfcPjDzbi57aDWyNZCehJw) 20 | 21 | ## 进阶部分 22 | 23 | - [SpringBoot进阶之缓存中间件Redis](https://mp.weixin.qq.com/s/ElCAiPiDmwBJXO_T7zE8_A) 24 | 25 | - [SpringBoot进阶之MyBatis分页插件](https://mp.weixin.qq.com/s/6OSmftWHa7anfWtClHNG_w) 26 | 27 | - [SpringBoot进阶之跨域问题处理(CORS)](https://mp.weixin.qq.com/s/xWCqEEdEkj1NaragcQOh4g) 28 | 29 | - [SpringBoot进阶之日志集成](https://mp.weixin.qq.com/s/d4lNPFxXo3PlL7zMpDd5LQ) 30 | 31 | - [SpringBoot进阶之请求拦截](https://mp.weixin.qq.com/s/JtFTVIguXkCjFLqvFw2Y-w) 32 | 33 | - [SpringBoot进阶之请求拦截](https://mp.weixin.qq.com/s/JtFTVIguXkCjFLqvFw2Y-w) 34 | 35 | - [SpringBoot进阶之事务管理及并发问题](https://mp.weixin.qq.com/s/5Lj5Ui42BMfyK1EP7NqQbA) 36 | 37 | 38 | ## Shiro安全框架整合 39 | 40 | - [SpringBoot进阶之整合Shiro鉴权框架(一)](https://mp.weixin.qq.com/s/WNM0iYcUDEBYo22JBwcCmw) 41 | - [SpringBoot进阶之整合Shiro鉴权框架(二)](https://mp.weixin.qq.com/s/p2kM9ObkhMhsTlPYjvB1lQ) 42 | - [SpringBoot进阶之整合Shiro鉴权框架(三)](https://mp.weixin.qq.com/s/SYOtFsdzZWksu-uJ81yk3w) 43 | - [SpringBoot进阶之整合Shiro鉴权框架(四)](https://mp.weixin.qq.com/s/9BVYhX_Gp8MbIjMz8_iHbg) 44 | - [SpringBoot进阶之整合Shiro鉴权框架(五)](https://mp.weixin.qq.com/s/GNPLxCZtvmfS1GxFmWhOCw) 45 | - [SpringBoot进阶之整合Shiro鉴权框架(六)](https://mp.weixin.qq.com/s/9WvPQbMasWVpQVcLMa6bkQ) 46 | 47 | ## 服务部署 48 | 49 | - [SpringBoot进阶之服务部署)](https://mp.weixin.qq.com/s/FOTDTwNcVlW5yxSpwBf-aA) 50 | 51 | 52 | ## SpringCloud微服务 53 | 54 | - [一起来学SpringCloud之微服务概述](https://mp.weixin.qq.com/s/lL0whlLJWj7gPoxLcD4eHA) 55 | - [一起来学SpringCloud之整合Nacos](https://mp.weixin.qq.com/s/pt4fsGlBczfQa6yh0-MbCA) 56 | - [一起来学SpringCloud之服务间调用](https://mp.weixin.qq.com/s/E0b2RCa45w5q8qCWS4wTzQ) 57 | - [一起来学SpringCloud之整合hystrix服务熔断和降级](https://mp.weixin.qq.com/s/wvw8PdGA9e3S2XwrV_pVgw) 58 | - [一起来学SpringCloud之整合Ribbon](https://mp.weixin.qq.com/s/TR0cgd-qPGLUhX-m13xHhg) 59 | - [一起来学SpringCloud之整合Open Feign实现远程调用](https://mp.weixin.qq.com/s/RGo5_kDxAANWog3vWe8lbg) 60 | - [一起来学SpringCloud之整合Alibaba Sentinel](https://mp.weixin.qq.com/s/Ph-I2C3ukXa1GbehhsNf2A) 61 | - [一起来学SpringCloud之整合Zuul网关服务(一)](https://mp.weixin.qq.com/s/4JdUhEJytR4812Rrr4x38g) 62 | - [一起来学SpringCloud之整合Zuul网关服务(二)](https://mp.weixin.qq.com/s/yEHAGFDgv3tR7ZrbGYPA3Q) 63 | - [一起来学SpringCloud之整合Jaeger链路追踪](https://mp.weixin.qq.com/s/au2e3uXoCRAlEHHnoop2Cw) 64 | - [SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 实现授权码模式的服务认证(一)](https://mp.weixin.qq.com/s/TCHLaTywd2C_oSqUmZL6lw) 65 | - [SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 实现授权码模式的服务认证(二)](https://mp.weixin.qq.com/s/dlX1pXIT19nJWN6pvH3tgw) 66 | 67 | ## Nginx教程相关文章 68 | 69 | - [一起来学Nginx(一)](https://mp.weixin.qq.com/s/5ofPIGLGK7J2QtKF9OGhHA) 70 | - [一起来学Nginx(二)](https://mp.weixin.qq.com/s/tAlqlgd7KqMxdC_jfsNO0w) 71 | - [一起来学Nginx(三)](https://mp.weixin.qq.com/s/Ih1kpoSL4xfabHyoM4cqhw) 72 | 73 | 74 | 75 | 76 | ## 往期Docker教程相关文章 77 | 78 | - [一起来学Docker(一)](https://mp.weixin.qq.com/s/aQ0c_y4fnT5fOb1BjXTYVQ) 79 | - [一起来学Docker(二)](https://mp.weixin.qq.com/s/dqnQGqoQNImcqgncVH_oWQ) 80 | - [一起来学Docker(三)](https://mp.weixin.qq.com/s/rNy_QwvhjBTWJwrVvc8U0Q) 81 | - [一起来学Docker(四)](https://mp.weixin.qq.com/s/IWtCcv8CkDvG851y8ZPdwA) 82 | - [一起来学Docker(五)](https://mp.weixin.qq.com/s/fINh2-SyetERS0-bzcnkMg) 83 | - [一起来学Docker(六)](https://mp.weixin.qq.com/s/6H9rexSfQ3BdRNgaLPriPQ) 84 | - [一起来学Docker(七)](https://mp.weixin.qq.com/s/8FFRNjapHpukaNiC1qw77w) 85 | 86 | ## 往前Shell脚本编程相关文章 87 | 88 | - [一起来学Shell脚本编程(一)](https://mp.weixin.qq.com/s/-_D7PoJwac6YDn9Vn5UF2A) 89 | - [一起来学Shell脚本编程(二)](https://mp.weixin.qq.com/s/vVnL3XT2i_Tdzwkr9mWjKw) 90 | - [一起来学Shell脚本编程(三)](https://mp.weixin.qq.com/s/qh3SqOD2D3wh3km5x6DJTw) 91 | - [一起来学Shell脚本编程(四)](https://mp.weixin.qq.com/s/gCKPssmQf1YIvfVl0jq5oA) 92 | - [一起来学Shell脚本编程(五)](https://mp.weixin.qq.com/s/zSrn7km_DzEZbqa1198BMA) 93 | - [一起来学Shell脚本编程(六)](https://mp.weixin.qq.com/s/9Ek2nDbKMsHYTmTvhMgTJg) 94 | - [一起来学Shell脚本编程(七)](https://mp.weixin.qq.com/s/skLKFKaqQxww-hogbKxpbQ) 95 | 96 | 97 | 98 | ## 往期Linux相关文章 99 | 100 | - [一起来学Linux命令(一)](https://mp.weixin.qq.com/s/sNIck5I2xH1kL5h5pKNDcw) 101 | - [一起来学Linux命令(二)](https://mp.weixin.qq.com/s/oEpoCyqMYG_Y6G3VLNH4Eg) 102 | - [一起来学Linux命令(三)](https://mp.weixin.qq.com/s/k7mGBEqkmh8TM8lXKFNcXg) 103 | - [一起来学Linux命令(四)](https://mp.weixin.qq.com/s/Yv-jrqPmUqIpQU3YtjRxug) 104 | - [一起来学Linux命令(五)](https://mp.weixin.qq.com/s/1rCrU_k9m_N5q4M858palw) 105 | - [一起来学Linux命令(六)](https://mp.weixin.qq.com/s/sBicYQoiBTLudI66qeMijg) 106 | - [一起来学Linux命令(七)](https://mp.weixin.qq.com/s/fc4qpZRW8sr6P_4s7EvXcA) 107 | - [一起来学Linux命令(八)](https://mp.weixin.qq.com/s/n388KavzFimUUT4r_E6IZg) 108 | - [一起来学Linux命令(九)](https://mp.weixin.qq.com/s/WpyWpMjoaUIsMSG0Tnbjcg) 109 | - [一起来学Linux命令(十)](https://mp.weixin.qq.com/s/fdRIDBrG06RtDs1KYw7t9w) 110 | 111 | 112 | ## 往期面试题相关文章 113 | 114 | - [查漏补缺第一期(Redis相关)](https://mp.weixin.qq.com/s/ETAVvqwU3ZkB0MDtQ8hBAg) 115 | - [查漏补缺第二期(synchronized & 锁升级)](https://mp.weixin.qq.com/s/KbVOq7CKza8Pdp1DDPjD5A) 116 | - [查漏补缺第三期(分布式事务相关)](https://mp.weixin.qq.com/s/tejPBx-huaDMYRFeWzH2jA) 117 | - [查漏补缺第四期(Mysql相关)](https://mp.weixin.qq.com/s/DsNWgaPYrgE7QqPgPjuEcA) 118 | - [查漏补缺第五期(HashMap & ConcurrentHashMap)](https://mp.weixin.qq.com/s/4CDkuH2w8Fe0acI-xW-5JA) 119 | - [查漏补缺第六期(京东一面)](https://mp.weixin.qq.com/s/AhQZABtVjIxXs4CVhDaPbg) 120 | - [查漏补缺第七期(美团到店一面)](https://mp.weixin.qq.com/s/jongfptIxQINp6HdrfiGUw) 121 | - [查漏补缺第八期(阿里一面)](https://mp.weixin.qq.com/s/A9mIydMAt_rGM1w9-tYe6A) 122 | - [查漏补缺第九期(阿里二面)](https://mp.weixin.qq.com/s/IJLWdKu4brmfQ2BZgApbtQ) 123 | - [查漏补缺第十期(网易实习一面)](https://mp.weixin.qq.com/s/T1mNDir9y8tcHNXOKQ0nVA) 124 | - [查漏补缺第十一期(网易实习二面)](https://mp.weixin.qq.com/s/kRdF0X_CDPI46GXkMTHquQ) 125 | - [查漏补缺第十二期(网易实习三面)](https://mp.weixin.qq.com/s/Dy7shhrcrBpoZFn8wN17zw) 126 | - [查漏补缺第十三期(滴滴实习一面)](https://mp.weixin.qq.com/s/B6Myjth7nd-ieBtCV7Q0-Q) 127 | - [查漏补缺第十四期(滴滴实习二面)](https://mp.weixin.qq.com/s/G-hmZJDTY0gr4qvrbRBGyg) 128 | - [查漏补缺第十五期(华为一面)](https://mp.weixin.qq.com/s/lio5r9YlX1UKqkeBrZLEeg) 129 | - [查漏补缺第十六期(华为二面)](https://mp.weixin.qq.com/s/7jqkMzY4h5zcWBRQCZOM9A) 130 | - [查漏补缺第十七期(华为三面)](https://mp.weixin.qq.com/s/IvNY9_Iz4uwAoT1vLvjogw) 131 | - [查漏补缺第十八期(你了解class文件吗)](https://mp.weixin.qq.com/s/lLsgqQcNNWJ_Q6xyUywXYw) 132 | 133 | ## 项目源码(源码已更新 欢迎star⭐️) 134 | 135 | - [java-interview-all: https://github.com/qiuChengleiy/java-interview-all](https://github.com/qiuChengleiy/java-interview-all) 136 | 137 | 138 | ## 往期设计模式相关文章 139 | 140 | - [一起来学设计模式之认识设计模式](https://mp.weixin.qq.com/s/1sFPpYKMYyRvKzU0EFse1A) 141 | - [一起来学设计模式之单例模式](https://mp.weixin.qq.com/s/9K6LxQoJs11iBNv9kzbDyQ) 142 | - [一起来学设计模式之工厂模式](https://mp.weixin.qq.com/s/E1ish-KysPsS5hjyzxkTow) 143 | - [一起来学设计模式之建造者模式](https://mp.weixin.qq.com/s/a-rTYNwnZAYPeEQQ0vuoUg) 144 | - [一起来学设计模式之原型模式](https://mp.weixin.qq.com/s/u9hJuZeUFEqyxdj7EP4NLA) 145 | - [一起来学设计模式之适配器模式](https://mp.weixin.qq.com/s/bazzKTQ08Tny4OdrQmaF8w) 146 | - [一起来学设计模式之桥接模式](https://mp.weixin.qq.com/s/jsh5oovdFG8W7PdJ4KQWRQ) 147 | - [一起来学设计模式之组合模式](https://mp.weixin.qq.com/s/Xm0HLLZSuaN6xRBSIu1bUA) 148 | - [一起来学设计模式之装饰器模式](https://mp.weixin.qq.com/s/U-93tjfB4OW0iMdFe0ziUg) 149 | - [一起来学设计模式之外观模式](https://mp.weixin.qq.com/s/9RzFRZT3KA5z4GahV1j6aw) 150 | - [一起来学设计模式之享元模式](https://mp.weixin.qq.com/s/0K0U7cUlgsxSxFJdde8E7A) 151 | - [一起来学设计模式之代理模式](https://mp.weixin.qq.com/s/hBp0fJ83Y9ijSnoraqlyIA) 152 | - [一起来学设计模式之责任链模式](https://mp.weixin.qq.com/s/552JCyXhNcxqOIrVC3OJWQ) 153 | - [一起来学设计模式之命令模式](https://mp.weixin.qq.com/s/9ENTuLqpmwSfUSc9Qe1vqQ) 154 | - [一起来学设计模式之解释器模式](https://mp.weixin.qq.com/s/UMi7GX9dOXYXgaxPCMuKgQ) 155 | - [一起来学设计模式之迭代器模式](https://mp.weixin.qq.com/s/ql_jDSK9LNHWCyhQ6uK6aQ) 156 | - [一起来学设计模式之中介者模式](https://mp.weixin.qq.com/s/_8j1QFYZWTiFEP5qz0rHfw) 157 | - [一起来学设计模式之备忘录模式](https://mp.weixin.qq.com/s/lUiySMrzx2hdmSsHMJPgpA) 158 | - [一起来学设计模式之观察者模式](https://mp.weixin.qq.com/s/THiXHvZG0W-qYU-EjUT1Nw) 159 | - [一起来学设计模式之状态模式](https://mp.weixin.qq.com/s/6k-HQCsGCTBBI9ie3eKk9A) 160 | - [一起来学设计模式之策略模式](https://mp.weixin.qq.com/s/pjbtiLss4TDGsWeXBQGU0A) 161 | - [一起来学设计模式之模板方法模式](https://mp.weixin.qq.com/s/QKWfGkot27sutkDD2-epww) 162 | - [一起来学设计模式之访问者模式](https://mp.weixin.qq.com/s/W8saETmyLRsV6LfvPxSxXQ) 163 | - [一起来学设计模式之依赖注入模式](https://mp.weixin.qq.com/s/tI0JxsgDKIz8Kfd--HcQEg) 164 | 165 | 166 | ## 设计模式项目源码(源码已更新 欢迎star⭐️) 167 | - [java-design-mode-all: https://github.com/qiuChengleiy/java-design-mode-all](https://github.com/qiuChengleiy/java-design-mode-all) 168 | 169 | 170 | ## Kafka 专题学习 171 | 172 | - [一起来学kafka之Kafka集群搭建](https://mp.weixin.qq.com/s/XV2GUwz8mKSNmdI5YWwYVg) 173 | - [一起来学kafka之整合SpringBoot基本使用](https://mp.weixin.qq.com/s/wgE21lrcjEYWP5-2kQeACA) 174 | - [一起来学kafka之整合SpringBoot深入使用(一)](https://mp.weixin.qq.com/s/fI4KNz497qUYueWuOkoUNA) 175 | - [一起来学kafka之整合SpringBoot深入使用(二)](https://mp.weixin.qq.com/s/xLkVTRn2OLcp9hblvw3Xvg) 176 | - [一起来学kafka之整合SpringBoot深入使用(三)](https://mp.weixin.qq.com/s/8iVJ8nyRIpF1gnql1X6yVg) 177 | 178 | ## 项目源码(源码已更新 欢迎star⭐️) 179 | 180 | - [springboot-kafka-all: https://github.com/qiuChengleiy/springboot-kafka-all](https://github.com/qiuChengleiy/springboot-kafka-all) 181 | 182 | ## ElasticSearch 专题学习 183 | 184 | - [利用docker搭建es集群](https://mp.weixin.qq.com/s/Z6HhZWNbmUrp4kRn5EX3FA) 185 | - [一起来学ElasticSearch(一)](https://mp.weixin.qq.com/s/UXDc2mmWlXHhn3R3D0rong) 186 | - [一起来学ElasticSearch(二)](https://mp.weixin.qq.com/s/BBidY95hm1_sGNYYbJT10g) 187 | - [一起来学ElasticSearch(三)](https://mp.weixin.qq.com/s/ItBixu4IN2vrEoFBuTIiMA) 188 | - [一起来学ElasticSearch(四)](https://mp.weixin.qq.com/s/AWEjVAzFS76IDUcuoIJUFw) 189 | - [一起来学ElasticSearch(五)](https://mp.weixin.qq.com/s/3xdqocmPmNRhmVl5C_FIOg) 190 | - [一起来学ElasticSearch(六)](https://mp.weixin.qq.com/s/RJgZCA04v4bzLEbZn-Rc2Q) 191 | - [一起来学ElasticSearch(七)](https://mp.weixin.qq.com/s/bZqDMPg-3yC7dI3hIuOLcA) 192 | - [一起来学ElasticSearch(八)](https://mp.weixin.qq.com/s/JhkCoI6sNTvwlkRmS5psHg) 193 | - [一起来学ElasticSearch(九)](https://mp.weixin.qq.com/s/rABSZhegOdQL7tEvF2bT0g) 194 | - [一起来学ElasticSearch(十)](https://mp.weixin.qq.com/s/rCIoJkVpqcJpDJ0molBaGw) 195 | 196 | - [一起来学ElasticSearch之整合SpringBoot(一)](https://mp.weixin.qq.com/s/Y1wiGPam81iD26KCu2bWKw) 197 | - [一起来学ElasticSearch之整合SpringBoot(二)](https://mp.weixin.qq.com/s/gJ4ueNKr0RqYVe7541gbGA) 198 | - [一起来学ElasticSearch之整合SpringBoot(三)](https://mp.weixin.qq.com/s/ngKMEzZJ59FiR4xnEzz-pA) 199 | 200 | ## 项目源码(源码已更新 欢迎star⭐️) 201 | 202 | - [springboot-es-all: https://github.com/qiuChengleiy/springboot-es-all](https://github.com/qiuChengleiy/springboot-es-all) 203 | 204 | ## 往期并发编程内容推荐 205 | 206 | - [Java多线程专题之线程与进程概述](https://mp.weixin.qq.com/s/PvFx7mm46bsFl94IUWZMUw) 207 | - [Java多线程专题之线程类和接口入门](https://mp.weixin.qq.com/s/Uze3brfNfqMg8eGUqU0lHg) 208 | - [Java多线程专题之进阶学习Thread(含源码分析)](https://mp.weixin.qq.com/s/R9MUmSmEF3HvNAV441rmrw) 209 | - [Java多线程专题之Callable、Future与FutureTask(含源码分析)](https://mp.weixin.qq.com/s/qlKTI3VXBJfypy6XvFo0cg) 210 | - [面试官: 有了解过线程组和线程优先级吗](https://mp.weixin.qq.com/s/obLO_Bmq9Uuy0VuF9z7NeA) 211 | - [面试官: 说一下线程的生命周期过程](https://mp.weixin.qq.com/s/LsyduaUkTdeTaZ3S3phAIw) 212 | - [面试官: 说一下线程间的通信](https://mp.weixin.qq.com/s/oKYUxw01YasA-sMFH8W3GQ) 213 | - [面试官: 说一下Java的共享内存模型](https://mp.weixin.qq.com/s/-n0x_Amt4t4V30IIXj0FnA) 214 | - [面试官: 有了解过指令重排吗,什么是happens-before](https://mp.weixin.qq.com/s/3nGVYKxaavweU40da96OMg) 215 | - [面试官: 有了解过volatile关键字吗 说说看](https://mp.weixin.qq.com/s/uSDAw_X3R7X-f3TvqXDuzg) 216 | - [面试官: 有了解过Synchronized吗 说说看](https://mp.weixin.qq.com/s/pY3A2iWb0derRXY2tx3SiQ) 217 | - [Java多线程专题之Lock锁的使用](https://mp.weixin.qq.com/s/KtS0cnnWQZItcwGKYxJ6pw) 218 | - [面试官: 有了解过ReentrantLock的底层实现吗?说说看](https://mp.weixin.qq.com/s/IErZZadVkqazjvUOibi-eQ) 219 | - [面试官: 有了解过CAS和原子操作吗?说说看](https://mp.weixin.qq.com/s/Waw9C4QHWqOH5nOoHT6sEQ) 220 | - [Java多线程专题之线程池的基本使用](https://mp.weixin.qq.com/s/7PHqofkjX_L4kHU1agTCfg) 221 | - [面试官: 有了解过线程池的工作原理吗?说说看](https://mp.weixin.qq.com/s/mTrV4tr70zT-umtWtyyIiQ) 222 | - [面试官: 线程池是如何做到线程复用的?有了解过吗,说说看](https://mp.weixin.qq.com/s/t1xU4rJFsHjzF9uWkXFjGA) 223 | - [面试官: 阻塞队列有了解过吗?说说看](https://mp.weixin.qq.com/s/SeF4BnGzqg2ossG2fhlU_g) 224 | - [面试官: 阻塞队列的底层实现有了解过吗? 说说看](https://mp.weixin.qq.com/s/zcc10wGeV0AkfH9OUmjL9g) 225 | - [面试官: 同步容器和并发容器有用过吗? 说说看](https://mp.weixin.qq.com/s/4BbePlrfDbyOR7V8TK6nfw) 226 | - [面试官: CopyOnWrite容器有了解过吗? 说说看](https://mp.weixin.qq.com/s/lE0BErDXLIFUGSiM-FWmPg) 227 | - [面试官: Semaphore在项目中有使用过吗?说说看(源码剖析)](https://mp.weixin.qq.com/s/x_q0FQqsmP5ojQF4e6PXAg) 228 | - [面试官: Exchanger在项目中有使用过吗?说说看(源码剖析)](https://mp.weixin.qq.com/s/4Ik4z_8gfzftLDb0FFW6tw) 229 | - [面试官: CountDownLatch有了解过吗?说说看(源码剖析)](https://mp.weixin.qq.com/s/nABrvJ0A5NL0OqF_J6AIlA) 230 | - [面试官: CyclicBarrier有了解过吗?说说看(源码剖析)](https://mp.weixin.qq.com/s/2Zoh3jUYnnL9TTj0kw8q3w) 231 | - [面试官: Phaser有了解过吗?说说看](https://mp.weixin.qq.com/s/rAAc1UH-iP6ox4LpmBJvEQ) 232 | - [面试官: Fork/Join 有了解过吗?说说看(含源码分析)](https://mp.weixin.qq.com/s/YESb3PH12jHAn8HSs_yQ9g) 233 | - [面试官: Stream并行流有了解过吗?说说看](https://mp.weixin.qq.com/s/Nmexsl9RrHZudRBrU0b1FA) 234 | 235 | ## Mybatis Plus 236 | 237 | - [一起来学Mybatis Plus(一)](https://mp.weixin.qq.com/s/3vT6H0XHrJv3RJ8oJNhAIg) 238 | - [一起来学Mybatis Plus(二) & 内置注解](https://mp.weixin.qq.com/s/8ovZuZIFyszrUzZhVc7m1w) 239 | - [一起来学Mybatis Plus(三) & 代码生成器](https://mp.weixin.qq.com/s/OlcmQbNeQKRmC7KN8ekj3A) 240 | - [一起来学Mybatis Plus(四) & Service CRUD接口](https://mp.weixin.qq.com/s/y5fNOaJtC9X5KuIcBtOfOg) 241 | - [一起来学Mybatis Plus(五) & Mapper CRUD接口](https://mp.weixin.qq.com/s/mjalFZ8K5xclF5XVMP7D3A) 242 | - [一起来学Mybatis Plus(六) & 条件构造器](https://mp.weixin.qq.com/s/FOGRmtl280K-LUcruPu1hQ) 243 | - [一起来学Mybatis Plus(七) & 主键策略](https://mp.weixin.qq.com/s/cGU13x6QaeY-jFvzQo6Pkw) 244 | 245 | 246 | ## 公众号 247 | 248 | 关注可以获取Java八股文面试资料哦~ 249 | 250 | ![](./wx.jpg) 251 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | springboot-all 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | springboot-mybatis-plus 24 | 25 | 26 | 27 | 8 28 | 8 29 | 2.5.1 30 | Hoxton.SR3 31 | 2.2.1.RELEASE 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-parent 38 | 2.5.1 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-dependencies 47 | ${spring.cloud.version} 48 | pom 49 | import 50 | 51 | 52 | com.alibaba.cloud 53 | spring-cloud-alibaba-dependencies 54 | ${spring.cloud.alibaba.version} 55 | pom 56 | import 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-starter-web 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-configuration-processor 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | org.projectlombok 115 | lombok 116 | true 117 | 118 | 119 | 120 | 121 | cn.hutool 122 | hutool-all 123 | 4.5.7 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | org.apache.commons 148 | commons-lang3 149 | 150 | 151 | 152 | org.projectlombok 153 | lombok 154 | 1.18.22 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | org.springframework.boot 164 | spring-boot-maven-plugin 165 | 2.5.1 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | dev 174 | 175 | 176 | true 177 | 178 | 179 | 180 | dev 181 | 182 | 183 | 184 | 185 | 186 | prod 187 | 188 | prod 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springboot-mybatis-plus 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-test 23 | test 24 | 25 | 26 | com.baomidou 27 | mybatis-plus-boot-starter 28 | 3.5.4.1 29 | 30 | 31 | org.apache.velocity 32 | velocity-engine-core 33 | 2.3 34 | 35 | 36 | com.baomidou 37 | mybatis-plus-generator 38 | 3.5.3 39 | 40 | 41 | 42 | com.alibaba 43 | druid-spring-boot-starter 44 | 1.1.10 45 | 46 | 47 | 48 | mysql 49 | mysql-connector-java 50 | 51 | 52 | junit 53 | junit 54 | 55 | 56 | org.springframework 57 | spring-test 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-test 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/MyBatisPlusApp.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @Author qcl 8 | * @Description 9 | * @Date 11:05 AM 12/4/2023 10 | */ 11 | @SpringBootApplication 12 | public class MyBatisPlusApp { 13 | public static void main(String[] args) { 14 | SpringApplication.run(MyBatisPlusApp.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/MyBatisPlusGenerator.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus; 2 | 3 | import com.baomidou.mybatisplus.generator.FastAutoGenerator; 4 | import com.baomidou.mybatisplus.generator.config.OutputFile; 5 | import com.baomidou.mybatisplus.generator.config.TemplateType; 6 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; 7 | import org.junit.Test; 8 | 9 | import java.util.Collections; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * @Author qcl 15 | * @Description 16 | * @Date 4:39 PM 12/14/2023 17 | */ 18 | public class MyBatisPlusGenerator { 19 | 20 | public Map getPackageInfo() { 21 | HashMap map = new HashMap<>(); 22 | map.put("packageName", "com.springboot.all.mybatisplus"); 23 | map.put("upperClassName", "User"); 24 | map.put("lowerClassName", "user"); 25 | return map; 26 | } 27 | 28 | @Test 29 | public void generate() { 30 | FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&useUnicode=true&useSSL=false", "root", "qcl123456") 31 | // 全局配置 32 | .globalConfig(builder -> { 33 | builder.author("pkq") // 设置作者 34 | .commentDate("yyyy-MM-dd hh:mm:ss") //注释日期 35 | .outputDir("./src/main/java") // 指定输出目录 36 | .disableOpenDir() //禁止打开输出目录,默认打开 37 | ; 38 | }) 39 | // 包配置 40 | .packageConfig(builder -> { 41 | builder.parent("com.springboot.all.mybatisplus") // 设置父包名 42 | .pathInfo(Collections.singletonMap(OutputFile.xml, "./src/main/resources/mappers")); // 设置mapperXml生成路径 43 | }) 44 | .templateConfig(builder -> { 45 | builder.disable(TemplateType.ENTITY).controller("/templates/controller.java").build(); 46 | }) 47 | .injectionConfig(builder -> { 48 | builder.customMap(getPackageInfo()).build(); 49 | }) 50 | // 策略配置 51 | .strategyConfig(builder -> { 52 | builder.addInclude("user") // 设置需要生成的表名 53 | .addTablePrefix("sys_") // 设置过滤表前缀 54 | // Entity 策略配置 55 | .entityBuilder() 56 | .enableLombok() //开启 Lombok 57 | .enableFileOverride() // 覆盖已生成文件 58 | .naming(NamingStrategy.underline_to_camel) //数据库表映射到实体的命名策略:下划线转驼峰命 59 | .columnNaming(NamingStrategy.underline_to_camel) //数据库表字段映射到实体的命名策略:下划线转驼峰命 60 | // Mapper 策略配置 61 | .mapperBuilder() 62 | .enableFileOverride() // 覆盖已生成文件 63 | // Service 策略配置 64 | .serviceBuilder() 65 | .enableFileOverride() // 覆盖已生成文件 66 | .formatServiceFileName("%sService") //格式化 service 接口文件名称,%s进行匹配表名,如 UserService 67 | .formatServiceImplFileName("%sServiceImpl") //格式化 service 实现类文件名称,%s进行匹配表名,如 UserServiceImpl 68 | // Controller 策略配置 69 | .controllerBuilder() 70 | .enableFileOverride() // 覆盖已生成文件 71 | ; 72 | }) 73 | .execute(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/config/MyBatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.config; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; 6 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 7 | import com.springboot.all.mybatisplus.plugin.MybatisPlusTestPlugin; 8 | import org.mybatis.spring.annotation.MapperScan; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.transaction.annotation.EnableTransactionManagement; 12 | 13 | /** 14 | * @Author qcl 15 | * @Description 16 | * @Date 11:07 AM 12/4/2023 17 | */ 18 | @EnableTransactionManagement 19 | @Configuration 20 | @MapperScan("com.springboot.all.mybatisplus.mapper") 21 | public class MyBatisPlusConfig { 22 | 23 | @Bean 24 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 25 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 26 | // 注册乐观锁插件 27 | interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); 28 | // 注入分页插件 29 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); 30 | // 注入自定义插件 31 | interceptor.addInnerInterceptor(new MybatisPlusTestPlugin()); 32 | return interceptor; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.controller; 2 | 3 | import cn.hutool.json.JSONObject; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; 6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 7 | import com.springboot.all.mybatisplus.entity.User; 8 | import com.springboot.all.mybatisplus.mapper.UserMapper; 9 | import com.springboot.all.mybatisplus.service.UserService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.ResponseBody; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | 21 | @RestController 22 | @RequestMapping("/user") 23 | public class UserController { 24 | 25 | @Autowired 26 | private UserService userService; 27 | 28 | @Autowired 29 | private UserMapper userMapper; 30 | 31 | @GetMapping("/all") 32 | @ResponseBody 33 | public List getUserList() { 34 | QueryWrapper queryWrapper = new QueryWrapper(); 35 | queryWrapper.like("name", "x"); 36 | List userList = userMapper.selectList(queryWrapper); 37 | return userList; 38 | } 39 | 40 | @GetMapping("/save") 41 | @ResponseBody 42 | public void saveUser() { 43 | // User user = new User(); 44 | // user.setName("小明"); 45 | // user.setAge(18); 46 | // user.setVersion(1); 47 | // userService.save(user); 48 | 49 | // User user1 = new User(); 50 | // user1.setName("小明1"); 51 | // user1.setAge(20); 52 | // user1.setVersion(1); 53 | // 54 | // User user2 = new User(); 55 | // user2.setName("小明2"); 56 | // user2.setAge(21); 57 | // user2.setVersion(1); 58 | // List userList = new ArrayList<>(); 59 | // userList.add(user1); 60 | // userList.add(user2); 61 | // userService.saveBatch(userList); 62 | 63 | 64 | User user = new User(); 65 | user.setName("小明"); 66 | user.setAge(18); 67 | user.setVersion(1); 68 | userMapper.insert(user); 69 | } 70 | 71 | @GetMapping("/update") 72 | @ResponseBody 73 | public void updateUser() { 74 | User user = new User(); 75 | user.setId(1731552348470849545L); 76 | user.setName("小明-UPDATE"); 77 | userService.updateById(user); 78 | 79 | UpdateWrapper updateWrapper = new UpdateWrapper<>(); 80 | updateWrapper.eq("name","小明1"); 81 | User user1 = new User(); 82 | user1.setName("小明1-UPDATE"); 83 | userService.update(user1, updateWrapper); 84 | 85 | userMapper.update(updateWrapper); 86 | } 87 | 88 | @GetMapping("/saveOrUpdate") 89 | @ResponseBody 90 | public void saveOrUpdateUser() { 91 | // User user = new User(); 92 | // user.setName("小明-saveOrUpdate"); 93 | // userService.saveOrUpdate(user); 94 | // 95 | // User user1 = new User(); 96 | // user1.setId(1731552348470849551L); 97 | // user1.setName("小明2"); 98 | // userService.saveOrUpdate(user1); 99 | 100 | UpdateWrapper updateWrapper = new UpdateWrapper<>(); 101 | updateWrapper.eq("name","小明-saveOrUpdate"); 102 | User user1 = new User(); 103 | user1.setName("小明-saveOrUpdate1"); 104 | userService.saveOrUpdate(user1, updateWrapper); 105 | } 106 | 107 | @GetMapping("/remove") 108 | @ResponseBody 109 | public void remove() { 110 | QueryWrapper queryWrapper = new QueryWrapper<>(); 111 | queryWrapper.eq("name","小明-saveOrUpdate1"); 112 | userService.remove(queryWrapper); 113 | 114 | 115 | Map map = new HashMap<>(); 116 | map.put("name", "小明2"); 117 | userService.removeByMap(map); 118 | 119 | userMapper.delete(queryWrapper); 120 | } 121 | 122 | @GetMapping("/page") 123 | @ResponseBody 124 | public Object page() { 125 | // 创建Page对象,指定当前页和每页显示的数据条数 126 | Page page = new Page<>(1, 10); 127 | 128 | QueryWrapper queryWrapper = new QueryWrapper<>(); 129 | queryWrapper.like("name","%小明%"); 130 | page = userService.page(page, queryWrapper); 131 | 132 | // 获取总记录数 133 | long size = page.getSize(); 134 | long total = page.getTotal(); 135 | long current = page.getCurrent(); 136 | // 获取分页数据列表 137 | List list = page.getRecords(); 138 | 139 | JSONObject json = new JSONObject(); 140 | json.put("size", size); 141 | json.put("total", total); 142 | json.put("current", current); 143 | json.put("list", list); 144 | return json; 145 | } 146 | 147 | @GetMapping("/activeRecord") 148 | @ResponseBody 149 | public void activeRecord() { 150 | User user = new User(); 151 | user.setName("小明"); 152 | user.setAge(18); 153 | user.setVersion(1); 154 | user.insert(); 155 | 156 | List list = user.selectAll(); 157 | 158 | User user1 = new User(); 159 | user1.setId(1731552348470849545L); 160 | user1.setName("小明hhh"); 161 | user1.setAge(18); 162 | user1.setVersion(1); 163 | user1.updateById(); 164 | 165 | user1.deleteById(); 166 | user1.deleteById(1731552348470849545L); 167 | 168 | } 169 | 170 | @GetMapping("/allEq") 171 | @ResponseBody 172 | public void allEq() { 173 | Map params = new HashMap<>(); 174 | params.put("name", "小明"); 175 | params.put("age", null); 176 | 177 | QueryWrapper queryWrapper = new QueryWrapper<>(); 178 | queryWrapper.allEq(params, false); 179 | queryWrapper.eq("name", "小明"); 180 | 181 | userMapper.selectList(queryWrapper); 182 | 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | import java.util.Date; 9 | 10 | import com.baomidou.mybatisplus.extension.activerecord.Model; 11 | import lombok.Getter; 12 | import lombok.Setter; 13 | 14 | /** 15 | *

16 | * 17 | *

18 | * 19 | * @author pkq 20 | * @since 2023-12-14 04:47:34 21 | */ 22 | @Getter 23 | @Setter 24 | public class User extends Model implements Serializable { 25 | 26 | private static final long serialVersionUID = 1L; 27 | 28 | /** 29 | * 主键ID 30 | */ 31 | @TableId(value = "id", type = IdType.AUTO) 32 | private Long id; 33 | 34 | /** 35 | * 姓名 36 | */ 37 | private String name; 38 | 39 | /** 40 | * 年龄 41 | */ 42 | private Integer age; 43 | 44 | private Integer version; 45 | 46 | private Date createAt; 47 | 48 | private Date updateAt; 49 | } 50 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.mapper; 2 | 3 | import com.springboot.all.mybatisplus.entity.User; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | *

8 | * Mapper 接口 9 | *

10 | * 11 | * @author pkq 12 | * @since 2023-12-14 05:38:58 13 | */ 14 | public interface UserMapper extends BaseMapper { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/model/User.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.model; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | /** 8 | * @Author qcl 9 | * @Description 10 | * @Date 11:09 AM 12/4/2023 11 | */ 12 | @Builder 13 | @Data 14 | @TableName("`user`") 15 | public class User { 16 | @TableId(value = "id", type = IdType.AUTO) 17 | private Long id; 18 | 19 | @TableField(value = "name", condition = SqlCondition.LIKE) 20 | private String name; 21 | private Integer age; 22 | 23 | /** 24 | * 乐观锁 25 | */ 26 | @Version 27 | private Integer version; 28 | } 29 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/plugin/MybatisPlusTestPlugin.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.plugin; 2 | 3 | import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; 4 | import com.baomidou.mybatisplus.core.toolkit.PluginUtils; 5 | import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport; 6 | import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import net.sf.jsqlparser.expression.StringValue; 9 | import net.sf.jsqlparser.expression.operators.conditional.AndExpression; 10 | import net.sf.jsqlparser.expression.operators.relational.EqualsTo; 11 | import net.sf.jsqlparser.schema.Column; 12 | import net.sf.jsqlparser.statement.select.PlainSelect; 13 | import net.sf.jsqlparser.statement.select.Select; 14 | import net.sf.jsqlparser.statement.select.SelectBody; 15 | import org.apache.ibatis.executor.statement.StatementHandler; 16 | import org.apache.ibatis.mapping.MappedStatement; 17 | 18 | import java.sql.Connection; 19 | 20 | /** 21 | * @Created by qcl 22 | * @Date 2/22/2024 9:47 AM 23 | * @Description 测试插件 24 | */ 25 | @Slf4j 26 | public class MybatisPlusTestPlugin extends JsqlParserSupport implements InnerInterceptor { 27 | 28 | @Override 29 | public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { 30 | PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); 31 | MappedStatement ms = mpSh.mappedStatement(); 32 | if (InterceptorIgnoreHelper.willIgnoreTenantLine(ms.getId())) { 33 | return; 34 | } 35 | PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql(); 36 | mpBs.sql(parserMulti(mpBs.sql(), null)); 37 | } 38 | 39 | @Override 40 | protected void processSelect(Select select, int index, String sql, Object obj) { 41 | // 解析SQL 42 | SelectBody selectBody = select.getSelectBody(); 43 | PlainSelect plainSelect = (PlainSelect) selectBody; 44 | 45 | // 构建eq对象 46 | EqualsTo equalsTo = new EqualsTo(new Column("age"), new StringValue("22")); 47 | // 将原来的条件和新构建的条件合在一起 48 | AndExpression andExpression = new AndExpression(plainSelect.getWhere(), equalsTo); 49 | // 重新封装where条件 50 | plainSelect.setWhere(andExpression); 51 | 52 | log.info("sql ---> {}", plainSelect); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.service; 2 | 3 | import com.springboot.all.mybatisplus.entity.User; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | *

8 | * 服务类 9 | *

10 | * 11 | * @author pkq 12 | * @since 2023-12-14 05:38:58 13 | */ 14 | public interface UserService extends IService { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.springboot.all.mybatisplus.service.impl; 2 | 3 | import com.springboot.all.mybatisplus.entity.User; 4 | import com.springboot.all.mybatisplus.mapper.UserMapper; 5 | import com.springboot.all.mybatisplus.service.UserService; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | *

11 | * 服务实现类 12 | *

13 | * 14 | * @author pkq 15 | * @since 2023-12-14 05:38:58 16 | */ 17 | @Service 18 | public class UserServiceImpl extends ServiceImpl implements UserService { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/java/com/springboot/all/mybatisplus/test/UserTest.java: -------------------------------------------------------------------------------- 1 | //package com.springboot.all.mybatisplus.test; 2 | // 3 | //import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | //import com.springboot.all.mybatisplus.MyBatisPlusApp; 5 | //import com.springboot.all.mybatisplus.mapper.UserMapper; 6 | //import com.springboot.all.mybatisplus.model.User; 7 | //import lombok.extern.slf4j.Slf4j; 8 | //import org.junit.Test; 9 | //import org.junit.runner.RunWith; 10 | //import org.springframework.beans.factory.annotation.Autowired; 11 | //import org.springframework.boot.test.context.SpringBootTest; 12 | //import org.springframework.test.context.junit4.SpringRunner; 13 | //import org.springframework.util.Assert; 14 | // 15 | //import java.util.List; 16 | // 17 | ///** 18 | // * @Author qcl 19 | // * @Description 20 | // * @Date 12:11 PM 12/4/2023 21 | // */ 22 | //@Slf4j 23 | //@RunWith(SpringRunner.class) 24 | //@SpringBootTest(classes = { MyBatisPlusApp.class}) 25 | //public class UserTest { 26 | // 27 | // @Autowired 28 | // private UserMapper userMapper; 29 | // 30 | // @Test 31 | // public void selectListTest() { 32 | // // select all 33 | // List userList = userMapper.selectList(null); 34 | // Assert.isTrue(5 == userList.size(), "user list size 不等于 5"); 35 | // } 36 | // 37 | // @Test 38 | // public void selectByName() { 39 | // // select all 40 | // QueryWrapper queryWrapper = new QueryWrapper(); 41 | // queryWrapper.like("name", "x%"); 42 | // List userList = userMapper.selectList(queryWrapper); 43 | // userList.forEach(System.out::println); 44 | // //User(id=1731552348403740673, name=xiaohong2, age=22) 45 | // //User(id=1731552348403740674, name=xiaohong3, age=23) 46 | // //User(id=1731552348470849537, name=xiaohong4, age=24) 47 | // //User(id=1731552348470849538, name=xiaohong5, age=25) 48 | // //User(id=1731552348470849539, name=xiaohong6, age=26) 49 | // } 50 | // 51 | // @Test 52 | // public void selectByConditionName() { 53 | // // select all 54 | // QueryWrapper queryWrapper = new QueryWrapper<>(User.builder().name("x").build()); 55 | // List userList = userMapper.selectList(queryWrapper); 56 | // userList.forEach(System.out::println); 57 | // //User(id=1731552348403740673, name=xiaohong2, age=22) 58 | // //User(id=1731552348403740674, name=xiaohong3, age=23) 59 | // //User(id=1731552348470849537, name=xiaohong4, age=24) 60 | // //User(id=1731552348470849538, name=xiaohong5, age=25) 61 | // //User(id=1731552348470849539, name=xiaohong6, age=26) 62 | // } 63 | // 64 | // @Test 65 | // public void insertTest() { 66 | // // insert 67 | //// userMapper.insert(User.builder().name("xiaohong1").age(21).build()); 68 | //// userMapper.insert(User.builder().name("xiaohong2").age(22).build()); 69 | //// userMapper.insert(User.builder().name("xiaohong3").age(23).build()); 70 | //// userMapper.insert(User.builder().name("xiaohong4").age(24).build()); 71 | //// userMapper.insert(User.builder().name("xiaohong5").age(25).build()); 72 | // userMapper.insert(User.builder().name("xiaohong6").age(26).build()); 73 | // } 74 | // 75 | // @Test 76 | // public void updateTest() { 77 | // userMapper.updateById(User.builder().id(1731552348470849539L).name("hhhhh").version(1).build()); 78 | // userMapper.updateById(User.builder().id(1731552348470849539L).name("hhhhh").version(1).build()); 79 | // } 80 | // 81 | // @Test 82 | // public void deleteTest() { 83 | // // delete 84 | // userMapper.deleteById(User.builder().id(1731552348286300161L).build()); 85 | // } 86 | //} 87 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | type: com.alibaba.druid.pool.DruidDataSource 5 | driverClassName: com.mysql.cj.jdbc.Driver 6 | url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true 7 | username: root 8 | password: qcl123456 9 | 10 | mybatis: 11 | mapper-locations: 12 | - classpath:mapper/*.xml 13 | - classpath*:com/**/mapper/*.xml 14 | configuration: 15 | cache-enabled: true 16 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 17 | 18 | mybatis-plus: 19 | configuration: 20 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 21 | global-config: 22 | db-config: 23 | table-prefix: sys_ 24 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/resources/mappers/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /springboot-mybatis-plus/src/main/resources/templates/controller.java.vm: -------------------------------------------------------------------------------- 1 | package ${packageName}.controller; 2 | 3 | import ${packageName}.entity.${upperClassName}; 4 | import ${packageName}.service.${upperClassName}Service; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import java.util.List; 12 | 13 | 14 | @RestController 15 | @RequestMapping("/${lowerClassName}") 16 | public class ${upperClassName}Controller { 17 | 18 | @Autowired 19 | private ${upperClassName}Service ${lowerClassName}Service; 20 | 21 | @GetMapping("/all") 22 | @ResponseBody 23 | public List<${upperClassName}> get${upperClassName}List() { 24 | return ${lowerClassName}Service.get${upperClassName}Info(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /springboot-shiro/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springboot-shiro 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/ShiroApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/4/26 10:47 AM 10 | * @description ShiroApp 11 | */ 12 | @SpringBootApplication 13 | public class ShiroApplication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(ShiroApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/authentication/CustomRealm.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.authentication; 2 | 3 | import cn.hutool.system.UserInfo; 4 | import com.example.shiro.dao.User; 5 | import com.example.shiro.mock.UserMock; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.apache.shiro.authc.AuthenticationException; 8 | import org.apache.shiro.authc.AuthenticationToken; 9 | import org.apache.shiro.authc.SimpleAuthenticationInfo; 10 | import org.apache.shiro.authz.AuthorizationInfo; 11 | import org.apache.shiro.authz.SimpleAuthorizationInfo; 12 | import org.apache.shiro.realm.AuthorizingRealm; 13 | import org.apache.shiro.subject.PrincipalCollection; 14 | 15 | import java.util.HashSet; 16 | import java.util.Set; 17 | 18 | /** 19 | * @author qcl 20 | * @version 1.0 21 | * @date 2022/5/5 11:04 AM 22 | * @description 23 | */ 24 | public class CustomRealm extends AuthorizingRealm { 25 | 26 | @Override 27 | public boolean supports(AuthenticationToken token) { 28 | return token instanceof JwtToken; 29 | } 30 | 31 | /** 32 | * 授权模块,获取用户角色和权限 33 | * @param token token 34 | * @return AuthorizationInfo 权限信息 35 | */ 36 | @Override 37 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection token) { 38 | SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); 39 | String userId = JwtUtil.getUserId(token.toString()); 40 | if(userId == null) { 41 | return simpleAuthorizationInfo; 42 | } 43 | 44 | String userRole = UserMock.getRoleById(userId); 45 | Set role = new HashSet<>(); 46 | role.add(userRole); 47 | simpleAuthorizationInfo.setRoles(role); 48 | simpleAuthorizationInfo.setStringPermissions(role); 49 | return simpleAuthorizationInfo; 50 | } 51 | 52 | /** 53 | * 用户认证 54 | * 55 | * @param authenticationToken 身份认证 token 56 | * @return AuthenticationInfo 身份认证信息 57 | * @throws AuthenticationException 认证相关异常 58 | */ 59 | @Override 60 | protected SimpleAuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { 61 | String token = (String) authenticationToken.getCredentials(); 62 | String userId = JwtUtil.getUserId(token); 63 | if (StringUtils.isBlank(userId)) { 64 | throw new AuthenticationException("验证失败"); 65 | } 66 | 67 | String userRole = UserMock.getRoleById(userId); 68 | User userBean = new User(); 69 | userBean.setUserId(userId); 70 | userBean.setRole(userRole); 71 | if (!JwtUtil.verify(token, userBean)) { 72 | throw new AuthenticationException("token失效"); 73 | } 74 | return new SimpleAuthenticationInfo(token, token, "shiroJwtRealm"); 75 | } 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/authentication/JwtFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.authentication; 2 | 3 | import org.apache.shiro.authz.UnauthorizedException; 4 | import org.apache.shiro.util.AntPathMatcher; 5 | import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | /** 17 | * @author qcl 18 | * @version 1.0 19 | * @date 2022/5/5 10:49 AM 20 | * @description 21 | */ 22 | public class JwtFilter extends BasicHttpAuthenticationFilter { 23 | 24 | private Logger log = LoggerFactory.getLogger(this.getClass()); 25 | 26 | private static final String TOKEN = "Authorization"; 27 | 28 | private AntPathMatcher pathMatcher = new AntPathMatcher(); 29 | 30 | 31 | @Override 32 | protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException { 33 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 34 | 35 | // 这里大家可以处理白名单逻辑,这里就不实现了 36 | // if (match) { 37 | // return true; 38 | // } 39 | 40 | if (isLoginAttempt(request, response)) { 41 | return executeLogin(request, response); 42 | } 43 | 44 | log.error("未传token {}", httpServletRequest.getRequestURI()); 45 | return false; 46 | } 47 | 48 | @Override 49 | protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) { 50 | HttpServletRequest req = (HttpServletRequest) request; 51 | String token = req.getHeader(TOKEN); 52 | return token != null; 53 | } 54 | 55 | @Override 56 | protected boolean executeLogin(ServletRequest request, ServletResponse response) { 57 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 58 | String token = httpServletRequest.getHeader(TOKEN); 59 | JwtToken jwtToken = new JwtToken(token); 60 | try { 61 | getSubject(request, response).login(jwtToken); 62 | return true; 63 | } catch (Exception e) { 64 | request.setAttribute("fail", e.getMessage()); 65 | log.error("executeLogin {}", e.getMessage()); 66 | return false; 67 | } 68 | } 69 | 70 | /** 71 | * 对跨域提供支持(注意生产) 72 | */ 73 | @Override 74 | protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { 75 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 76 | HttpServletResponse httpServletResponse = (HttpServletResponse) response; 77 | httpServletResponse.setHeader("Access-control-Allow-Origin", "*"); 78 | httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS"); 79 | httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers")); 80 | if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { 81 | httpServletResponse.setStatus(HttpStatus.OK.value()); 82 | return false; 83 | } 84 | return super.preHandle(request, response); 85 | } 86 | } 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/authentication/JwtToken.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.authentication; 2 | 3 | import org.apache.shiro.authc.AuthenticationToken; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/5/5 10:56 AM 9 | * @description 10 | */ 11 | public class JwtToken implements AuthenticationToken { 12 | 13 | private static final long serialVersionUID = 1282057025599826155L; 14 | 15 | private String token; 16 | 17 | private String expireAt; 18 | 19 | public JwtToken(String token) { 20 | this.token = token; 21 | } 22 | 23 | public JwtToken(String token, String expireAt) { 24 | this.token = token; 25 | this.expireAt = expireAt; 26 | } 27 | 28 | @Override 29 | public Object getPrincipal() { 30 | return token; 31 | } 32 | 33 | @Override 34 | public Object getCredentials() { 35 | return token; 36 | } 37 | 38 | public String getToken() { 39 | return token; 40 | } 41 | 42 | public void setToken(String token) { 43 | this.token = token; 44 | } 45 | 46 | public String getExpireAt() { 47 | return expireAt; 48 | } 49 | 50 | public void setExpireAt(String expireAt) { 51 | this.expireAt = expireAt; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/authentication/JwtUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.authentication; 2 | 3 | import com.auth0.jwt.JWT; 4 | import com.auth0.jwt.JWTVerifier; 5 | import com.auth0.jwt.algorithms.Algorithm; 6 | import com.auth0.jwt.exceptions.JWTDecodeException; 7 | import com.auth0.jwt.interfaces.DecodedJWT; 8 | import com.example.shiro.dao.User; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.util.Date; 13 | 14 | /** 15 | * @author qcl 16 | * @version 1.0 17 | * @date 2022/5/5 10:57 AM 18 | * @description 19 | */ 20 | public class JwtUtil { 21 | 22 | private static Logger log = LoggerFactory.getLogger(JwtUtil.class); 23 | 24 | // 设置过期时间 25 | private static final long EXPIRE_TIME = 1000 * 72 * 36; 26 | 27 | // 设置秘钥 (这里推荐大家可以写入 yml配置文件里) 28 | private static final String Secret = "28ca017de15a57e206f0"; 29 | 30 | /** 31 | * 校验 token是否正确 32 | * 33 | * @param token 密钥 34 | * @return 是否正确 35 | */ 36 | public static boolean verify(String token, User user) { 37 | try { 38 | Algorithm algorithm = Algorithm.HMAC256(Secret); 39 | JWTVerifier verifier = JWT.require(algorithm) 40 | .withClaim("userId", user.getUserId()) 41 | .withClaim("roleId", user.getRole()) 42 | .build(); 43 | verifier.verify(token); 44 | log.info("token is valid"); 45 | return true; 46 | } catch (Exception e) { 47 | log.error("token is invalid{}", e.getMessage()); 48 | return false; 49 | } 50 | } 51 | 52 | /** 53 | * 从 token中获取用户id 54 | * 55 | * @return token中包含的用户id 56 | */ 57 | public static String getUserId(String token) { 58 | try { 59 | DecodedJWT jwt = JWT.decode(token); 60 | return jwt.getClaim("userId").asString(); 61 | } catch (JWTDecodeException e) { 62 | log.error("error:{}", e.getMessage()); 63 | return null; 64 | } 65 | } 66 | 67 | /** 68 | * 从 token中获取用户roleId 69 | * 70 | * @return token中包含的用户id 71 | */ 72 | public static Integer getRoleId(String token) { 73 | try { 74 | DecodedJWT jwt = JWT.decode(token); 75 | return jwt.getClaim("roleId").asInt(); 76 | } catch (JWTDecodeException e) { 77 | log.error("error:{}", e.getMessage()); 78 | return null; 79 | } 80 | } 81 | 82 | /** 83 | * 生成 token 84 | * 85 | * @param user 86 | * @return token 87 | */ 88 | public static String sign(User user) { 89 | try { 90 | Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); 91 | // 这里可以加入秘钥 92 | Algorithm algorithm = Algorithm.HMAC256(Secret); 93 | 94 | // 这里可以存放于jwt中的内容信息,最后可以通过解密拿到 95 | return JWT.create() 96 | .withClaim("userId", user.getUserId()) 97 | .withClaim("roleId", user.getRole()) 98 | .withExpiresAt(date) 99 | .sign(algorithm); 100 | } catch (Exception e) { 101 | log.error("error:{}", e); 102 | return null; 103 | } 104 | } 105 | } 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/authentication/ShiroConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.authentication; 2 | 3 | import com.example.shiro.authentication.CustomRealm; 4 | import com.example.shiro.config.ShiroSessionListener; 5 | import org.apache.shiro.mgt.SecurityManager; 6 | import org.apache.shiro.session.SessionListener; 7 | import org.apache.shiro.session.mgt.SessionManager; 8 | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 9 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 10 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 11 | import org.apache.shiro.web.servlet.SimpleCookie; 12 | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; 13 | import org.crazycake.shiro.RedisCacheManager; 14 | import org.crazycake.shiro.RedisManager; 15 | import org.crazycake.shiro.RedisSessionDAO; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | 22 | import javax.servlet.Filter; 23 | import java.util.ArrayList; 24 | import java.util.Collection; 25 | import java.util.LinkedHashMap; 26 | import java.util.Map; 27 | 28 | /** 29 | * @author qcl 30 | * @version 1.0 31 | * @date 2022/5/5 10:46 AM 32 | * @description 33 | */ 34 | @Configuration 35 | public class ShiroConfig { 36 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 37 | 38 | @Value("${spring.redis.host}") 39 | private String redisHost; 40 | 41 | @Value("${spring.redis.port}") 42 | private Integer redisPort; 43 | 44 | private static final Integer expireAt = 1800; 45 | 46 | private static final Integer timeout = 3000; 47 | 48 | @Value("${spring.redis.password}") 49 | private String redisPassword; 50 | 51 | @Bean 52 | public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { 53 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 54 | shiroFilterFactoryBean.setSecurityManager(securityManager); 55 | String prefix = "/api"; 56 | shiroFilterFactoryBean.setLoginUrl(prefix + "/notLogin"); 57 | shiroFilterFactoryBean.setUnauthorizedUrl(prefix + "/notRole"); 58 | 59 | Map filterChainDefinitionMap = new LinkedHashMap<>(); 60 | LinkedHashMap filters = new LinkedHashMap<>(); 61 | filters.put("jwt", new JwtFilter()); 62 | shiroFilterFactoryBean.setFilters(filters); 63 | 64 | // 所有请求都要经过 jwt过滤器 65 | filterChainDefinitionMap.put("/**", "jwt"); 66 | 67 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 68 | logger.warn("Shiro jwt 拦截器工厂类注入成功"); 69 | return shiroFilterFactoryBean; 70 | } 71 | 72 | @Bean 73 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { 74 | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 75 | authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 76 | return authorizationAttributeSourceAdvisor; 77 | } 78 | 79 | /** 80 | * 注入 securityManager 81 | */ 82 | @Bean 83 | public SecurityManager securityManager() { 84 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 85 | // 设置realm. 86 | securityManager.setRealm(customRealm()); 87 | 88 | // 设置缓存 89 | securityManager.setCacheManager(cacheManager()); 90 | 91 | // 设置会话 92 | securityManager.setSessionManager(sessionManager()); 93 | return securityManager; 94 | } 95 | 96 | /** 97 | * 自定义身份认证 realm; 98 | *

99 | * 必须写这个类,并加上 @Bean 注解,目的是注入 CustomRealm, 100 | * 否则会影响 CustomRealm类 中其他类的依赖注入 101 | */ 102 | @Bean 103 | public CustomRealm customRealm() { 104 | return new CustomRealm(); 105 | } 106 | 107 | 108 | /** 109 | * 加入redis缓存,避免重复从数据库获取数据 110 | */ 111 | public RedisManager redisManager() { 112 | RedisManager redisManager = new RedisManager(); 113 | redisManager.setHost(redisHost); 114 | redisManager.setPort(redisPort); 115 | redisManager.setPassword(redisPassword); 116 | redisManager.setExpire(expireAt); 117 | redisManager.setTimeout(timeout); 118 | return redisManager; 119 | } 120 | 121 | public RedisCacheManager cacheManager() { 122 | RedisCacheManager redisCacheManager = new RedisCacheManager(); 123 | redisCacheManager.setRedisManager(redisManager()); 124 | return redisCacheManager; 125 | } 126 | 127 | 128 | /** 129 | * session 会话管理 130 | */ 131 | @Bean 132 | public RedisSessionDAO sessionDAO() { 133 | RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); 134 | redisSessionDAO.setRedisManager(redisManager()); 135 | return redisSessionDAO; 136 | } 137 | 138 | @Bean 139 | public SimpleCookie sessionIdCookie(){ 140 | SimpleCookie cookie = new SimpleCookie("X-Token"); 141 | cookie.setMaxAge(-1); 142 | cookie.setPath("/"); 143 | cookie.setHttpOnly(false); 144 | return cookie; 145 | } 146 | 147 | @Bean 148 | public SessionManager sessionManager() { 149 | DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); 150 | sessionManager.setSessionIdCookie(sessionIdCookie()); 151 | sessionManager.setSessionIdCookieEnabled(true); 152 | Collection listeners = new ArrayList(); 153 | listeners.add(new ShiroSessionListener()); 154 | sessionManager.setSessionListeners(listeners); 155 | sessionManager.setSessionDAO(sessionDAO()); 156 | return sessionManager; 157 | } 158 | } 159 | 160 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/config/CustomRealm.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.config; 2 | 3 | import com.example.shiro.dao.User; 4 | import com.example.shiro.mock.UserMock; 5 | import org.apache.shiro.SecurityUtils; 6 | import org.apache.shiro.authc.*; 7 | import org.apache.shiro.authz.AuthorizationInfo; 8 | import org.apache.shiro.authz.SimpleAuthorizationInfo; 9 | import org.apache.shiro.realm.AuthorizingRealm; 10 | import org.apache.shiro.subject.PrincipalCollection; 11 | 12 | import java.util.HashSet; 13 | import java.util.Set; 14 | 15 | /** 16 | * @author qcl 17 | * @version 1.0 18 | * @date 2022/4/26 10:56 AM 19 | * @description 20 | */ 21 | public class CustomRealm extends AuthorizingRealm { 22 | 23 | /** 24 | * 登录认证 25 | */ 26 | @Override 27 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 28 | 29 | // 获取用户输入的用户名和密码 30 | String userName = (String) token.getPrincipal(); 31 | String password = new String((char[]) token.getCredentials()); 32 | 33 | System.out.println("用户" + userName + "认证-----ShiroRealm.doGetAuthenticationInfo"); 34 | 35 | // 通过用户名到数据库查询用户信息 36 | User user = UserMock.getUserByUsername(userName); 37 | 38 | if (user == null) { 39 | throw new UnknownAccountException("用户名或密码错误!"); 40 | } 41 | if (!password.equals(user.getPassword())) { 42 | throw new IncorrectCredentialsException("用户名或密码错误!"); 43 | } 44 | if (user.getState().equals("0")) { 45 | throw new LockedAccountException("账号已被锁定,请联系管理员!"); 46 | } 47 | SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName()); 48 | return info; 49 | } 50 | 51 | 52 | /** 53 | * 获取用户角色和权限 54 | */ 55 | @Override 56 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) { 57 | User user = (User) SecurityUtils.getSubject().getPrincipal(); 58 | String userName = user.getUsername(); 59 | SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); 60 | 61 | // 获取用户角色 62 | Set roleSet = new HashSet<>(); 63 | String role = UserMock.getRole(userName); 64 | roleSet.add(role); 65 | simpleAuthorizationInfo.setRoles(roleSet); 66 | 67 | // 获取用户权限 68 | String permission = UserMock.getPermission(userName); 69 | Set permissionSet = new HashSet(); 70 | permissionSet.add(permission); 71 | simpleAuthorizationInfo.setStringPermissions(permissionSet); 72 | return simpleAuthorizationInfo; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/config/ShiroConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.config; 2 | 3 | import cn.hutool.core.codec.Base64; 4 | import org.apache.shiro.mgt.SecurityManager; 5 | import org.apache.shiro.session.SessionListener; 6 | import org.apache.shiro.session.mgt.SessionManager; 7 | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 8 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 9 | import org.apache.shiro.web.mgt.CookieRememberMeManager; 10 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 11 | import org.apache.shiro.web.servlet.SimpleCookie; 12 | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; 13 | import org.crazycake.shiro.RedisCacheManager; 14 | import org.crazycake.shiro.RedisManager; 15 | import org.crazycake.shiro.RedisSessionDAO; 16 | import org.springframework.context.annotation.Bean; 17 | import org.springframework.context.annotation.Configuration; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collection; 21 | import java.util.LinkedHashMap; 22 | 23 | /** 24 | * @author qcl 25 | * @version 1.0 26 | * @date 2022/4/26 10:55 AM 27 | * @description 28 | */ 29 | @Configuration 30 | public class ShiroConfig { 31 | @Bean 32 | public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { 33 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 34 | // 设置securityManager 35 | shiroFilterFactoryBean.setSecurityManager((SecurityManager) securityManager); 36 | // 登录的url 37 | shiroFilterFactoryBean.setLoginUrl("/login"); 38 | // 登录成功后跳转的url 39 | shiroFilterFactoryBean.setSuccessUrl("/index"); 40 | // 未授权url 41 | shiroFilterFactoryBean.setUnauthorizedUrl("/403"); 42 | 43 | LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>(); 44 | 45 | // 定义filterChain,静态资源不拦截 46 | filterChainDefinitionMap.put("/css/**", "anon"); 47 | filterChainDefinitionMap.put("/js/**", "anon"); 48 | filterChainDefinitionMap.put("/fonts/**", "anon"); 49 | filterChainDefinitionMap.put("/img/**", "anon"); 50 | // druid数据源监控页面不拦截 51 | filterChainDefinitionMap.put("/druid/**", "anon"); 52 | // 配置退出过滤器,其中具体的退出代码Shiro已经替我们实现了 53 | filterChainDefinitionMap.put("/logout", "logout"); 54 | filterChainDefinitionMap.put("/", "anon"); 55 | // 除上以外所有url都必须认证通过才可以访问,未通过认证自动访问LoginUrl 56 | // filterChainDefinitionMap.put("/**", "authc"); 57 | filterChainDefinitionMap.put("/**", "user"); 58 | 59 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 60 | return shiroFilterFactoryBean; 61 | } 62 | 63 | @Bean 64 | public SecurityManager securityManager(){ 65 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 66 | securityManager.setRealm(shiroRealm()); 67 | securityManager.setRememberMeManager(rememberMeManager()); 68 | securityManager.setCacheManager(cacheManager()); 69 | securityManager.setSessionManager(sessionManager()); 70 | return securityManager; 71 | } 72 | 73 | /** 74 | * 自定义实现的Realm 75 | * @return 76 | */ 77 | @Bean 78 | public CustomRealm shiroRealm(){ 79 | CustomRealm shiroRealm = new CustomRealm(); 80 | return shiroRealm; 81 | } 82 | 83 | /** 84 | * cookie 85 | * @return 86 | */ 87 | public SimpleCookie rememberMeCookie() { 88 | // 设置cookie名称 89 | SimpleCookie cookie = new SimpleCookie("rememberMe"); 90 | // 单位为秒 91 | cookie.setMaxAge(86400); 92 | return cookie; 93 | } 94 | 95 | /** 96 | * cookie管理对象 97 | * @return 98 | */ 99 | public CookieRememberMeManager rememberMeManager() { 100 | CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); 101 | cookieRememberMeManager.setCookie(rememberMeCookie()); 102 | // cookie加密的密钥 103 | cookieRememberMeManager.setCipherKey(Base64.decode("uwandaljILlia458ad4")); 104 | return cookieRememberMeManager; 105 | } 106 | 107 | /** 108 | * 开启注解 109 | * @param securityManager 110 | * @return 111 | */ 112 | @Bean 113 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { 114 | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 115 | authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 116 | return authorizationAttributeSourceAdvisor; 117 | } 118 | 119 | public RedisManager redisManager() { 120 | RedisManager redisManager = new RedisManager(); 121 | return redisManager; 122 | } 123 | 124 | public RedisCacheManager cacheManager() { 125 | RedisCacheManager redisCacheManager = new RedisCacheManager(); 126 | redisCacheManager.setRedisManager(redisManager()); 127 | return redisCacheManager; 128 | } 129 | 130 | @Bean 131 | public RedisSessionDAO sessionDAO() { 132 | RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); 133 | redisSessionDAO.setRedisManager(redisManager()); 134 | return redisSessionDAO; 135 | } 136 | 137 | @Bean 138 | public SessionManager sessionManager() { 139 | DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); 140 | Collection listeners = new ArrayList(); 141 | listeners.add(new ShiroSessionListener()); 142 | sessionManager.setSessionListeners(listeners); 143 | sessionManager.setSessionDAO(sessionDAO()); 144 | return sessionManager; 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/config/ShiroSessionListener.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.config; 2 | 3 | import org.apache.shiro.session.Session; 4 | import org.apache.shiro.session.SessionListener; 5 | 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * @author qcl 10 | * @version 1.0 11 | * @date 2022/4/29 10:24 AM 12 | * @description 13 | */ 14 | public class ShiroSessionListener implements SessionListener { 15 | private final AtomicInteger sessionCount = new AtomicInteger(0); 16 | 17 | @Override 18 | public void onStart(Session session) { 19 | sessionCount.incrementAndGet(); 20 | } 21 | 22 | @Override 23 | public void onStop(Session session) { 24 | sessionCount.decrementAndGet(); 25 | } 26 | 27 | @Override 28 | public void onExpiration(Session session) { 29 | sessionCount.decrementAndGet(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/controller/ExceptionController.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.controller; 2 | 3 | import org.apache.shiro.authz.AuthorizationException; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | 7 | /** 8 | * @author qcl 9 | * @version 1.0 10 | * @date 2022/4/28 10:54 AM 11 | * @description 12 | */ 13 | @ControllerAdvice 14 | public class ExceptionController { 15 | @ExceptionHandler(value = AuthorizationException.class) 16 | public String handleAuthorizationException() { 17 | return "您当前没有权限访问~ 请联系管理员"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.controller; 2 | 3 | import com.example.shiro.dao.User; 4 | import com.example.shiro.dao.UserOnline; 5 | import org.apache.shiro.SecurityUtils; 6 | import org.apache.shiro.authz.annotation.RequiresPermissions; 7 | import org.apache.shiro.session.Session; 8 | import org.apache.shiro.session.mgt.eis.SessionDAO; 9 | import org.apache.shiro.subject.SimplePrincipalCollection; 10 | import org.apache.shiro.subject.support.DefaultSubjectContext; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.ui.Model; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.ResponseBody; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collection; 19 | import java.util.List; 20 | 21 | /** 22 | * @author qcl 23 | * @version 1.0 24 | * @date 2022/4/26 11:22 AM 25 | * @description 26 | */ 27 | @RestController 28 | public class IndexController { 29 | 30 | @Autowired 31 | private SessionDAO sessionDAO; 32 | 33 | @RequiresPermissions("p:user") 34 | @RequestMapping("/index") 35 | public String index(Model model) { 36 | // 登录成后,即可通过Subject获取登录的用户信息 37 | User user = (User) SecurityUtils.getSubject().getPrincipal(); 38 | model.addAttribute("user", user); 39 | return "index --->" + user.getUsername(); 40 | } 41 | 42 | @RequiresPermissions("p:admin") 43 | @RequestMapping("/userOnline/list") 44 | @ResponseBody 45 | public List list() { 46 | List list = new ArrayList<>(); 47 | Collection sessions = sessionDAO.getActiveSessions(); 48 | for (Session session : sessions) { 49 | UserOnline userOnline = new UserOnline(); 50 | User user = new User(); 51 | SimplePrincipalCollection principalCollection; 52 | if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) { 53 | continue; 54 | } else { 55 | principalCollection = (SimplePrincipalCollection) session 56 | .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); 57 | user = (User) principalCollection.getPrimaryPrincipal(); 58 | userOnline.setUsername(user.getUsername()); 59 | userOnline.setUserId(user.getId().toString()); 60 | } 61 | userOnline.setSessionId((String) session.getId()); 62 | userOnline.setHost(session.getHost()); 63 | userOnline.setStartTime(session.getStartTimestamp()); 64 | userOnline.setLastTime(session.getLastAccessTime()); 65 | Long timeout = session.getTimeout(); 66 | if (timeout == 0l) { 67 | userOnline.setStatus("离线"); 68 | } else { 69 | userOnline.setStatus("在线"); 70 | } 71 | userOnline.setTimeout(timeout); 72 | list.add(userOnline); 73 | } 74 | return list; 75 | } 76 | 77 | @RequiresPermissions("p:admin") 78 | @RequestMapping("/forceLogout") 79 | @ResponseBody 80 | public boolean forceLogout(String sessionId) { 81 | Session session = sessionDAO.readSession(sessionId); 82 | session.setTimeout(0); 83 | return true; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.controller; 2 | 3 | import com.example.shiro.dao.User; 4 | import org.apache.shiro.SecurityUtils; 5 | import org.apache.shiro.authc.*; 6 | import org.apache.shiro.subject.Subject; 7 | import org.springframework.ui.Model; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | /** 11 | * @author qcl 12 | * @version 1.0 13 | * @date 2022/4/26 10:53 AM 14 | * @description 15 | */ 16 | @RestController 17 | public class LoginController { 18 | @GetMapping("/login") 19 | public String login() { 20 | return "login"; 21 | } 22 | 23 | @PostMapping("/login") 24 | @ResponseBody 25 | public String login(String username, String password) { 26 | //UsernamePasswordToken token = new UsernamePasswordToken(username, password); 27 | // 获取Subject对象 28 | UsernamePasswordToken token = new UsernamePasswordToken(username, password, true); 29 | Subject subject = SecurityUtils.getSubject(); 30 | try { 31 | // 执行登录 32 | subject.login(token); 33 | return "ok"; 34 | } catch (UnknownAccountException e) { 35 | return e.getMessage(); 36 | } catch (IncorrectCredentialsException e) { 37 | return "IncorrectCredentialsException " + e.getMessage(); 38 | } catch (LockedAccountException e) { 39 | return "LockedAccountException " + e.getMessage(); 40 | } catch (AuthenticationException e) { 41 | return "认证失败!"; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/dao/User.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.dao; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/4/26 11:13 AM 9 | * @description 10 | */ 11 | @Data 12 | public class User { 13 | public Integer id; 14 | public String userId; 15 | public String username; 16 | public String password; 17 | public String role; 18 | public String state; 19 | public String permission; 20 | } 21 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/dao/UserOnline.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.dao; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | 8 | /** 9 | * @author qcl 10 | * @version 1.0 11 | * @date 2022/4/29 10:30 AM 12 | * @description 13 | */ 14 | @Data 15 | public class UserOnline implements Serializable { 16 | 17 | private static final long serialVersionUID = 3828664348416633856L; 18 | 19 | private String sessionId; 20 | 21 | private String userId; 22 | 23 | private String username; 24 | 25 | private String host; 26 | 27 | private String ip; 28 | 29 | private String status; 30 | 31 | private Date startTime; 32 | 33 | private Date lastTime; 34 | 35 | private Long timeout; 36 | } 37 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/java/com/example/shiro/mock/UserMock.java: -------------------------------------------------------------------------------- 1 | package com.example.shiro.mock; 2 | 3 | import com.example.shiro.dao.User; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/4/26 11:14 AM 9 | * @description 用户数据模拟 10 | */ 11 | public class UserMock { 12 | 13 | public static String getPassword(String username) { 14 | System.out.println("用户名: " + username); 15 | if(username.equals("admin")) { 16 | return "123"; 17 | }else { 18 | return "456"; 19 | } 20 | } 21 | 22 | public static String getRole(String username) { 23 | if(username.equals("admin")) { 24 | return "admin"; 25 | }else { 26 | return "user"; 27 | } 28 | } 29 | 30 | public static String getRoleById(String userId) { 31 | if(userId.equals("1")) { 32 | return "admin"; 33 | }else { 34 | return "user"; 35 | } 36 | } 37 | 38 | public static String getPermission(String username) { 39 | if(username.equals("admin")) { 40 | return "p:admin"; 41 | }else { 42 | return "P:user"; 43 | } 44 | } 45 | 46 | public static User getUserByUsername(String username) { 47 | User user = new User(); 48 | if(username.equals("admin")) { 49 | user.setUsername("admin"); 50 | user.setPassword("123"); 51 | user.setRole("admin"); 52 | }else { 53 | user.setUsername("admin1"); 54 | user.setPassword("456"); 55 | user.setRole("user"); 56 | } 57 | user.setState("1"); 58 | return user; 59 | } 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8878 # 设置应用端口,默认是8080 3 | tomcat: 4 | max-threads: 800 5 | uri-encoding: UTF-8 6 | servlet: 7 | context-path: /dev-api 8 | 9 | spring: 10 | application: 11 | name: app-shiro 12 | datasource: 13 | url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true 14 | username: root 15 | password: qcl123456 16 | redis: 17 | host: localhost # Redis服务器地址 18 | database: 1 # Redis数据库索引(默认为0) 19 | port: 6379 # Redis服务器连接端口 20 | password: # Redis服务器连接密码(默认为空) 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8888 # 设置应用端口,默认是8080 3 | tomcat: 4 | max-threads: 800 5 | uri-encoding: UTF-8 6 | servlet: 7 | context-path: /prod-api 8 | 9 | spring: 10 | application: 11 | name: app-shiro 12 | datasource: 13 | url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true 14 | username: xxx 15 | password: xxxxxxx 16 | redis: 17 | host: xxxxx # Redis服务器地址 18 | database: x # Redis数据库索引(默认为0) 19 | port: 6379 # Redis服务器连接端口 20 | password: xxxx # Redis服务器连接密码(默认为空) -------------------------------------------------------------------------------- /springboot-shiro/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | spring: 3 | profiles: 4 | active: @profile.active@ 5 | 6 | mybatis: 7 | mapper-locations: 8 | - classpath:mapper/*.xml 9 | configuration: 10 | cache-enabled: true 11 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /springboot-shiro/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ${APP_NAME} 11 | 12 | 13 | 14 | ${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log 15 | 30 16 | 17 | 18 | ${FILE_LOG_PATTERN} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /springboot-study/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springboot-study 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/Application.java: -------------------------------------------------------------------------------- 1 | package com.example.app; 2 | 3 | import com.example.app.config.AppConfig; 4 | import org.springframework.boot.Banner; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.transaction.annotation.EnableTransactionManagement; 9 | 10 | /** 11 | * @author qcl 12 | * @version 1.0 13 | * @date 2022/4/8 9:45 AM 14 | * @description 15 | */ 16 | @EnableTransactionManagement 17 | @EnableConfigurationProperties({AppConfig.class}) 18 | @SpringBootApplication 19 | public class Application { 20 | public static void main(String[] args) { 21 | SpringApplication app = new SpringApplication(Application.class); 22 | // 关闭 banner 23 | app.setBannerMode(Banner.Mode.OFF); 24 | app.run(args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/common/CommonPage.java: -------------------------------------------------------------------------------- 1 | package com.example.app.common; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import com.github.pagehelper.PageInfo; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author qcl 10 | * @version 1.0 11 | * @date 2022/4/18 11:08 AM 12 | * @description 13 | */ 14 | public class CommonPage { 15 | private Integer pageNum; 16 | private Integer pageSize; 17 | private Long total; 18 | private List list; 19 | 20 | /** 21 | * 将PageHelper分页后的list转为分页信息 22 | */ 23 | public static CommonPage restPage(List list) { 24 | CommonPage result = new CommonPage(); 25 | PageInfo pageInfo = new PageInfo(list); 26 | result.setPageNum(pageInfo.getPageNum()); 27 | result.setPageSize(pageInfo.getPageSize()); 28 | result.setTotal(pageInfo.getTotal()); 29 | result.setList(pageInfo.getList()); 30 | return result; 31 | } 32 | 33 | public static void setPageHelper(Integer pageNum, Integer pageSize) { 34 | if(pageNum == null || pageNum <= 0) { 35 | pageNum = 1; 36 | } 37 | 38 | if(pageSize == null || pageSize <= 0) { 39 | pageSize = 10; 40 | } 41 | 42 | if(pageSize >= 20) { 43 | pageSize = 20; 44 | } 45 | 46 | PageHelper.startPage(pageNum, pageSize); 47 | } 48 | 49 | public Integer getPageNum() { 50 | return pageNum; 51 | } 52 | 53 | public void setPageNum(Integer pageNum) { 54 | this.pageNum = pageNum; 55 | } 56 | 57 | public Integer getPageSize() { 58 | return pageSize; 59 | } 60 | 61 | public void setPageSize(Integer pageSize) { 62 | this.pageSize = pageSize; 63 | } 64 | 65 | public List getList() { 66 | return list; 67 | } 68 | 69 | public void setList(List list) { 70 | this.list = list; 71 | } 72 | 73 | public Long getTotal() { 74 | return total; 75 | } 76 | 77 | public void setTotal(Long total) { 78 | this.total = total; 79 | } 80 | } 81 | 82 | 83 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/component/App.java: -------------------------------------------------------------------------------- 1 | package com.example.app.component; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/4/8 10:59 AM 10 | * @description 11 | */ 12 | @Component 13 | public class App { 14 | 15 | @Value("${app.name}") 16 | private String name; 17 | 18 | @Value("${app.version}") 19 | private String version; 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | 26 | public String getVersion() { 27 | return version; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/component/RedisUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.app.component; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.core.StringRedisTemplate; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * @author qcl 11 | * @version 1.0 12 | * @date 2022/4/15 10:37 AM 13 | * @description 14 | */ 15 | @Component 16 | public class RedisUtil { 17 | 18 | @Autowired 19 | private StringRedisTemplate stringRedisTemplate; 20 | 21 | public void set(String key, String value) { 22 | stringRedisTemplate.opsForValue().set(key, value); 23 | } 24 | 25 | public String get(String key) { 26 | return stringRedisTemplate.opsForValue().get(key); 27 | } 28 | 29 | public boolean expire(String key, long expire) { 30 | return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS); 31 | } 32 | 33 | public void remove(String key) { 34 | stringRedisTemplate.delete(key); 35 | } 36 | 37 | public Long increment(String key, long delta) { 38 | return stringRedisTemplate.opsForValue().increment(key,delta); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/component/WebLogFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.app.component; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import cn.hutool.json.JSONUtil; 5 | import com.example.app.dto.WebLog; 6 | import org.aspectj.lang.JoinPoint; 7 | import org.aspectj.lang.ProceedingJoinPoint; 8 | import org.aspectj.lang.Signature; 9 | import org.aspectj.lang.annotation.*; 10 | import org.aspectj.lang.reflect.MethodSignature; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.core.annotation.Order; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.util.StringUtils; 16 | import org.springframework.web.bind.annotation.RequestBody; 17 | import org.springframework.web.bind.annotation.RequestParam; 18 | import org.springframework.web.context.request.RequestContextHolder; 19 | import org.springframework.web.context.request.ServletRequestAttributes; 20 | import cn.hutool.core.util.URLUtil; 21 | 22 | import javax.servlet.http.HttpServletRequest; 23 | import java.lang.reflect.Method; 24 | import java.lang.reflect.Parameter; 25 | import java.util.ArrayList; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | 30 | /** 31 | * @author qcl 32 | * @version 1.0 33 | * @date 2022/4/21 10:36 AM 34 | * @description 35 | */ 36 | @Aspect 37 | @Component 38 | @Order(1) 39 | public class WebLogFilter { 40 | private static final Logger LOGGER = LoggerFactory.getLogger(WebLogFilter.class); 41 | 42 | @Pointcut("execution(public * com.example.app.controller.*.*(..))") 43 | public void webLog() { 44 | } 45 | 46 | @Before("webLog()") 47 | public void doBefore(JoinPoint joinPoint) throws Throwable { 48 | } 49 | 50 | @AfterReturning(value = "webLog()", returning = "ret") 51 | public void doAfterReturning(Object ret) throws Throwable { 52 | } 53 | 54 | @Around("webLog()") 55 | public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { 56 | long startTime = System.currentTimeMillis(); 57 | //获取当前请求对象 58 | ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 59 | HttpServletRequest request = attributes.getRequest(); 60 | //记录请求信息 61 | WebLog webLog = new WebLog(); 62 | Object result = joinPoint.proceed(); 63 | Signature signature = joinPoint.getSignature(); 64 | MethodSignature methodSignature = (MethodSignature) signature; 65 | Method method = methodSignature.getMethod(); 66 | long endTime = System.currentTimeMillis(); 67 | String urlStr = request.getRequestURL().toString(); 68 | webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath())); 69 | webLog.setIp(getIp(request)); 70 | webLog.setMethod(request.getMethod()); 71 | webLog.setParams(getParameter(method, joinPoint.getArgs())); 72 | webLog.setResponse(result); 73 | webLog.setSpendTime((int) (endTime - startTime)); 74 | webLog.setStartTime(startTime); 75 | webLog.setUri(request.getRequestURI()); 76 | webLog.setUrl(request.getRequestURL().toString()); 77 | LOGGER.info("{}", JSONUtil.parse(webLog)); 78 | return result; 79 | } 80 | 81 | /** 82 | * 根据方法和传入的参数获取请求参数 83 | */ 84 | private Object getParameter(Method method, Object[] args) { 85 | List argList = new ArrayList<>(); 86 | Parameter[] parameters = method.getParameters(); 87 | for (int i = 0; i < parameters.length; i++) { 88 | //将RequestBody注解修饰的参数作为请求参数 89 | RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); 90 | if (requestBody != null) { 91 | argList.add(args[i]); 92 | } 93 | //将RequestParam注解修饰的参数作为请求参数 94 | RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); 95 | if (requestParam != null) { 96 | Map map = new HashMap<>(); 97 | String key = parameters[i].getName(); 98 | if (!StringUtils.isEmpty(requestParam.value())) { 99 | key = requestParam.value(); 100 | } 101 | map.put(key, args[i]); 102 | argList.add(map); 103 | } 104 | } 105 | if (argList.size() == 0) { 106 | return null; 107 | } else if (argList.size() == 1) { 108 | return argList.get(0); 109 | } else { 110 | return argList; 111 | } 112 | } 113 | 114 | public static String getIp(HttpServletRequest req){ 115 | String ip = req.getHeader("Origin"); 116 | if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 117 | ip = req.getHeader("x-forwarded-for"); 118 | } 119 | if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 120 | ip = req.getHeader("Proxy-Client-IP"); 121 | } 122 | if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 123 | ip = req.getHeader("X-Real-IP"); 124 | } 125 | if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 126 | ip = req.getRemoteAddr(); 127 | } 128 | if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ 129 | ip = "127.0.0.1"; 130 | } 131 | String[] ips = ip.split(","); 132 | LOGGER.info("抓取的ip为:{}",ips[0]); 133 | return ips[0].trim(); 134 | } 135 | } 136 | 137 | 138 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.app.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/4/8 10:34 AM 9 | * @description 10 | */ 11 | @ConfigurationProperties(prefix= "app") 12 | public class AppConfig { 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | 18 | public void setName(String name) { 19 | this.name = name; 20 | } 21 | 22 | public String getVersion() { 23 | return version; 24 | } 25 | 26 | public void setVersion(String version) { 27 | this.version = version; 28 | } 29 | 30 | private String name; 31 | 32 | private String version; 33 | } 34 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/config/GlobalCorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.app.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.cors.CorsConfiguration; 6 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 7 | import org.springframework.web.filter.CorsFilter; 8 | 9 | /** 10 | * @author qcl 11 | * @version 1.0 12 | * @date 2022/4/19 10:04 AM 13 | * @description 14 | */ 15 | @Configuration 16 | public class GlobalCorsConfig { 17 | 18 | /** 19 | * 允许跨域调用的过滤器 20 | */ 21 | @Bean 22 | public CorsFilter corsFilter() { 23 | CorsConfiguration config = new CorsConfiguration(); 24 | //允许白名单域名进行跨域调用 25 | config.addAllowedOrigin("*"); 26 | //允许跨越发送cookie 27 | config.setAllowCredentials(true); 28 | //放行全部原始头信息 29 | config.addAllowedHeader("*"); 30 | //允许所有请求方法跨域调用 31 | config.addAllowedMethod("*"); 32 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 33 | source.registerCorsConfiguration("/**", config); 34 | return new CorsFilter(source); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/config/MyBatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.app.config; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/4/13 10:43 AM 10 | * @description 11 | */ 12 | @Configuration 13 | @MapperScan({"com.example.app.mapper"}) 14 | public class MyBatisConfig {} 15 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/config/ThreadPoolConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.app.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 6 | 7 | /** 8 | * @author qcl 9 | * @version 1.0 10 | * @date 2022/4/8 11:17 AM 11 | * @description 12 | */ 13 | //@Configuration 14 | //public class ThreadPoolConfig { 15 | // 16 | // @Bean(name = "threadPoolTaskExecutor") 17 | // public ThreadPoolTaskExecutor threadPoolTaskExecutor() { 18 | // ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 19 | // executor.setCorePoolSize(4); 20 | // executor.setMaxPoolSize(16); 21 | // executor.setQueueCapacity(80); 22 | // executor.setKeepAliveSeconds(120); 23 | // executor.setThreadNamePrefix("thread-pool-"); 24 | // return executor; 25 | // } 26 | //} 27 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/controller/ExceptionController.java: -------------------------------------------------------------------------------- 1 | package com.example.app.controller; 2 | 3 | import org.springframework.web.bind.annotation.ExceptionHandler; 4 | import org.springframework.web.bind.annotation.ResponseBody; 5 | import org.springframework.web.bind.annotation.RestControllerAdvice; 6 | 7 | /** 8 | * @author qcl 9 | * @version 1.0 10 | * @date 2022/4/11 2:40 PM 11 | * @description 12 | */ 13 | @RestControllerAdvice 14 | public class ExceptionController { 15 | @ExceptionHandler(Exception.class) 16 | @ResponseBody 17 | public String error(Exception e) { 18 | return e.getMessage(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.example.app.controller; 2 | 3 | import com.example.app.config.AppConfig; 4 | import com.example.app.dto.Post; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.beans.factory.annotation.Qualifier; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | 15 | /** 16 | * @author qcl 17 | * @version 1.0 18 | * @date 2022/4/8 9:48 AM 19 | * @description 20 | */ 21 | @RestController 22 | @RequestMapping("/v1") 23 | public class HelloController { 24 | private static final Logger logger = LoggerFactory.getLogger(HelloController.class); 25 | 26 | @Value("${app.name}") 27 | private String name; 28 | 29 | @Value("${app.version}") 30 | private String version; 31 | 32 | @Autowired 33 | private AppConfig appConfig; 34 | 35 | @Autowired 36 | @Qualifier("Hello1ServiceImpl") 37 | private com.example.app.service.HelloService HelloService; 38 | 39 | @RequestMapping("/hello") 40 | public String hello(){ 41 | logger.info("hello"); 42 | return "Hello World!" + name + version; 43 | } 44 | 45 | @RequestMapping("/hello1") 46 | public String hello1(){ 47 | return "Hello World!" + appConfig.getName() + appConfig.getVersion(); 48 | } 49 | 50 | @RequestMapping("/hello2") 51 | public String hello2(){ 52 | HelloService.hello(); 53 | return "Hello World!"; 54 | } 55 | 56 | @RequestMapping(value = "/hello3", headers = {}, method = RequestMethod.GET) 57 | public String hello3(){ 58 | HelloService.hello(); 59 | return "Hello World!"; 60 | } 61 | 62 | @GetMapping("/hello4/{id}") 63 | public String hello4(@PathVariable String id){ 64 | return "Hello World!" + id; 65 | } 66 | 67 | @GetMapping("/hello5/user") 68 | public String hello5(@RequestParam String name){ 69 | return "Hello World!" + name; 70 | } 71 | 72 | @PostMapping("/hello6/create") 73 | public String hello6(@RequestBody String name){ 74 | return "Hello World!" + name; 75 | } 76 | 77 | @PostMapping("/post/create") 78 | public String create(@RequestBody Post req){ 79 | return "Hello World!" + req.getTitle(); 80 | } 81 | 82 | @PostMapping("/post/update") 83 | public String update(@RequestBody Post req){ 84 | return "Hello World!" + req.getContent(); 85 | } 86 | 87 | @GetMapping("/hello7") 88 | public String hello7(HttpServletRequest req){ 89 | return "Hello World!" + req.getHeader("Cookie"); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/controller/RedisController.java: -------------------------------------------------------------------------------- 1 | package com.example.app.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.core.StringRedisTemplate; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * @author qcl 13 | * @version 1.0 14 | * @date 2022/4/15 10:12 AM 15 | * @description 16 | */ 17 | @RequestMapping("/redis") 18 | @RestController 19 | public class RedisController { 20 | 21 | @Autowired 22 | private StringRedisTemplate stringRedisTemplate; 23 | 24 | @GetMapping("/set") 25 | public String setData() { 26 | String key = "data"; 27 | stringRedisTemplate.opsForValue().set(key, "dataVal"); 28 | return "success"; 29 | } 30 | 31 | @GetMapping("/expire") 32 | public String expireData() { 33 | String key = "data"; 34 | if(!stringRedisTemplate.expire(key, 10, TimeUnit.SECONDS)) { 35 | return "fail"; 36 | } 37 | return "success"; 38 | } 39 | 40 | @GetMapping("/del") 41 | public String deleteData() { 42 | String key = "data"; 43 | stringRedisTemplate.delete(key); 44 | return "success"; 45 | } 46 | 47 | @GetMapping("/increment") 48 | public Long incrementData() { 49 | String key = "data"; 50 | return stringRedisTemplate.opsForValue().increment(key,1); 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.example.app.controller; 2 | 3 | import com.example.app.common.CommonPage; 4 | import com.example.app.mapper.UserRoleMapper; 5 | import com.example.app.model.UserRole; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.transaction.annotation.Transactional; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author qcl 14 | * @version 1.0 15 | * @date 2022/4/13 11:06 AM 16 | * @description 17 | */ 18 | @RequestMapping("/user") 19 | @RestController 20 | public class UserController { 21 | 22 | @Autowired 23 | private UserRoleMapper userRoleMapper; 24 | 25 | @GetMapping("role/list") 26 | @ResponseBody 27 | public CommonPage getUserRole() { 28 | CommonPage.setPageHelper(1, 10); 29 | List list = userRoleMapper.getRoles(); 30 | return CommonPage.restPage(list); 31 | } 32 | 33 | @GetMapping("role") 34 | @ResponseBody 35 | public UserRole getUserRole(@RequestParam Integer id) { 36 | return userRoleMapper.getRole(id); 37 | } 38 | 39 | @GetMapping("role/update") 40 | @ResponseBody 41 | public String updateUserRole(@RequestParam Integer id) { 42 | if(userRoleMapper.updateRole(id) <= 0) { 43 | return "fail"; 44 | } 45 | 46 | return "success"; 47 | } 48 | 49 | @GetMapping("role/add") 50 | @ResponseBody 51 | public String addUserRole(@RequestParam String name) { 52 | if(userRoleMapper.addRole(name) <= 0) { 53 | return "fail"; 54 | } 55 | 56 | return "success"; 57 | } 58 | 59 | @Transactional(rollbackFor = Exception.class) 60 | @GetMapping("trans") 61 | @ResponseBody 62 | public String transUser(@RequestParam String name) throws Exception { 63 | userRoleMapper.addRole(name); 64 | if(name.equals("xiaohong")) { 65 | throw new Exception("trans error"); 66 | } 67 | 68 | userRoleMapper.updateRole(2); 69 | return "success"; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/controller/WebController.java: -------------------------------------------------------------------------------- 1 | package com.example.app.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | import java.util.HashMap; 7 | 8 | /** 9 | * @author qcl 10 | * @version 1.0 11 | * @date 2022/4/11 10:53 AM 12 | * @description 13 | */ 14 | @Controller 15 | public class WebController { 16 | 17 | @RequestMapping 18 | public String index(HashMap map) { 19 | map.put("data","我是数据data"); 20 | return "index"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/dto/Post.java: -------------------------------------------------------------------------------- 1 | package com.example.app.dto; 2 | 3 | /** 4 | * @author qcl 5 | * @version 1.0 6 | * @date 2022/4/11 2:15 PM 7 | * @description 8 | */ 9 | public class Post { 10 | 11 | private Integer id; 12 | 13 | private String title; 14 | 15 | public Integer getId() { 16 | return id; 17 | } 18 | 19 | public void setId(Integer id) { 20 | this.id = id; 21 | } 22 | 23 | public String getTitle() { 24 | return title; 25 | } 26 | 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | 31 | public String getContent() { 32 | return content; 33 | } 34 | 35 | public void setContent(String content) { 36 | this.content = content; 37 | } 38 | 39 | public String getCover() { 40 | return cover; 41 | } 42 | 43 | public void setCover(String cover) { 44 | this.cover = cover; 45 | } 46 | 47 | private String content; 48 | 49 | private String cover; 50 | } 51 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/dto/WebLog.java: -------------------------------------------------------------------------------- 1 | package com.example.app.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/4/21 10:38 AM 9 | * @description 10 | */ 11 | @Data 12 | public class WebLog { 13 | /** 14 | * 请求参数 15 | */ 16 | private Object params; 17 | 18 | /** 19 | * URI 20 | */ 21 | private String uri; 22 | 23 | /** 24 | * URL 25 | */ 26 | private String url; 27 | 28 | /** 29 | * 请求类型 30 | */ 31 | private String method; 32 | 33 | /** 34 | * 操作时间 35 | */ 36 | private Long startTime; 37 | 38 | /** 39 | * 消耗时间 40 | */ 41 | private Integer spendTime; 42 | 43 | /** 44 | * 根路径 45 | */ 46 | private String basePath; 47 | 48 | 49 | /** 50 | * 请求返回的结果 51 | */ 52 | private Object response; 53 | 54 | /** 55 | * IP地址 56 | */ 57 | private String ip; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/mapper/UserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.app.mapper; 2 | 3 | import com.example.app.model.UserRole; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author qcl 9 | * @version 1.0 10 | * @date 2022/4/13 10:54 AM 11 | * @description 12 | */ 13 | public interface UserRoleMapper { 14 | List getRoles(); 15 | 16 | UserRole getRole(Integer id); 17 | 18 | int updateRole(Integer id); 19 | 20 | int addRole(String userRole); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/model/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.example.app.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/4/13 10:57 AM 9 | * @description 10 | */ 11 | public class UserRole implements Serializable { 12 | private Integer id; 13 | 14 | public Integer getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Integer id) { 19 | this.id = id; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | public String getRoleName() { 31 | return roleName; 32 | } 33 | 34 | public void setRoleName(String roleName) { 35 | this.roleName = roleName; 36 | } 37 | 38 | private String name; 39 | 40 | private String roleName; 41 | } 42 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/service/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.example.app.service; 2 | 3 | /** 4 | * @author qcl 5 | * @version 1.0 6 | * @date 2022/4/8 11:04 AM 7 | * @description 8 | */ 9 | public interface HelloService { 10 | void hello(); 11 | } 12 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/service/impl/Hello1ServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.app.service.impl; 2 | 3 | import com.example.app.service.HelloService; 4 | import org.springframework.stereotype.Service; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/4/8 11:28 AM 10 | * @description 11 | */ 12 | @Service("Hello1ServiceImpl") 13 | public class Hello1ServiceImpl implements HelloService { 14 | @Override 15 | public void hello() { 16 | System.out.println("Hello1ServiceImpl"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /springboot-study/src/main/java/com/example/app/service/impl/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.app.service.impl; 2 | 3 | import com.example.app.service.HelloService; 4 | import org.springframework.stereotype.Service; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/4/8 11:05 AM 10 | * @description 11 | */ 12 | @Service 13 | public class HelloServiceImpl implements HelloService { 14 | @Override 15 | public void hello() { 16 | System.out.println("hello service"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /springboot-study/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8877 # 设置应用端口,默认是8080 3 | tomcat: 4 | max-threads: 800 5 | uri-encoding: UTF-8 6 | servlet: 7 | context-path: /api 8 | 9 | spring: 10 | application: 11 | name: app 12 | datasource: 13 | url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true 14 | username: root 15 | password: qcl123456 16 | redis: 17 | host: localhost # Redis服务器地址 18 | database: 1 # Redis数据库索引(默认为0) 19 | port: 6379 # Redis服务器连接端口 20 | password: # Redis服务器连接密码(默认为空) 21 | 22 | mybatis: 23 | mapper-locations: 24 | - classpath:mapper/*.xml 25 | configuration: 26 | cache-enabled: true 27 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 28 | 29 | app: 30 | name: ${spring.application.name} 31 | version: "1.0" 32 | 33 | 34 | -------------------------------------------------------------------------------- /springboot-study/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | _ooOoo_ 3 | o8888888o 4 | 88" . "88 5 | (| -_- |) 6 | O\ = /O 7 | ____/`---'\____ 8 | .' \\| |// `. 9 | / \\||| : |||// \ 10 | / _||||| -:- |||||- \ 11 | | | \\\ - /// | | 12 | | \_| ''\---/'' | | 13 | \ .-\__ `-` ___/-. / 14 | ___`. .' /--.--\ `. . __ 15 | ."" '< `.___\_<|>_/___.' >'"". 16 | | | : `- \`.;`\ _ /`;.`/ - ` : | | 17 | \ \ `-. \_ __\ /__ _/ .-` / / 18 | ======`-.____`-.___\_____/___.-`____.-'====== 19 | `=---=' 20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21 | 佛祖保佑 永无BUG 22 | 23 | 博客地址: https://www.qiucheng.top -------------------------------------------------------------------------------- /springboot-study/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ${APP_NAME} 11 | 12 | 13 | 14 | ${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log 15 | 30 16 | 17 | 18 | ${FILE_LOG_PATTERN} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /springboot-study/src/main/resources/mapper/UserRoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | update user_role set name = "普通用户123" where id=#{id} 45 | 46 | 47 | 48 | insert user_role (name) values (#{name}) 49 | 50 | 51 | -------------------------------------------------------------------------------- /springboot-study/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | Document 9 | 10 | 11 |

12 | 13 | -------------------------------------------------------------------------------- /springcloud-hystrix/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-hystrix 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | com.alibaba.cloud 23 | spring-cloud-starter-alibaba-nacos-discovery 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-starter-netflix-hystrix 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /springcloud-hystrix/src/main/java/com/cloud/hystrix/HystrixApplication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.hystrix; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/12 11:06 AM 10 | * @description 11 | */ 12 | @SpringCloudApplication 13 | public class HystrixApplication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(HystrixApplication.class, args); 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /springcloud-hystrix/src/main/java/com/cloud/hystrix/config/RestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | package com.cloud.hystrix.config; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.client.ClientHttpRequestFactory; 7 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | /** 11 | * @author qcl 12 | * @version 1.0 13 | * @date 2022/5/11 9:43 AM 14 | * @description 15 | */ 16 | @Configuration 17 | public class RestTemplateConfig { 18 | 19 | @Bean 20 | @LoadBalanced // 这样可以使用服务对象调用 http://provicer/app/hello 21 | public RestTemplate restTemplate(ClientHttpRequestFactory factory) { 22 | return new RestTemplate(factory); 23 | } 24 | 25 | @Bean 26 | public ClientHttpRequestFactory clientHttpRequestFactory() { 27 | SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); 28 | factory.setReadTimeout(6000); 29 | factory.setConnectTimeout(3000); 30 | return factory; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /springcloud-hystrix/src/main/java/com/cloud/hystrix/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.hystrix.controller; 2 | 3 | import com.cloud.hystrix.model.User; 4 | import com.cloud.hystrix.service.UserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.ResponseBody; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * @author qcl 12 | * @version 1.0 13 | * @date 2022/5/11 9:44 AM 14 | * @description 15 | */ 16 | @RestController 17 | @RequestMapping("/hello") 18 | public class HelloController { 19 | 20 | @Autowired 21 | private UserService userService; 22 | 23 | /** 24 | * 服务容错测试 25 | * @return 26 | */ 27 | @RequestMapping("/hello/user/hyx") 28 | @ResponseBody 29 | public User hello2() { 30 | return userService.hello("HystrixCommand"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /springcloud-hystrix/src/main/java/com/cloud/hystrix/model/User.java: -------------------------------------------------------------------------------- 1 | package com.cloud.hystrix.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/5/11 9:46 AM 9 | * @description 10 | */ 11 | @Data 12 | public class User { 13 | private String username; 14 | } 15 | -------------------------------------------------------------------------------- /springcloud-hystrix/src/main/java/com/cloud/hystrix/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.cloud.hystrix.service; 2 | 3 | import com.cloud.hystrix.model.User; 4 | import com.example.consumer.model.vo.User; 5 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 6 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author qcl 16 | * @version 1.0 17 | * @date 2021/12/23 5:07 下午 18 | * @description 19 | */ 20 | 21 | @Service 22 | public class UserService { 23 | 24 | int num = 0; 25 | 26 | @Autowired 27 | private RestTemplate restTemplate; 28 | 29 | // 设置回调 - 请求错误时回调 30 | // 还可以对降级的服务进行分组 31 | @HystrixCommand(fallbackMethod = "getUserDefault", commandKey = "getUserById", groupKey = "userGroup", 32 | threadPoolKey = "getUserThread", 33 | 34 | // 熔断配置 35 | // https://mrbird.cc/Spring-Cloud-Hystrix-Circuit-Breaker.html 属性讲解 36 | commandProperties= { 37 | // 如果5秒内,请求达到了4个,错误率达到50%以上,就开启跳闸, 38 | // 就会直接走fallback,业务代码将不再会调用 39 | // 如果3秒以后再调用,会再执行一次业务方法 40 | @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "5000"), 41 | @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "4"), 42 | @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"), 43 | @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000"), 44 | 45 | // 不是很推荐 - 尽量使用单独的线程执行 46 | // 信号隔离设置 - 在主线程执行 47 | //只需要设置execution.isolation.strategy = SEMAPHORE即可 48 | // 并设置并发数 49 | // @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE"), 50 | // @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="10") 51 | } 52 | 53 | // 以上几个参数的含义是:5秒种以内,请求次数达到4个以上,失败率达到50%以上,则开启跳闸。跳闸3秒以后如果有请求过来不会继续跳闸, 54 | // 而是去实际做请求,如果请求失败,继续保持跳闸的状态,如果请求成功,则取消跳闸。 55 | ) 56 | // 开启缓存 如果对数据改变不大的 可以使用, 变化的数据不推荐使用 尽量使用redis 57 | // @CacheResult 58 | public User hello(String name) { 59 | Map params = new HashMap<>(); 60 | num ++; 61 | if (num > 4) { 62 | // 当num 大于4时 且 过了3秒 后恢复正常执行 63 | params.put("name", 0); 64 | }else { 65 | params.put("name", name); 66 | } 67 | User u = restTemplate.getForObject("http://provider/hello/app/{name}", User.class, params); 68 | 69 | 70 | System.out.println("执行方法" + num); 71 | return u; 72 | } 73 | 74 | // 如果该方法抛出错误 就会降级到 getUserDefault1 , 也可以通过 ignoreExceptions 去忽略某些异常 75 | @HystrixCommand(fallbackMethod = "getUserDefault1", ignoreExceptions = {NullPointerException.class}) 76 | public User getUserDefault(String name, Throwable e) { 77 | // 获取异常信息 78 | System.out.println(e.getMessage()); 79 | 80 | // 测试服务降级 - 该方法会错误 回调 getUserDefault1 81 | // String a = null; 82 | // a.toString(); 83 | 84 | User user = new User(); 85 | user.setUsername("defaultUser"); 86 | return user; 87 | } 88 | 89 | public User getUserDefault1(String name) { 90 | User user = new User(); 91 | user.setUsername("defaultUser 1"); 92 | return user; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /springcloud-hystrix/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10003 3 | 4 | spring: 5 | application: 6 | name: hystrix 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | namespace: '2ef2186e-078c-4904-8643-ff5e90555456' 14 | -------------------------------------------------------------------------------- /springcloud-jaeger/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-jaeger 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | 28 | com.alibaba.cloud 29 | spring-cloud-starter-alibaba-nacos-discovery 30 | 31 | 32 | 33 | 34 | io.opentracing.contrib 35 | opentracing-spring-jaeger-cloud-starter 36 | 3.3.1 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /springcloud-jaeger/src/main/java/com/cloud/jaeger/JaegerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.jaeger; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/23 10:16 AM 10 | * @description 11 | */ 12 | @SpringCloudApplication 13 | public class JaegerApplication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(JaegerApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /springcloud-jaeger/src/main/java/com/cloud/jaeger/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.jaeger.controller; 2 | 3 | 4 | import org.springframework.web.bind.annotation.PathVariable; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | /** 10 | * @author qcl 11 | * @version 1.0 12 | * @date 2022/5/11 9:44 AM 13 | * @description 14 | */ 15 | @RestController 16 | @RequestMapping("/hello") 17 | public class HelloController { 18 | 19 | @RequestMapping("/hello/user/{id:\\d+}") 20 | @ResponseBody 21 | public String hello(@PathVariable String id) { 22 | return id; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /springcloud-jaeger/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8085 3 | 4 | spring: 5 | application: 6 | name: jaeger 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | 14 | # jaeger ui: localhost:16681/search 15 | opentracing: 16 | jaeger: 17 | enabled: true 18 | log-spans: true 19 | const-sampler: 20 | decision: true 21 | udp-sender: 22 | host: localhost 23 | port: 6831 24 | 25 | 26 | -------------------------------------------------------------------------------- /springcloud-nacos/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-nacos 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | 28 | com.alibaba.cloud 29 | spring-cloud-starter-alibaba-nacos-discovery 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /springcloud-nacos/src/main/java/com/cloud/nacos/NacosAppication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.nacos; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/10 10:14 AM 10 | * @description 11 | */ 12 | @SpringCloudApplication 13 | public class NacosAppication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(NacosAppication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /springcloud-nacos/src/main/java/com/cloud/nacos/controller/ConfigController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.nacos.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.cloud.context.config.annotation.RefreshScope; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * @author qcl 10 | * @version 1.0 11 | * @date 2022/5/10 10:36 AM 12 | * @description 13 | */ 14 | @RestController 15 | @RefreshScope 16 | public class ConfigController { 17 | @Value("${app:name}") 18 | private String appName; 19 | 20 | @GetMapping("/api/appInfo") 21 | public String appInfo() { 22 | return "appName: " + appName; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /springcloud-nacos/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8003 3 | 4 | spring: 5 | application: 6 | name: app-nacos 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | namespace: '2ef2186e-078c-4904-8643-ff5e90555456' 14 | prefix: febs 15 | group: g_nacos 16 | refresh: false -------------------------------------------------------------------------------- /springcloud-openfeign/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-openfeign 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | 28 | com.alibaba.cloud 29 | spring-cloud-starter-alibaba-nacos-discovery 30 | 31 | 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-openfeign 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /springcloud-openfeign/src/main/java/com/cloud/openfeign/OpenFeignApplicaiton.java: -------------------------------------------------------------------------------- 1 | package com.cloud.openfeign; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | import org.springframework.cloud.openfeign.EnableFeignClients; 6 | 7 | /** 8 | * @author qcl 9 | * @version 1.0 10 | * @date 2022/5/16 9:35 AM 11 | * @description 12 | */ 13 | @EnableFeignClients(basePackages = "com.cloud.openfeign.api") 14 | @SpringCloudApplication 15 | public class OpenFeignApplicaiton { 16 | public static void main(String[] args) { 17 | SpringApplication.run(OpenFeignApplicaiton.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /springcloud-openfeign/src/main/java/com/cloud/openfeign/api/OpenFeignService.java: -------------------------------------------------------------------------------- 1 | package com.cloud.openfeign.api; 2 | 3 | import com.cloud.openfeign.model.User; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | 8 | /** 9 | * @author qcl 10 | * @version 1.0 11 | * @date 2022/5/16 10:08 AM 12 | * @description 13 | */ 14 | @FeignClient(value = "provider") 15 | public interface OpenFeignService { 16 | 17 | @PostMapping("/openfeign/provider/order2") 18 | User getUser(@RequestBody User user); 19 | } 20 | -------------------------------------------------------------------------------- /springcloud-openfeign/src/main/java/com/cloud/openfeign/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.openfeign.controller; 2 | 3 | 4 | import com.cloud.openfeign.api.OpenFeignService; 5 | import com.cloud.openfeign.model.User; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | /** 13 | * @author qcl 14 | * @version 1.0 15 | * @date 2022/5/11 9:44 AM 16 | * @description 17 | */ 18 | @RestController 19 | @RequestMapping("/hello") 20 | public class HelloController { 21 | 22 | @Autowired 23 | OpenFeignService openFeignService; 24 | 25 | @RequestMapping("/hello/user/{id:\\d+}") 26 | @ResponseBody 27 | public User hello(@PathVariable String id) { 28 | User user = new User(); 29 | user.setUsername(id); 30 | return openFeignService.getUser(user); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /springcloud-openfeign/src/main/java/com/cloud/openfeign/model/User.java: -------------------------------------------------------------------------------- 1 | package com.cloud.openfeign.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/5/11 9:46 AM 9 | * @description 10 | */ 11 | @Data 12 | public class User { 13 | private String username; 14 | } 15 | -------------------------------------------------------------------------------- /springcloud-openfeign/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10002 3 | 4 | spring: 5 | application: 6 | name: consumer 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | namespace: '2ef2186e-078c-4904-8643-ff5e90555456' 14 | 15 | feign: 16 | client: 17 | config: 18 | #default 设置的全局超时时间 19 | default: 20 | connectTimeout: 5000 21 | readTimeout: 5000 22 | # 指定服务 23 | provider: 24 | connectTimeout: 30000 25 | readTimeout: 30000 26 | -------------------------------------------------------------------------------- /springcloud-rest-consumer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-rest-consumer 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | 28 | com.alibaba.cloud 29 | spring-cloud-starter-alibaba-nacos-discovery 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /springcloud-rest-consumer/src/main/java/com/cloud/rest/consumer/ConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.rest.consumer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/11 9:34 AM 10 | * @description 11 | */ 12 | @SpringCloudApplication 13 | public class ConsumerApplication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(ConsumerApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /springcloud-rest-consumer/src/main/java/com/cloud/rest/consumer/config/RestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | package com.cloud.rest.consumer.config; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.client.ClientHttpRequestFactory; 7 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | /** 11 | * @author qcl 12 | * @version 1.0 13 | * @date 2022/5/11 9:43 AM 14 | * @description 15 | */ 16 | @Configuration 17 | public class RestTemplateConfig { 18 | 19 | @Bean 20 | @LoadBalanced // 这样可以使用服务对象调用 http://provicer/app/hello 21 | public RestTemplate restTemplate(ClientHttpRequestFactory factory) { 22 | return new RestTemplate(factory); 23 | } 24 | 25 | @Bean 26 | public ClientHttpRequestFactory clientHttpRequestFactory() { 27 | SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); 28 | factory.setReadTimeout(6000); 29 | factory.setConnectTimeout(3000); 30 | return factory; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /springcloud-rest-consumer/src/main/java/com/cloud/rest/consumer/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.rest.consumer.controller; 2 | 3 | import com.cloud.rest.consumer.model.User; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.cloud.client.ServiceInstance; 6 | import org.springframework.cloud.client.discovery.DiscoveryClient; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; 8 | import org.springframework.web.bind.annotation.*; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | import java.net.URI; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * @author qcl 18 | * @version 1.0 19 | * @date 2022/5/11 9:44 AM 20 | * @description 21 | */ 22 | @RestController 23 | @RequestMapping("/hello") 24 | public class HelloController { 25 | 26 | @Autowired 27 | private DiscoveryClient discoveryClient; 28 | 29 | @Autowired 30 | private RestTemplate restTemplate; 31 | 32 | @Autowired 33 | private LoadBalancerClient loadBalancerClient; 34 | 35 | @GetMapping("/discoverSvrInfo") 36 | @ResponseBody 37 | public URI getSvrUrl() throws Exception { 38 | // 如果是多个服务提供者 39 | ServiceInstance serviceInstance; 40 | if(true) { 41 | List services = discoveryClient.getInstances("provider"); 42 | serviceInstance = services.size() > 0 ? services.get(0) : null; 43 | }else { 44 | serviceInstance = loadBalancerClient.choose("provider"); 45 | } 46 | 47 | // 发起调用 48 | // 1. 不同命名空间下 调用,会导致找不到实例 49 | if(serviceInstance == null) { 50 | throw new Exception("未获取到实例"); 51 | } 52 | 53 | return serviceInstance.getUri(); 54 | } 55 | 56 | @RequestMapping("/hello/user/{id:\\d+}") 57 | @ResponseBody 58 | public User hello1(@PathVariable String id) { 59 | 60 | // restTemplate 61 | // GET 62 | // 1. getForEntity {name} 是站位 id是传值 63 | // 指定返回对象类型 64 | User u = restTemplate.getForEntity("http://provider/hello/app/{name}", User.class, id).getBody(); 65 | // { 66 | // "username": "hello java456" 67 | // } 68 | // id参数 也可以放在hashmap里 69 | Map params = new HashMap<>(); 70 | params.put("name", id); 71 | u = restTemplate.getForEntity("http://provider/hello/app/{name}", User.class, params).getBody(); 72 | 73 | 74 | // 2. getForObject 和1类似, 可以站位,和接收map参数, 区别在于返回的类型是 getBody内容 75 | u = restTemplate.getForObject("http://provider/hello/app/{name}", User.class, params); 76 | 77 | // post请求 主要有三种 postForObject postForEntity postForLocation 78 | Map us = new HashMap<>(); 79 | us.put("username", "java rest api -- "); 80 | us.put("username", us.get("username") + id); 81 | u = restTemplate.postForObject("http://provider/hello/app/post", us, User.class); 82 | 83 | // 其它 与上述类似 84 | // put r.put(...) delete r.delete(....) 85 | return u; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /springcloud-rest-consumer/src/main/java/com/cloud/rest/consumer/model/User.java: -------------------------------------------------------------------------------- 1 | package com.cloud.rest.consumer.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/5/11 9:46 AM 9 | * @description 10 | */ 11 | @Data 12 | public class User { 13 | private String username; 14 | } 15 | -------------------------------------------------------------------------------- /springcloud-rest-consumer/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10002 3 | 4 | spring: 5 | application: 6 | name: consumer 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | namespace: '2ef2186e-078c-4904-8643-ff5e90555456' 14 | -------------------------------------------------------------------------------- /springcloud-rest-producer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-rest-producer 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | 28 | com.alibaba.cloud 29 | spring-cloud-starter-alibaba-nacos-discovery 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /springcloud-rest-producer/src/main/java/com/cloud/rest/producer/ProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.rest.producer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/11 9:35 AM 10 | * @description 11 | */ 12 | @SpringCloudApplication 13 | public class ProducerApplication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(ProducerApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /springcloud-rest-producer/src/main/java/com/cloud/rest/producer/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.rest.producer.controller; 2 | 3 | import com.cloud.rest.producer.model.User; 4 | import org.springframework.web.bind.annotation.*; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/11 9:44 AM 10 | * @description 11 | */ 12 | @RestController 13 | @RequestMapping("/hello") 14 | public class HelloController { 15 | 16 | @GetMapping("/app/{id:\\d+}") 17 | @ResponseBody 18 | public String hello1(@PathVariable String id) { 19 | return "hello " + id; 20 | } 21 | 22 | @PostMapping("/app/post") 23 | @ResponseBody 24 | public User hello2(@RequestBody User u) { 25 | return u; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /springcloud-rest-producer/src/main/java/com/cloud/rest/producer/model/User.java: -------------------------------------------------------------------------------- 1 | package com.cloud.rest.producer.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/5/11 9:46 AM 9 | * @description 10 | */ 11 | @Data 12 | public class User { 13 | private String username; 14 | } 15 | -------------------------------------------------------------------------------- /springcloud-rest-producer/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10001 3 | 4 | spring: 5 | application: 6 | name: provider 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | namespace: '2ef2186e-078c-4904-8643-ff5e90555456' 14 | -------------------------------------------------------------------------------- /springcloud-ribbon/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-ribbon 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /springcloud-ribbon/src/main/java/com/cloud/ribbon/RibbonApplication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.ribbon; 2 | 3 | import org.springframework.cloud.client.SpringCloudApplication; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/5/13 11:25 AM 9 | * @description 10 | */ 11 | @SpringCloudApplication 12 | public class RibbonApplication { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /springcloud-ribbon/src/main/java/com/cloud/ribbon/config/RestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | package com.cloud.ribbon.config; 2 | 3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.client.ClientHttpRequestFactory; 7 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | /** 11 | * @author qcl 12 | * @version 1.0 13 | * @date 2022/5/11 9:43 AM 14 | * @description 15 | */ 16 | @Configuration 17 | public class RestTemplateConfig { 18 | 19 | @Bean 20 | @LoadBalanced // 这样可以使用服务对象调用 http://provicer/app/hello 21 | public RestTemplate restTemplate(ClientHttpRequestFactory factory) { 22 | return new RestTemplate(factory); 23 | } 24 | 25 | @Bean 26 | public ClientHttpRequestFactory clientHttpRequestFactory() { 27 | SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); 28 | factory.setReadTimeout(6000); 29 | factory.setConnectTimeout(3000); 30 | return factory; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /springcloud-ribbon/src/main/java/com/cloud/ribbon/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.ribbon.controller; 2 | 3 | 4 | import com.cloud.ribbon.model.User; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import org.springframework.web.client.RestTemplate; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author qcl 17 | * @version 1.0 18 | * @date 2022/5/11 9:44 AM 19 | * @description 20 | */ 21 | @RestController 22 | @RequestMapping("/hello") 23 | public class HelloController { 24 | @Autowired 25 | private RestTemplate restTemplate; 26 | 27 | @RequestMapping("/hello/user/{id:\\d+}") 28 | @ResponseBody 29 | public User hello1(@PathVariable String id) { 30 | 31 | Map us = new HashMap<>(); 32 | us.put("username", "java rest api -- "); 33 | us.put("username", us.get("username") + id); 34 | User u = restTemplate.postForObject("http://provider/hello/app/post", us, User.class); 35 | 36 | return u; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /springcloud-ribbon/src/main/java/com/cloud/ribbon/model/User.java: -------------------------------------------------------------------------------- 1 | package com.cloud.ribbon.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author qcl 7 | * @version 1.0 8 | * @date 2022/5/11 9:46 AM 9 | * @description 10 | */ 11 | @Data 12 | public class User { 13 | private String username; 14 | } 15 | -------------------------------------------------------------------------------- /springcloud-ribbon/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10005 3 | 4 | spring: 5 | application: 6 | name: ribbon 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | namespace: '2ef2186e-078c-4904-8643-ff5e90555456' 14 | 15 | 16 | ribbon: 17 | # restclient: 18 | # enabled: true # 开启重试机制 19 | #所有服务都使用随机策略 20 | NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule 21 | ConnectTimeout: 2 # 超时时间(ms) 22 | OkToRetryOnAllOperations: true # 所有请求在失败的时候都进行重试: 23 | MaxAutoRetriesNextServer: 1 # 实例的重试次数: 24 | listOfServers: localhost:18080 # 如果不和Eureka搭配使用的话,我们就需要手动指定服务清单给Ribbon: -------------------------------------------------------------------------------- /springcloud-sentinel/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-sentinel 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | 28 | com.alibaba.cloud 29 | spring-cloud-starter-alibaba-sentinel 30 | 31 | 32 | com.alibaba.csp 33 | sentinel-transport-simple-http 34 | 1.7.1 35 | 36 | 37 | 38 | com.alibaba.cloud 39 | spring-cloud-starter-alibaba-nacos-config 40 | 41 | 42 | 43 | com.alibaba.csp 44 | sentinel-datasource-nacos 45 | 1.7.1 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /springcloud-sentinel/src/main/java/com/cloud/sentinel/SentinelApplication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.sentinel; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/18 9:23 AM 10 | * @description 11 | */ 12 | @SpringBootApplication 13 | public class SentinelApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(SentinelApplication.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /springcloud-sentinel/src/main/java/com/cloud/sentinel/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.cloud.sentinel.controller; 2 | 3 | import com.cloud.sentinel.service.HelloService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | /** 9 | * @author qcl 10 | * @version 1.0 11 | * @date 2021/12/9 2:45 下午 12 | * @description 13 | */ 14 | @RestController 15 | public class TestController { 16 | 17 | @Autowired 18 | private HelloService hello; 19 | 20 | /** 21 | * 浏览器访问 用工具访问不起作用 22 | * sentinel控制台就会不戳到应用 23 | * @return 24 | */ 25 | @GetMapping("/test") 26 | public String test() throws InterruptedException { 27 | // TimeUnit.SECONDS.sleep(5); 28 | return "test" + hello.hello(); 29 | } 30 | 31 | @GetMapping("/hello") 32 | public String test1() throws InterruptedException { 33 | // TimeUnit.SECONDS.sleep(1); 34 | return "hello" + hello.hello(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /springcloud-sentinel/src/main/java/com/cloud/sentinel/service/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.cloud.sentinel.service; 2 | 3 | import com.alibaba.csp.sentinel.annotation.SentinelResource; 4 | import com.alibaba.csp.sentinel.slots.block.BlockException; 5 | import org.springframework.stereotype.Service; 6 | 7 | /** 8 | * @author qcl 9 | * @version 1.0 10 | * @date 2021/12/9 4:29 下午 11 | * @description 12 | */ 13 | @Service 14 | public class HelloService { 15 | @SentinelResource(value= "hello", fallback = "helloCallback", blockHandler = "helloCallback1") 16 | public String hello() { 17 | // try { 18 | // throw new Exception("报错了"); 19 | // } catch (Exception e) { 20 | // e.printStackTrace(); 21 | // } 22 | return "hello"; 23 | } 24 | 25 | // 异常回退 -- 触发异常 / (触发规则 如果没有helloCallback1则会回调到该方法) 26 | public String helloCallback(Throwable throwable) { 27 | return "这是异常回调 ---> " + throwable.getMessage(); 28 | } 29 | 30 | // sentinel回退 / 触发规则 31 | public String helloCallback1(BlockException e) { 32 | return "sentinel 回退 ---> " + e.getMessage(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /springcloud-sentinel/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8082 3 | 4 | spring: 5 | application: 6 | name: sentinel 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | 14 | # sentinel 15 | sentinel: 16 | transport: 17 | dashboard: localhost:8080 18 | port: 8719 19 | eager: true # 禁止控制台懒加载 20 | datasource: 21 | ds1: 22 | nacos: 23 | server-addr: localhost:8848 24 | dataId: sentinel 25 | groupId: DEFAULT_GROUP 26 | data-type: json 27 | rule-type: flow 28 | 29 | -------------------------------------------------------------------------------- /springcloud-zuul/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-all 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | springcloud-zuul 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-bootstrap 24 | 3.0.3 25 | 26 | 27 | com.alibaba.cloud 28 | spring-cloud-starter-alibaba-nacos-discovery 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-netflix-ribbon 34 | 35 | 36 | 37 | org.springframework.cloud 38 | spring-cloud-starter-netflix-hystrix 39 | 40 | 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-netflix-zuul 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /springcloud-zuul/src/main/java/com/cloud/zuul/ZuulApplication.java: -------------------------------------------------------------------------------- 1 | package com.cloud.zuul; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | 6 | /** 7 | * @author qcl 8 | * @version 1.0 9 | * @date 2022/5/19 9:15 AM 10 | * @description 11 | */ 12 | @SpringCloudApplication 13 | public class ZuulApplication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(ZuulApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /springcloud-zuul/src/main/java/com/cloud/zuul/filter/ErrorZuulFilter.java: -------------------------------------------------------------------------------- 1 | package com.cloud.zuul.filter; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.netflix.zuul.ZuulFilter; 5 | import com.netflix.zuul.context.RequestContext; 6 | import com.netflix.zuul.exception.ZuulException; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.util.ReflectionUtils; 11 | 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.PrintWriter; 14 | 15 | /** 16 | * @author qcl 17 | * @version 1.0 18 | * @date 2021/12/24 2:22 下午 19 | * @description error过滤器是在服务网关出现异常的时候起作用的 20 | */ 21 | @Component 22 | public class ErrorZuulFilter extends ZuulFilter { 23 | private final Logger log = LoggerFactory.getLogger(this.getClass()); 24 | 25 | @Override 26 | public String filterType() { 27 | return "error"; 28 | } 29 | 30 | @Override 31 | public int filterOrder() { 32 | //需要在默认的 SendErrorFilter 之前 33 | return 5; 34 | } 35 | 36 | @Override 37 | public boolean shouldFilter() { 38 | // 只有在抛出异常时才会进行拦截 39 | return RequestContext.getCurrentContext().containsKey("throwable"); 40 | } 41 | 42 | @Override 43 | public Object run() { 44 | try { 45 | RequestContext requestContext = RequestContext.getCurrentContext(); 46 | Object e = requestContext.get("throwable"); 47 | 48 | if (e instanceof ZuulException) { 49 | ZuulException zuulException = (ZuulException) e; 50 | // 删除该异常信息,不然在下一个过滤器中还会被执行处理 51 | requestContext.remove("throwable"); 52 | // 响应给客户端信息 53 | HttpServletResponse response = requestContext.getResponse(); 54 | response.setHeader("Content-type", "application/json;charset=UTF-8"); 55 | response.setCharacterEncoding("UTF-8"); 56 | PrintWriter pw = null; 57 | pw = response.getWriter(); 58 | pw.write(JSONObject.toJSONString("系统出现异常")); 59 | pw.close(); 60 | } 61 | } catch (Exception ex) { 62 | log.error("Exception filtering in custom error filter", ex); 63 | ReflectionUtils.rethrowRuntimeException(ex); 64 | } 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /springcloud-zuul/src/main/java/com/cloud/zuul/filter/PostZuulFilter.java: -------------------------------------------------------------------------------- 1 | package com.cloud.zuul.filter; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.netflix.zuul.ZuulFilter; 5 | import com.netflix.zuul.context.RequestContext; 6 | import com.netflix.zuul.exception.ZuulException; 7 | import org.apache.commons.io.IOUtils; 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import java.io.BufferedReader; 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | import java.util.Enumeration; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * @author qcl 24 | * @version 1.0 25 | * @date 2021/12/24 2:16 下午 26 | * @description post过滤器可以在请求转发后获取请求信息和响应入库,或者日志记录 27 | */ 28 | @Component 29 | public class PostZuulFilter extends ZuulFilter { 30 | private final Logger log = LoggerFactory.getLogger(this.getClass()); 31 | 32 | @Override 33 | public String filterType() { 34 | return "post"; 35 | } 36 | 37 | @Override 38 | public int filterOrder() { 39 | return 2; 40 | } 41 | 42 | @Override 43 | public boolean shouldFilter() { 44 | // 进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求来探测后续需要发起的跨域POST请求是否安全可接受 45 | // 所以这个请求就不需要拦截,下面是处理方式 46 | RequestContext requestContext = RequestContext.getCurrentContext(); 47 | HttpServletRequest request = requestContext.getRequest(); 48 | if (request.getMethod().equals(RequestMethod.OPTIONS.name())) { 49 | log.info("OPTIONS请求不做拦截操作"); 50 | return false; 51 | } 52 | // 如果前面的拦截器不进行路由,那么后面的过滤器就没必要执行 53 | if (!requestContext.sendZuulResponse()) { 54 | return false; 55 | } 56 | return true; 57 | } 58 | 59 | @Override 60 | public Object run() throws ZuulException { 61 | RequestContext requestContext = RequestContext.getCurrentContext(); 62 | InputStream stream = requestContext.getResponseDataStream(); 63 | if (stream == null) { 64 | return null; 65 | } 66 | 67 | HttpServletRequest request = requestContext.getRequest(); 68 | 69 | String requestParams = getRequestParams(requestContext, request); 70 | log.warn(requestParams); 71 | 72 | try { 73 | String responseBody = IOUtils.toString(stream); 74 | RequestContext.getCurrentContext().setResponseBody(responseBody); 75 | } catch (IOException e) { 76 | e.printStackTrace(); 77 | } 78 | return null; 79 | } 80 | 81 | //获取请求参数,适用于POST请求/GET请求,以及参数拼接在URL后面的POST请求 82 | private String getRequestParams(RequestContext requestContext, HttpServletRequest request) { 83 | String requestParams = null; 84 | String requestMethod = request.getMethod(); 85 | StringBuilder params = new StringBuilder(); 86 | Enumeration names = request.getParameterNames(); 87 | if (requestMethod.equals("GET")) { 88 | while (names.hasMoreElements()) { 89 | String name = (String) names.nextElement(); 90 | params.append(name); 91 | params.append("="); 92 | params.append(request.getParameter(name)); 93 | params.append("&"); 94 | } 95 | requestParams = params.delete(params.length() - 1, params.length()).toString(); 96 | } else { 97 | Map res = new HashMap<>(); 98 | Enumeration temp = request.getParameterNames(); 99 | if (null != temp) { 100 | while (temp.hasMoreElements()) { 101 | String en = (String) temp.nextElement(); 102 | String value = request.getParameter(en); 103 | res.put(en, value); 104 | } 105 | requestParams = JSON.toJSONString(res); 106 | } 107 | if (StringUtils.isBlank(requestParams) || "{}".equals(requestParams)) { 108 | BufferedReader br = null; 109 | StringBuilder sb = new StringBuilder(""); 110 | try { 111 | br = request.getReader(); 112 | String str; 113 | while ((str = br.readLine()) != null) { 114 | sb.append(str); 115 | } 116 | br.close(); 117 | } catch (IOException e) { 118 | e.printStackTrace(); 119 | } finally { 120 | if (null != br) { 121 | try { 122 | br.close(); 123 | } catch (IOException e) { 124 | e.printStackTrace(); 125 | } 126 | } 127 | } 128 | requestParams = sb.toString(); 129 | } 130 | } 131 | return requestParams; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /springcloud-zuul/src/main/java/com/cloud/zuul/filter/PreZuulFilter.java: -------------------------------------------------------------------------------- 1 | package com.cloud.zuul.filter; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.netflix.zuul.ZuulFilter; 5 | import com.netflix.zuul.context.RequestContext; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | 14 | /** 15 | * @author qcl 16 | * @version 1.0 17 | * @date 2021/12/24 11:24 上午 18 | * @description PRE过滤器用于将请求路径与配置的路由规则进行匹配,以找到需要转发的目标地址,并做一些前置加工,比如请求的校验等; 19 | */ 20 | @Component 21 | public class PreZuulFilter extends ZuulFilter { 22 | private final Logger log = LoggerFactory.getLogger(this.getClass()); 23 | 24 | /** 25 | * 对应Zuul生命周期的四个阶段:pre、post、route和error; 26 | * @return 27 | * 28 | * PRE:PRE过滤器用于将请求路径与配置的路由规则进行匹配,以找到需要转发的目标地址,并做一些前置加工,比如请求的校验等; 29 | * 30 | * ROUTING:ROUTING过滤器用于将外部请求转发到具体服务实例上去; 31 | * 32 | * POST:POST过滤器用于将微服务的响应信息返回到客户端,这个过程种可以对返回数据进行加工处理; 33 | * 34 | * ERROR:上述的过程发生异常后将调用ERROR过滤器。ERROR过滤器捕获到异常后需要将异常信息返回给客户端,所以最终还是会调用POST过滤器。 35 | */ 36 | @Override 37 | public String filterType() { 38 | return "pre"; 39 | } 40 | 41 | /** 42 | * 过滤器的优先级,数字越小,优先级越高; 43 | * @return 44 | */ 45 | @Override 46 | public int filterOrder() { 47 | return 1; 48 | } 49 | 50 | /** 51 | * 方法返回boolean类型,true时表示是否执行该过滤器的run方法,false则表示不执行; 52 | * @return 53 | */ 54 | @Override 55 | public boolean shouldFilter() { 56 | // 进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求来探测后续需要发起的跨域POST请求是否安全可接受 57 | // 所以这个请求就不需要拦截,下面是处理方式 58 | RequestContext requestContext = RequestContext.getCurrentContext(); 59 | HttpServletRequest request = requestContext.getRequest(); 60 | if (request.getMethod().equals(RequestMethod.OPTIONS.name())) { 61 | log.info("OPTIONS请求不做拦截操作"); 62 | return false; 63 | } 64 | return true; 65 | } 66 | 67 | /** 68 | * 过滤器的过滤逻辑 69 | * @return 70 | */ 71 | @Override 72 | public Object run() { 73 | RequestContext requestContext = RequestContext.getCurrentContext(); 74 | HttpServletRequest request = requestContext.getRequest(); 75 | String userToken = request.getHeader("apikey"); 76 | if (StringUtils.isBlank(userToken)) { 77 | log.warn("apikey为空"); 78 | sendError(requestContext, 99001, "请传输参数apikey", null); 79 | return null; 80 | } 81 | 82 | String host = request.getRemoteHost(); 83 | String method = request.getMethod(); 84 | String uri = request.getRequestURI(); 85 | log.info("请求URI:{},HTTP Method:{},请求IP:{}", uri, method, host); 86 | return null; 87 | } 88 | 89 | /** 90 | * 发送错误消息 91 | * todo: 如果是重定向到本地 还是会正常返回对应的api数据,状态码会变成返回的状态码 92 | * todo: 如果是转发到其它服务的, 会被拦截下来返回对应的错误信息 93 | * 94 | * @param requestContext 95 | * @param status 96 | * @param msg 97 | */ 98 | private void sendError(RequestContext requestContext, int status, String msg, String userToken) { 99 | requestContext.setSendZuulResponse(false); //不对请求进行路由 100 | requestContext.setResponseStatusCode(status);//设置返回状态码 101 | requestContext.setResponseBody(JSONObject.toJSONString(msg));//设置返回响应体 102 | requestContext.getResponse().setContentType("application/json;charset=UTF-8");//设置返回响应体格式,可能会乱码 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /springcloud-zuul/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8083 3 | 4 | spring: 5 | application: 6 | name: zuul 7 | cloud: 8 | # nacos 9 | nacos: 10 | config: 11 | server-addr: 127.0.0.1:8848 12 | file-extension: yml 13 | 14 | 15 | 16 | #zuul: 17 | # routes: 18 | # # 访问 http://localhost:8003/hello/app/1 转发-> http://localhost:18080/hello/app/1 19 | # hello: 20 | # path: /** 21 | # #url: http://localhost:18080 22 | # 23 | # # 加入注册中心后不需要url了 直接使用serviceID 24 | # serviceId: provider 25 | 26 | 27 | # 引入注册中心 还可以简化为 28 | zuul: 29 | # 关闭某个过滤器 具体过滤器解释: https://mrbird.cc/Spring-Cloud-Zuul-Router.html 30 | # SendResponseFilter: 31 | # post: 32 | # disable: true 33 | 34 | # 敏感请求头过滤 如果想关闭默认配置可以置为空 sensitive-headers: 35 | sensitive-headers: Cookie,Set-Cookie,Authorization 36 | 37 | # 路由重定向问题 38 | add-host-header: true 39 | 40 | # 添加前缀 41 | prefix: /gateway # http://localhost:8003/gateway/provider/hello/app/1 -> http://localhost:18080/hello/app/1 42 | 43 | # 关闭默认配置 44 | ignored-services: provider # 再次访问 http://localhost:8003/provider/hello/app/1 -> 404 会使前缀失效 45 | routes: 46 | # 以服务名称作为请求前缀 http://localhost:8003/provider/hello/app/1 -> http://localhost:18080/hello/app/1 47 | provider: 48 | path: /** 49 | # 进行本地跳转 不会转发到 provider 服务 http://localhost:8003/gateway/ -> http://localhost:8003/hello/app 50 | #url: forward:/hello/app 51 | 52 | # 关闭某个路由下的头过滤 53 | sensitive-headers: 54 | 55 | 56 | # 默认的serviceId: provider 57 | 58 | # 相同路径下 优先级取决于谁在前 所以会先访问 provider下的, 如果服务不存在会报错 59 | # consumer: 60 | # path: /** -------------------------------------------------------------------------------- /wx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiuChengleiy/springboot-all/357a0ba55449047f629fb3b0179981cc9d6adb92/wx.jpg --------------------------------------------------------------------------------